File size: 3,943 Bytes
a690ed9
 
e0317f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a690ed9
 
e0317f8
 
 
 
a690ed9
e0317f8
 
a690ed9
e0317f8
a690ed9
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

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