Files
Habegger_loader_game/qr_scan_old.py
2025-09-22 19:18:01 +02:00

161 lines
6.1 KiB
Python

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()