Spaces:
Configuration error
Configuration error
| 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() | |