Marcel0123 commited on
Commit
f83a852
·
verified ·
1 Parent(s): 4f8044a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -3
app.py CHANGED
@@ -30,7 +30,7 @@ EN_TO_NL = {
30
 
31
  "surprise": "verrast",
32
  "surprised": "verrast",
33
- "supprised": "verrast", # veelvoorkomende typo
34
  "surprized": "verrast",
35
 
36
  "angry": "boos",
@@ -40,7 +40,7 @@ EN_TO_NL = {
40
 
41
  "fear": "angstig",
42
  "fearful": "angstig",
43
- "fearfull": "angstig", # veelvoorkomende typo
44
 
45
  "contempt": "minachting",
46
 
@@ -66,4 +66,167 @@ def visualize(image, det_res, fer_res):
66
  fer_type_str_nl = to_dutch_lower(FacialExpressionRecog.getDesc(fer_type))
67
 
68
  cv.rectangle(output, (bbox[0], bbox[1]), (bbox[0]+bbox[2], bbox[1]+bbox[3]), (0, 255, 0), 2)
69
- cv.putText(output, fer_type_str_nl, (_
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  "surprise": "verrast",
32
  "surprised": "verrast",
33
+ "supprised": "verrast", # typo
34
  "surprized": "verrast",
35
 
36
  "angry": "boos",
 
40
 
41
  "fear": "angstig",
42
  "fearful": "angstig",
43
+ "fearfull": "angstig", # typo
44
 
45
  "contempt": "minachting",
46
 
 
66
  fer_type_str_nl = to_dutch_lower(FacialExpressionRecog.getDesc(fer_type))
67
 
68
  cv.rectangle(output, (bbox[0], bbox[1]), (bbox[0]+bbox[2], bbox[1]+bbox[3]), (0, 255, 0), 2)
69
+ cv.putText(
70
+ output,
71
+ fer_type_str_nl,
72
+ (bbox[0], max(0, bbox[1] - 10)),
73
+ cv.FONT_HERSHEY_SIMPLEX,
74
+ 0.7,
75
+ (0, 0, 255),
76
+ 2,
77
+ cv.LINE_AA
78
+ )
79
+
80
+ landmarks = det[4:14].astype(np.int32).reshape((5, 2))
81
+ for idx, landmark in enumerate(landmarks):
82
+ cv.circle(output, landmark, 2, landmark_color[idx], 2)
83
+ return output
84
+
85
+ def summarize_emotions(fer_res):
86
+ """Maakt de grote groene NL-lowercase samenvatting."""
87
+ if not fer_res:
88
+ return "## **geen gezicht gedetecteerd**"
89
+ names_nl = [to_dutch_lower(FacialExpressionRecog.getDesc(x)) for x in fer_res]
90
+ counts = Counter(names_nl).most_common()
91
+ top = counts[0][0]
92
+ details = ", ".join([f"{name} ({n})" for name, n in counts])
93
+ return f"# **{top}**\n\n_Gedetecteerde emoties: {details}_"
94
+
95
+ # --- Staafdiagram tekenen met OpenCV (geen matplotlib nodig) ---
96
+ def draw_bar_chart_cv(stats: dict, width=640, height=320):
97
+ img = np.full((height, width, 3), 255, dtype=np.uint8)
98
+ cv.putText(img, "Live emotie-statistieken", (12, 28), cv.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 0), 2, cv.LINE_AA)
99
+ if not stats:
100
+ cv.putText(img, "Nog geen statistieken", (12, height//2), cv.FONT_HERSHEY_SIMPLEX, 0.9, (128, 128, 128), 2, cv.LINE_AA)
101
+ return cv.cvtColor(img, cv.COLOR_BGR2RGB)
102
+
103
+ left, right, top, bottom = 60, 20, 50, 40
104
+ plot_w = width - left - right
105
+ plot_h = height - top - bottom
106
+ origin = (left, height - bottom)
107
+
108
+ cv.line(img, origin, (left + plot_w, height - bottom), (0, 0, 0), 2) # x-as
109
+ cv.line(img, origin, (left, height - bottom - plot_h), (0, 0, 0), 2) # y-as
110
+
111
+ labels = list(stats.keys())
112
+ values = [stats[k] for k in labels]
113
+ max_val = max(values) if max(values) > 0 else 1
114
+
115
+ n = len(labels)
116
+ gap = 12
117
+ bar_w = max(10, int((plot_w - gap * (n + 1)) / max(1, n)))
118
+
119
+ for i, (lab, val) in enumerate(zip(labels, values)):
120
+ x1 = left + gap + i * (bar_w + gap)
121
+ x2 = x1 + bar_w
122
+ h_px = int((val / max_val) * (plot_h - 10))
123
+ y1 = height - bottom - h_px
124
+ y2 = height - bottom - 1
125
+ cv.rectangle(img, (x1, y1), (x2, y2), (0, 170, 60), -1) # groene balk
126
+ cv.putText(img, str(val), (x1 + 2, y1 - 6), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 90, 30), 1, cv.LINE_AA)
127
+
128
+ show_lab = lab if len(lab) <= 12 else lab[:11] + "…"
129
+ (tw, th), _ = cv.getTextSize(show_lab, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
130
+ tx = x1 + (bar_w - tw) // 2
131
+ ty = height - bottom + th + 12
132
+ cv.putText(img, show_lab, (tx, ty), cv.FONT_HERSHEY_SIMPLEX, 0.5, (40, 40, 40), 1, cv.LINE_AA)
133
+
134
+ return cv.cvtColor(img, cv.COLOR_BGR2RGB)
135
+
136
+ def process_image(input_image):
137
+ """Helper: run detectie en retourneer (output_img, fer_res as list[int])."""
138
+ image = cv.cvtColor(input_image, cv.COLOR_RGB2BGR)
139
+ h, w, _ = image.shape
140
+ detect_model.setInputSize([w, h])
141
+ dets = detect_model.infer(image)
142
+ if dets is None:
143
+ return cv.cvtColor(image, cv.COLOR_BGR2RGB), []
144
+ fer_res = [fer_model.infer(image, face_points[:-1])[0] for face_points in dets]
145
+ output = visualize(image, dets, fer_res)
146
+ return cv.cvtColor(output, cv.COLOR_BGR2RGB), fer_res
147
+
148
+ def detect_expression(input_image):
149
+ """Versie die WÉL statistieken bijwerkt (gebruik voor 'Verstuur')."""
150
+ output_img, fer_res = process_image(input_image)
151
+ emotion_md = summarize_emotions(fer_res)
152
+ # update stats in NL-lowercase
153
+ names_nl = [to_dutch_lower(FacialExpressionRecog.getDesc(x)) for x in fer_res]
154
+ for name in names_nl:
155
+ emotion_stats[name] += 1
156
+ stats_plot = draw_bar_chart_cv(emotion_stats)
157
+ return output_img, emotion_md, stats_plot
158
+
159
+ def detect_expression_no_stats(input_image):
160
+ """Versie die GEEN statistieken bijwerkt (gebruik voor gr.Examples & caching)."""
161
+ output_img, fer_res = process_image(input_image)
162
+ emotion_md = summarize_emotions(fer_res)
163
+ # géén stats update en ook géén stats_image teruggeven
164
+ return output_img, emotion_md
165
+
166
+ # Voorbeelden automatisch laden
167
+ IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".bmp", ".webp"}
168
+ EXAMPLES_DIR = Path("examples")
169
+ if EXAMPLES_DIR.exists() and EXAMPLES_DIR.is_dir():
170
+ example_paths = [str(p) for p in sorted(EXAMPLES_DIR.iterdir()) if Path(p).suffix.lower() in IMAGE_EXTS]
171
+ else:
172
+ example_paths = []
173
+ example_list = [[p] for p in example_paths]
174
+ CACHE_EXAMPLES = bool(example_list)
175
+
176
+ # CSS (groene emotietekst)
177
+ custom_css = """
178
+ #emotie-uitslag { color: #16a34a; }
179
+ #emotie-uitslag h1, #emotie-uitslag h2, #emotie-uitslag h3 { margin: 0.25rem 0; }
180
+ """
181
+
182
+ with gr.Blocks(css=custom_css) as demo:
183
+ gr.Markdown("## Herkenning van gezichtsuitdrukkingen (FER) met OpenCV DNN")
184
+ gr.Markdown("Detecteert gezichten en herkent gezichtsuitdrukkingen met YuNet + MobileFaceNet (ONNX).")
185
+
186
+ # Rij 1: Links upload/knoppen, Rechts output + emotie
187
+ with gr.Row():
188
+ with gr.Column():
189
+ input_image = gr.Image(type="numpy", label="Afbeelding uploaden")
190
+ with gr.Row():
191
+ submit_btn = gr.Button("Verstuur", variant="primary")
192
+ clear_btn = gr.Button("Wissen")
193
+ with gr.Column():
194
+ output_image = gr.Image(type="numpy", label="Resultaat gezichtsuitdrukking")
195
+ emotion_md = gr.Markdown("## **Nog geen resultaat**", elem_id="emotie-uitslag")
196
+
197
+ # Rij 2: Links mugshots (Examples), Rechts statistieken
198
+ with gr.Row():
199
+ with gr.Column():
200
+ gr.Markdown("**Voorbeelden (klik om te testen):**")
201
+ examples_component = gr.Examples(
202
+ examples=example_list,
203
+ inputs=input_image,
204
+ outputs=[output_image, emotion_md], # <- 2 outputs
205
+ fn=detect_expression_no_stats, # <- geeft 2 outputs terug
206
+ examples_per_page=20,
207
+ cache_examples=CACHE_EXAMPLES
208
+ )
209
+ with gr.Column():
210
+ stats_image = gr.Image(
211
+ label="Statistieken",
212
+ type="numpy",
213
+ value=draw_bar_chart_cv(emotion_stats) # start met lege/actuele chart
214
+ )
215
+
216
+ # Clear-helpers
217
+ def clear_all_on_new():
218
+ return None, "## **Nog geen resultaat**"
219
+
220
+ def clear_all_button():
221
+ # reset inputs/outputs; statistieken blijven behouden
222
+ return None, None, "## **Nog geen resultaat**", draw_bar_chart_cv(emotion_stats)
223
+
224
+ # Nieuwe upload wist output + emotietekst (grafiek blijft staan)
225
+ input_image.change(fn=clear_all_on_new, outputs=[output_image, emotion_md])
226
+ # Verwerken
227
+ submit_btn.click(fn=detect_expression, inputs=input_image, outputs=[output_image, emotion_md, stats_image])
228
+ # Wissen-knop: ook grafiek opnieuw tekenen (maar stats niet resetten)
229
+ clear_btn.click(fn=clear_all_button, outputs=[input_image, output_image, emotion_md, stats_image])
230
+
231
+ if __name__ == "__main__":
232
+ demo.launch()