import cv2 from pyzbar.pyzbar import decode import time import numpy as np from urllib.parse import urlparse, parse_qs, unquote from PIL import ImageFont, ImageDraw, Image import os import subprocess # Fenstergröße & Farben window_width, window_height = 1920, 1080 # Habegger Gold COLOR_GREEN = (0, 255, 0) COLOR_YELLOW = (0, 255, 255) COLOR_BACKGROUND = (45, 46, 47) # HTML-Farbe #2d2e2f COLOR_WHITE = (255, 255, 255) COLOR_GOLD = (131, 188, 214) # BGR für Habegger-Gold # Font & Logo FONT_PATH = os.path.join("fonts", "Tisa Sans Pro Regular.ttf" "") # Alternativ: Georgia.ttf, falls vorhanden FONT_SIZE = 48 font = ImageFont.truetype(FONT_PATH, FONT_SIZE) logo_path = "images/habegger_logo_goldbar_whitefont.png" # Logo mit sichtbarem Text logo_pil = Image.open(logo_path).convert("RGBA") logo_pil.thumbnail((300, 100)) logo_pil = Image.alpha_composite(Image.new("RGBA", logo_pil.size, (0, 0, 0, 0)), logo_pil) logo_img = np.array(logo_pil) logo_img = cv2.cvtColor(logo_img, cv2.COLOR_RGBA2BGRA) def draw_unicode_text(cv2_image, text, position, color=COLOR_WHITE): img_pil = Image.fromarray(cv2_image) draw = ImageDraw.Draw(img_pil) draw.text(position, text, font=font, fill=color) return np.array(img_pil) def parse_qr_data(data): try: parsed = urlparse(data) query = parse_qs(parsed.query) mail = query.get("mail", [""])[0] name = query.get("name", [""])[0] name = unquote(name, encoding="utf-8", errors="replace") name = (name.replace("鐼", "ö") .replace("ü", "ü") .replace("ä", "ä") .replace("Ö", "Ö") .replace("Ü", "Ü") .replace("Ãß", "ß")) if "@habegger.ch" in mail.lower() and name.strip(): return mail.strip(), name.strip() except: pass return None, None def start_game(mail, name): with open("last_user.txt", "w", encoding="utf-8-sig") as f: f.write(f"{mail}\n{name}") subprocess.run(["python", "loader_game.py"]) # Endlosschleife für den Scanner while True: detected_color = COLOR_GOLD detected_time = None cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # Rahmenfarbe wird später im Loop anhand der Zeit gesetzt last_display_text = "" start_timer = None game_started = False while True: success, frame = cap.read() if not success: break decoded_objects = decode(frame) # QR-Status zurücksetzen nach 5 Sek. if detected_time and time.time() - detected_time >= 5.0: detected_color = COLOR_GOLD frame_color = COLOR_GOLD if decoded_objects: detected_time = time.time() for obj in decoded_objects: points = obj.polygon if len(points) > 4: hull = cv2.convexHull(np.array([point for point in points], dtype=np.float32)) points = hull.reshape(-1, 2) for i in range(len(points)): pt1 = tuple(points[i]) pt2 = tuple(points[(i + 1) % len(points)]) cv2.line(frame, pt1, pt2, COLOR_GREEN, 3) data = obj.data.decode("utf-8") mail, name = parse_qr_data(data) if mail and name: detected_color = COLOR_GREEN last_display_text = f"Richtiger QR-Code: Hallo {name}" detected_time = time.time() start_timer = time.time() game_started = True last_mail = mail last_name = name else: detected_color = COLOR_YELLOW detected_time = time.time() last_display_text = "Bitte dein HAG Last-Thursday Code scannen." break if start_timer and time.time() - start_timer >= 5.0: cap.release() cv2.destroyAllWindows() start_game(last_mail, last_name) break display_frame = np.full((window_height, window_width, 3), COLOR_BACKGROUND, dtype=np.uint8) cam_h, cam_w = frame.shape[:2] x_offset = (window_width - cam_w) // 2 y_offset = (window_height - cam_h) // 2 display_frame[y_offset:y_offset+cam_h, x_offset:x_offset+cam_w] = frame display_frame = draw_unicode_text(display_frame, "Scanne deinen QR-Code um das Spiel zu starten.", (80, 100), COLOR_WHITE) if last_display_text: display_frame = draw_unicode_text(display_frame, last_display_text, (80, window_height - 100), COLOR_WHITE) # Kamera-Rahmen if detected_time and time.time() - detected_time < 5.0: current_color = detected_color else: current_color = COLOR_GOLD cv2.rectangle(display_frame, (x_offset, y_offset), (x_offset + cam_w, y_offset + cam_h), current_color, 6) # Logo oben rechts ohne Alpha-Blending-Probleme logo_pos = (window_width - logo_img.shape[1] - 40, 40) overlay = np.zeros_like(display_frame, dtype=np.uint8) overlay[logo_pos[1]:logo_pos[1]+logo_img.shape[0], logo_pos[0]:logo_pos[0]+logo_img.shape[1]] = logo_img[:, :, :3] mask = logo_img[:, :, 3] # alpha channel for c in range(3): display_frame[logo_pos[1]:logo_pos[1]+logo_img.shape[0], logo_pos[0]:logo_pos[0]+logo_img.shape[1], c] = ( logo_img[:, :, c] * (mask / 255.0) + display_frame[logo_pos[1]:logo_pos[1]+logo_img.shape[0], logo_pos[0]:logo_pos[0]+logo_img.shape[1], c] * (1.0 - mask / 255.0)).astype(np.uint8) cv2.namedWindow("QR Scanner", cv2.WINDOW_NORMAL) cv2.setWindowProperty("QR Scanner", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) cv2.imshow("QR Scanner", display_frame) key = cv2.waitKey(1) if key == 27 or key == ord('q'): cap.release() cv2.destroyAllWindows() exit()