diff --git a/bildPy/src/source.py b/bildPy/src/source.py index 9d694d9..0097b89 100644 --- a/bildPy/src/source.py +++ b/bildPy/src/source.py @@ -1,76 +1,163 @@ import cv2 import os import numpy as np +import pickle -# da wir in src sind , so können wir zu andrem ordner kommen +# --- KONFIGURATION --- +# Da wir in 'src' sind, greifen wir auf die übergeordneten Ordner zu RAW_DATA_PFAD = "../data_raw" MODEL_PFAD = "../models" -MODEL_FILE = os.path.join(MODEL_PFAD, "trained_lbph.yml") # yml für biometrische Data -NAMES_FILE = os.path.join(MODEL_PFAD, "names.pkl") # für mapping the ids from bio data to real person +# yml für biometrische Daten +MODEL_FILE = os.path.join(MODEL_PFAD, "trained_lbph.yml") +# Mapping der IDs aus den Bio-Daten zu echten Personennamen +NAMES_FILE = os.path.join(MODEL_PFAD, "names.pkl") -# gesicht detektor erstmal initializieren +# Gesicht-Detektor (Haar Cascade) initialisieren face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') - -#LBPH Recognizer initializieren +# LBPH Recognizer initialisieren recognizer = cv2.face.LBPHFaceRecognizer_create() -# dir hersteller + +# Hilfsfunktion: Erstellt Ordner, falls sie nicht existieren def create_directory_if_not_exists(directory): if not os.path.exists(directory): os.makedirs(directory) -# trainiert model + +# Funktion: Trainiert das Modell def train_model(): - print("\n-training is angefangen") + print("\n--- Training hat angefangen ---") faces = [] ids = [] names_map = {} current_id = 0 - -# überpruft ob data dir schon exestiert + # Überprüft, ob der Daten-Ordner existiert if not os.path.exists(RAW_DATA_PFAD): - print(f"Error: Directory '{RAW_DATA_PFAD}' nicht gefunden.") + print(f"Fehler: Verzeichnis '{RAW_DATA_PFAD}' nicht gefunden.") return - -# geht durch jede ordner in data raw (e.g., diddy, kirk, etc.) + # Geht durch jeden Ordner in data_raw (z.B. diddy, kirk, etc.) for person_name in os.listdir(RAW_DATA_PFAD): person_path = os.path.join(RAW_DATA_PFAD, person_name) - - -# verpasst (skip) alles was nicht ordner ist so wie store.ds oder sowas (.txt....) + # Überspringt alles, was kein Ordner ist (z.B. .DS_Store oder .txt Dateien) if not os.path.isdir(person_path): continue names_map[current_id] = person_name - print(f"Processing ID {current_id}: {person_name}") + print(f"Verarbeite ID {current_id}: {person_name}") - # geht durch jedes Bild in der Ordner jeder Person + # Geht durch jedes Bild im Ordner der jeweiligen Person for image_name in os.listdir(person_path): - - if image_name.startswith("."): continue # Skip unsichbare files die mit . starten + # Überspringt unsichtbare Dateien, die mit '.' starten + if image_name.startswith("."): + continue image_path = os.path.join(person_path, image_name) - # ladet das bild hoch dann convertiert zum Grayscale + # Lädt das Bild und konvertiert es in Graustufen (Grayscale) img = cv2.imread(image_path) - if img is None: continue + if img is None: + continue gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - - #detectiert gesichte + # Detektiert Gesichter im Bild faces_rects = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5) + for (x, y, w, h) in faces_rects: - # region von interest ist das gesicht selbst - roi = gray[y:y + w, x:x + h] + # Region of Interest (ROI) - das gefundene Gesicht ausschneiden + roi = gray[y:y + h, x:x + w] faces.append(roi) ids.append(current_id) current_id += 1 if len(faces) == 0: - print("No faces found. Please check your 'data_raw' folder.") - return \ No newline at end of file + print("Keine Gesichter gefunden. Bitte prüfe den 'data_raw' Ordner.") + return + + # Trainiert das LBPH Modell + print(f"\nTraining mit {len(faces)} Gesichtsproben...") + recognizer.train(faces, np.array(ids)) + + # Speichert das Modell und die Namensliste + create_directory_if_not_exists(MODEL_PFAD) + recognizer.write(MODEL_FILE) + with open(NAMES_FILE, 'wb') as f: + pickle.dump(names_map, f) + + print(f"Erfolg! Modell gespeichert unter: {MODEL_FILE}") + + +# Funktion: Erkennt Gesichter in Echtzeit (Webcam) +def recognize_faces(): + print("\n--- Gesichtserkennung gestartet ---") + + if not os.path.exists(MODEL_FILE) or not os.path.exists(NAMES_FILE): + print("Fehler: Modell nicht gefunden. Bitte zuerst Option 1 (Training) ausführen.") + return + + # Modell und Namen laden + recognizer.read(MODEL_FILE) + with open(NAMES_FILE, 'rb') as f: + names_map = pickle.load(f) + + cap = cv2.VideoCapture(0) + print("Drücke 'q', um das Fenster zu schließen.") + + while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + faces_rects = face_cascade.detectMultiScale(gray, 1.2, 5) + + for (x, y, w, h) in faces_rects: + roi_gray = gray[y:y + h, x:x + w] + id_, confidence = recognizer.predict(roi_gray) + + # Bei LBPH gilt: Niedrigerer Wert = Bessere Übereinstimmung + if confidence < 85: + name = names_map[id_] + conf_text = f"{round(100 - confidence)}%" + else: + name = "Unbekannt" + conf_text = f"{round(100 - confidence)}%" + + # Rechteck und Text zeichnen + color = (0, 255, 0) if name != "Unbekannt" else (0, 0, 255) + cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2) + cv2.putText(frame, name, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color, 2) + cv2.putText(frame, conf_text, (x, y + h + 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 0), 1) + + cv2.imshow("LBPH Gesichtserkennung Projekt", frame) + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cap.release() + cv2.destroyAllWindows() + + +# Hauptmenü Steuerung +if __name__ == "__main__": + while True: + print("\n=== KLASSENPROJEKT MENÜ ===") + print("1. Modell trainieren") + print("2. Erkennung starten (Webcam)") + print("3. Beenden") + + wahl = input("Wähle eine Option (1-3): ") + + if wahl == '1': + train_model() + elif wahl == '2': + recognize_faces() + elif wahl == '3': + print("Programm wird beendet.") + break + else: + print("Ungültige Eingabe.") \ No newline at end of file