import gradio as gr import numpy as np from PIL import Image, ImageDraw, ImageFont from deepface import DeepFace # Instellingen voor "gewoon werken" DETECTOR = "retinaface" # nauwkeuriger dan 'opencv' TAU = 0.65 # onder deze confidence -> "Onzeker" ACTIONS = ["emotion"] def analyze_batch(files, tau=TAU, show_boxes=True): all_rows = [] visuals = [] for f in files: img = Image.open(f).convert("RGB") np_img = np.array(img) try: result = DeepFace.analyze( img_path=np_img, actions=ACTIONS, detector_backend=DETECTOR, enforce_detection=False # crash niet als er geen gezicht is ) except Exception as e: all_rows.append({"file": f.name, "error": str(e)}) visuals.append(img) continue # DeepFace kan 1 dict of list teruggeven results = result if isinstance(result, list) else [result] draw = ImageDraw.Draw(img.copy()) try: font = ImageFont.truetype("DejaVuSans.ttf", 16) except: font = None rows = [] for r in results: region = r.get("region") or {} x, y, w, h = region.get("x",0), region.get("y",0), region.get("w",0), region.get("h",0) emotions = r.get("emotion", {}) if not emotions or w==0 or h==0: continue # Sorteer op score (DeepFace geeft percentages 0..100) sorted_items = sorted(emotions.items(), key=lambda kv: kv[1], reverse=True) top_label, top_score = sorted_items[0][0], float(sorted_items[0][1]) / 100.0 final_label = top_label if top_score >= float(tau) else "Onzeker" rows.append({ "bbox": {"x": x, "y": y, "w": w, "h": h}, "top1": top_label, "confidence": round(top_score,3), "label": final_label, "top3": [ {"label": l, "conf": round(s/100.0,3)} for l, s in sorted_items[:3] ] }) if show_boxes and w>0 and h>0: draw.rectangle([x, y, x+w, y+h], outline=(0,255,0), width=3) txt = f"{final_label} {int(top_score*100)}%" tw, th = draw.textbbox((0,0), txt, font=font)[2:] draw.rectangle([x, y-(th+6), x+tw+8, y], fill=(0,255,0)) draw.text((x+4, y-(th+5)), txt, fill=(0,0,0), font=font) all_rows.append({ "file": f.name, "faces": rows, "note": "Geen gezichten gevonden." if not rows else f"Gezichten: {len(rows)}" }) visuals.append(img if not rows else draw.im) return visuals, all_rows with gr.Blocks(title="Simpel & Betrouwbaar: Emotieherkenning") as demo: gr.Markdown("## 😀 Emotieherkenning (serie foto’s)\n" "- **RetinaFace** detectie + alignment\n" "- Emoties: angry, disgust, fear, happy, sad, surprise, neutral\n" "- Drempel voor **'Onzeker'** om fouten te voorkomen\n" "> Let op: dit is een schatting van **gezichtsuitdrukking** (geen gemoedstoestand/intenties).") with gr.Row(): with gr.Column(scale=1): files = gr.File(label="Upload meerdere foto’s", file_count="multiple", type="filepath") tau = gr.Slider(0.5, 0.9, value=TAU, step=0.01, label="Drempel τ voor 'Onzeker'") show_boxes = gr.Checkbox(True, label="Toon kaders & labels") btn = gr.Button("Analyseer") with gr.Column(scale=1): gallery = gr.Gallery(label="Resultaat (met labels)").style(grid=2, height="auto") out_json = gr.JSON(label="Details (per foto en gezicht)") btn.click(analyze_batch, [files, tau, show_boxes], [gallery, out_json]) if __name__ == "__main__": demo.launch()