Marcel0123 commited on
Commit
a432ed6
·
verified ·
1 Parent(s): 84d178b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -42
app.py CHANGED
@@ -18,47 +18,52 @@ target_id = cv.dnn.DNN_TARGET_CPU
18
  fer_model = FacialExpressionRecog(modelPath=FER_MODEL_PATH, backendId=backend_id, targetId=target_id)
19
  detect_model = YuNet(modelPath=FD_MODEL_PATH)
20
 
21
- # EN -> NL mapping
22
  EN_TO_NL = {
23
- "neutral": "Neutraal",
24
- "happy": "Blij",
25
- "sad": "Verdrietig",
26
- "surprise": "Verrast",
27
- "angry": "Boos",
28
- "anger": "Boos",
29
- "disgust": "Walging",
30
- "fear": "Bang",
31
- "contempt": "Minachting",
32
- "unknown": "Onbekend",
33
  }
34
 
35
- def to_dutch(label: str) -> str:
 
36
  if not label:
37
- return "Onbekend"
38
  key = label.strip().lower()
39
- return EN_TO_NL.get(key, label)
40
 
41
  # In-memory statistieken
42
  emotion_stats = defaultdict(int)
43
 
44
  def visualize(image, det_res, fer_res):
 
45
  output = image.copy()
46
  landmark_color = [(255, 0, 0), (0, 0, 255), (0, 255, 0), (255, 0, 255), (0, 255, 255)]
47
  for det, fer_type in zip(det_res, fer_res):
48
  bbox = det[0:4].astype(np.int32)
49
- fer_type_str_nl = to_dutch(FacialExpressionRecog.getDesc(fer_type))
 
50
  cv.rectangle(output, (bbox[0], bbox[1]), (bbox[0]+bbox[2], bbox[1]+bbox[3]), (0, 255, 0), 2)
51
  cv.putText(output, fer_type_str_nl, (bbox[0], max(0, bbox[1] - 10)),
52
  cv.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2, cv.LINE_AA)
 
53
  landmarks = det[4:14].astype(np.int32).reshape((5, 2))
54
  for idx, landmark in enumerate(landmarks):
55
  cv.circle(output, landmark, 2, landmark_color[idx], 2)
56
  return output
57
 
58
  def summarize_emotions(fer_res):
 
59
  if not fer_res:
60
- return "## **Geen gezicht gedetecteerd**"
61
- names_nl = [to_dutch(FacialExpressionRecog.getDesc(x)) for x in fer_res]
62
  counts = Counter(names_nl).most_common()
63
  top = counts[0][0]
64
  details = ", ".join([f"{name} ({n})" for name, n in counts])
@@ -77,8 +82,8 @@ def draw_bar_chart_cv(stats: dict, width=640, height=320):
77
  plot_h = height - top - bottom
78
  origin = (left, height - bottom)
79
 
80
- cv.line(img, origin, (left + plot_w, height - bottom), (0, 0, 0), 2)
81
- cv.line(img, origin, (left, height - bottom - plot_h), (0, 0, 0), 2)
82
 
83
  labels = list(stats.keys())
84
  values = [stats[k] for k in labels]
@@ -94,10 +99,10 @@ def draw_bar_chart_cv(stats: dict, width=640, height=320):
94
  h_px = int((val / max_val) * (plot_h - 10))
95
  y1 = height - bottom - h_px
96
  y2 = height - bottom - 1
97
- cv.rectangle(img, (x1, y1), (x2, y2), (0, 170, 60), -1)
98
  cv.putText(img, str(val), (x1 + 2, y1 - 6), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 90, 30), 1, cv.LINE_AA)
99
 
100
- show_lab = lab if len(lab) <= 10 else lab[:9] + "…"
101
  (tw, th), _ = cv.getTextSize(show_lab, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
102
  tx = x1 + (bar_w - tw) // 2
103
  ty = height - bottom + th + 12
@@ -106,7 +111,7 @@ def draw_bar_chart_cv(stats: dict, width=640, height=320):
106
  return cv.cvtColor(img, cv.COLOR_BGR2RGB)
107
 
108
  def process_image(input_image):
109
- """Helper: run detectie en retourneer (output_img, fer_res as list of ints)."""
110
  image = cv.cvtColor(input_image, cv.COLOR_RGB2BGR)
111
  h, w, _ = image.shape
112
  detect_model.setInputSize([w, h])
@@ -121,8 +126,8 @@ def detect_expression(input_image):
121
  """Versie die WÉL statistieken bijwerkt (gebruik voor 'Verstuur')."""
122
  output_img, fer_res = process_image(input_image)
123
  emotion_md = summarize_emotions(fer_res)
124
- # update stats alleen hier:
125
- names_nl = [to_dutch(FacialExpressionRecog.getDesc(x)) for x in fer_res]
126
  for name in names_nl:
127
  emotion_stats[name] += 1
128
  stats_plot = draw_bar_chart_cv(emotion_stats)
@@ -132,8 +137,7 @@ def detect_expression_no_stats(input_image):
132
  """Versie die GEEN statistieken bijwerkt (gebruik voor gr.Examples & caching)."""
133
  output_img, fer_res = process_image(input_image)
134
  emotion_md = summarize_emotions(fer_res)
135
- # géén update van emotion_stats
136
- stats_plot = draw_bar_chart_cv(emotion_stats) # toon huidige stand (kan leeg zijn)
137
  return output_img, emotion_md, stats_plot
138
 
139
  # Voorbeelden automatisch laden
@@ -153,9 +157,10 @@ custom_css = """
153
  """
154
 
155
  with gr.Blocks(css=custom_css) as demo:
156
- gr.Markdown("## Herkenning van gezichtsuitdrukkingen ")
157
- gr.Markdown("Detecteert gezichten en herkent gezichtsuitdrukkingen ")
158
 
 
159
  with gr.Row():
160
  with gr.Column():
161
  input_image = gr.Image(type="numpy", label="Afbeelding uploaden")
@@ -165,29 +170,40 @@ with gr.Blocks(css=custom_css) as demo:
165
  with gr.Column():
166
  output_image = gr.Image(type="numpy", label="Resultaat gezichtsuitdrukking")
167
  emotion_md = gr.Markdown("## **Nog geen resultaat**", elem_id="emotie-uitslag")
168
- stats_image = gr.Image(label="Statistieken", type="numpy")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
  # Clear-helpers
171
  def clear_all_on_new():
172
- return None, "## **Nog geen resultaat**", draw_bar_chart_cv(emotion_stats)
173
 
174
  def clear_all_button():
 
175
  return None, None, "## **Nog geen resultaat**", draw_bar_chart_cv(emotion_stats)
176
 
177
- input_image.change(fn=clear_all_on_new, outputs=[output_image, emotion_md, stats_image])
 
 
178
  submit_btn.click(fn=detect_expression, inputs=input_image, outputs=[output_image, emotion_md, stats_image])
 
179
  clear_btn.click(fn=clear_all_button, outputs=[input_image, output_image, emotion_md, stats_image])
180
 
181
- gr.Markdown("Klik op een voorbeeld om te testen.")
182
- # BELANGRIJK: gebruik de 'no_stats'-functie voor Examples zodat deze NIET meetellen
183
- gr.Examples(
184
- examples=example_list,
185
- inputs=input_image,
186
- outputs=[output_image, emotion_md, stats_image],
187
- fn=detect_expression_no_stats, # <- telt NIET mee
188
- examples_per_page=20,
189
- cache_examples=CACHE_EXAMPLES
190
- )
191
-
192
  if __name__ == "__main__":
193
  demo.launch()
 
18
  fer_model = FacialExpressionRecog(modelPath=FER_MODEL_PATH, backendId=backend_id, targetId=target_id)
19
  detect_model = YuNet(modelPath=FD_MODEL_PATH)
20
 
21
+ # EN -> NL mapping (lowercase)
22
  EN_TO_NL = {
23
+ "neutral": "neutraal",
24
+ "happy": "blij",
25
+ "sad": "verdrietig",
26
+ "surprise": "verrast",
27
+ "angry": "boos",
28
+ "anger": "boos",
29
+ "disgust": "walging",
30
+ "fear": "bang",
31
+ "contempt": "minachting",
32
+ "unknown": "onbekend",
33
  }
34
 
35
+ def to_dutch_lower(label: str) -> str:
36
+ """Zet emotielabel om naar NL en lowercase (fallback: originele lowercase)."""
37
  if not label:
38
+ return "onbekend"
39
  key = label.strip().lower()
40
+ return EN_TO_NL.get(key, key)
41
 
42
  # In-memory statistieken
43
  emotion_stats = defaultdict(int)
44
 
45
  def visualize(image, det_res, fer_res):
46
+ """Tekent bbox + NL-lowercase emotielabel op de output."""
47
  output = image.copy()
48
  landmark_color = [(255, 0, 0), (0, 0, 255), (0, 255, 0), (255, 0, 255), (0, 255, 255)]
49
  for det, fer_type in zip(det_res, fer_res):
50
  bbox = det[0:4].astype(np.int32)
51
+ fer_type_str_nl = to_dutch_lower(FacialExpressionRecog.getDesc(fer_type))
52
+
53
  cv.rectangle(output, (bbox[0], bbox[1]), (bbox[0]+bbox[2], bbox[1]+bbox[3]), (0, 255, 0), 2)
54
  cv.putText(output, fer_type_str_nl, (bbox[0], max(0, bbox[1] - 10)),
55
  cv.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2, cv.LINE_AA)
56
+
57
  landmarks = det[4:14].astype(np.int32).reshape((5, 2))
58
  for idx, landmark in enumerate(landmarks):
59
  cv.circle(output, landmark, 2, landmark_color[idx], 2)
60
  return output
61
 
62
  def summarize_emotions(fer_res):
63
+ """Maakt de grote groene NL-lowercase samenvatting."""
64
  if not fer_res:
65
+ return "## **geen gezicht gedetecteerd**"
66
+ names_nl = [to_dutch_lower(FacialExpressionRecog.getDesc(x)) for x in fer_res]
67
  counts = Counter(names_nl).most_common()
68
  top = counts[0][0]
69
  details = ", ".join([f"{name} ({n})" for name, n in counts])
 
82
  plot_h = height - top - bottom
83
  origin = (left, height - bottom)
84
 
85
+ cv.line(img, origin, (left + plot_w, height - bottom), (0, 0, 0), 2) # x-as
86
+ cv.line(img, origin, (left, height - bottom - plot_h), (0, 0, 0), 2) # y-as
87
 
88
  labels = list(stats.keys())
89
  values = [stats[k] for k in labels]
 
99
  h_px = int((val / max_val) * (plot_h - 10))
100
  y1 = height - bottom - h_px
101
  y2 = height - bottom - 1
102
+ cv.rectangle(img, (x1, y1), (x2, y2), (0, 170, 60), -1) # groene balk
103
  cv.putText(img, str(val), (x1 + 2, y1 - 6), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 90, 30), 1, cv.LINE_AA)
104
 
105
+ show_lab = lab if len(lab) <= 12 else lab[:11] + "…"
106
  (tw, th), _ = cv.getTextSize(show_lab, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
107
  tx = x1 + (bar_w - tw) // 2
108
  ty = height - bottom + th + 12
 
111
  return cv.cvtColor(img, cv.COLOR_BGR2RGB)
112
 
113
  def process_image(input_image):
114
+ """Helper: run detectie en retourneer (output_img, fer_res as list[int])."""
115
  image = cv.cvtColor(input_image, cv.COLOR_RGB2BGR)
116
  h, w, _ = image.shape
117
  detect_model.setInputSize([w, h])
 
126
  """Versie die WÉL statistieken bijwerkt (gebruik voor 'Verstuur')."""
127
  output_img, fer_res = process_image(input_image)
128
  emotion_md = summarize_emotions(fer_res)
129
+ # update stats in NL-lowercase
130
+ names_nl = [to_dutch_lower(FacialExpressionRecog.getDesc(x)) for x in fer_res]
131
  for name in names_nl:
132
  emotion_stats[name] += 1
133
  stats_plot = draw_bar_chart_cv(emotion_stats)
 
137
  """Versie die GEEN statistieken bijwerkt (gebruik voor gr.Examples & caching)."""
138
  output_img, fer_res = process_image(input_image)
139
  emotion_md = summarize_emotions(fer_res)
140
+ stats_plot = draw_bar_chart_cv(emotion_stats) # toon huidige stand
 
141
  return output_img, emotion_md, stats_plot
142
 
143
  # Voorbeelden automatisch laden
 
157
  """
158
 
159
  with gr.Blocks(css=custom_css) as demo:
160
+ gr.Markdown("## Herkenning van gezichtsuitdrukkingen (FER) met OpenCV DNN")
161
+ gr.Markdown("Detecteert gezichten en herkent gezichtsuitdrukkingen met YuNet + MobileFaceNet (ONNX).")
162
 
163
+ # Rij 1: Links upload/knoppen, Rechts output + emotie
164
  with gr.Row():
165
  with gr.Column():
166
  input_image = gr.Image(type="numpy", label="Afbeelding uploaden")
 
170
  with gr.Column():
171
  output_image = gr.Image(type="numpy", label="Resultaat gezichtsuitdrukking")
172
  emotion_md = gr.Markdown("## **Nog geen resultaat**", elem_id="emotie-uitslag")
173
+
174
+ # Rij 2: Links mugshots (Examples), Rechts statistieken
175
+ with gr.Row():
176
+ with gr.Column():
177
+ gr.Markdown("**Voorbeelden (klik om te testen):**")
178
+ examples_component = gr.Examples(
179
+ examples=example_list,
180
+ inputs=input_image,
181
+ outputs=[output_image, emotion_md], # stats volgt hieronder in dezelfde row
182
+ fn=detect_expression_no_stats,
183
+ examples_per_page=20,
184
+ cache_examples=CACHE_EXAMPLES
185
+ )
186
+ with gr.Column():
187
+ stats_image = gr.Image(
188
+ label="Statistieken",
189
+ type="numpy",
190
+ value=draw_bar_chart_cv(emotion_stats) # start met lege/actuele chart
191
+ )
192
 
193
  # Clear-helpers
194
  def clear_all_on_new():
195
+ return None, "## **Nog geen resultaat**"
196
 
197
  def clear_all_button():
198
+ # reset inputs/outputs; statistieken blijven behouden
199
  return None, None, "## **Nog geen resultaat**", draw_bar_chart_cv(emotion_stats)
200
 
201
+ # Nieuwe upload wist output + emotietekst (grafiek blijft staan)
202
+ input_image.change(fn=clear_all_on_new, outputs=[output_image, emotion_md])
203
+ # Verwerken
204
  submit_btn.click(fn=detect_expression, inputs=input_image, outputs=[output_image, emotion_md, stats_image])
205
+ # Wissen-knop: ook grafiek opnieuw tekenen (maar stats niet resetten)
206
  clear_btn.click(fn=clear_all_button, outputs=[input_image, output_image, emotion_md, stats_image])
207
 
 
 
 
 
 
 
 
 
 
 
 
208
  if __name__ == "__main__":
209
  demo.launch()