Update app.py
Browse files
app.py
CHANGED
|
@@ -66,31 +66,19 @@ def summarize_emotions(fer_res):
|
|
| 66 |
|
| 67 |
# --- Staafdiagram tekenen met OpenCV (geen matplotlib nodig) ---
|
| 68 |
def draw_bar_chart_cv(stats: dict, width=640, height=320):
|
| 69 |
-
"""
|
| 70 |
-
Maakt een simpele staafdiagram als numpy image (RGB).
|
| 71 |
-
"""
|
| 72 |
-
# Wit canvas (BGR eerst, later naar RGB)
|
| 73 |
img = np.full((height, width, 3), 255, dtype=np.uint8)
|
| 74 |
-
|
| 75 |
-
# Titel
|
| 76 |
-
title = "Live emotie-statistieken"
|
| 77 |
-
cv.putText(img, title, (12, 28), cv.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 0), 2, cv.LINE_AA)
|
| 78 |
-
|
| 79 |
-
# Geen data?
|
| 80 |
if not stats:
|
| 81 |
-
|
| 82 |
-
cv.putText(img, msg, (12, height//2), cv.FONT_HERSHEY_SIMPLEX, 0.9, (128, 128, 128), 2, cv.LINE_AA)
|
| 83 |
return cv.cvtColor(img, cv.COLOR_BGR2RGB)
|
| 84 |
|
| 85 |
-
# Marges & plotgebied
|
| 86 |
left, right, top, bottom = 60, 20, 50, 40
|
| 87 |
plot_w = width - left - right
|
| 88 |
plot_h = height - top - bottom
|
| 89 |
origin = (left, height - bottom)
|
| 90 |
|
| 91 |
-
|
| 92 |
-
cv.line(img, origin, (left
|
| 93 |
-
cv.line(img, origin, (left, height - bottom - plot_h), (0, 0, 0), 2) # y-as
|
| 94 |
|
| 95 |
labels = list(stats.keys())
|
| 96 |
values = [stats[k] for k in labels]
|
|
@@ -100,20 +88,15 @@ def draw_bar_chart_cv(stats: dict, width=640, height=320):
|
|
| 100 |
gap = 12
|
| 101 |
bar_w = max(10, int((plot_w - gap * (n + 1)) / max(1, n)))
|
| 102 |
|
| 103 |
-
# Bars (groen)
|
| 104 |
for i, (lab, val) in enumerate(zip(labels, values)):
|
| 105 |
x1 = left + gap + i * (bar_w + gap)
|
| 106 |
x2 = x1 + bar_w
|
| 107 |
-
# Hoogte proportioneel
|
| 108 |
h_px = int((val / max_val) * (plot_h - 10))
|
| 109 |
y1 = height - bottom - h_px
|
| 110 |
y2 = height - bottom - 1
|
| 111 |
-
cv.rectangle(img, (x1, y1), (x2, y2), (0, 170, 60), -1)
|
| 112 |
-
|
| 113 |
-
# Waardelabel boven balk
|
| 114 |
cv.putText(img, str(val), (x1 + 2, y1 - 6), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 90, 30), 1, cv.LINE_AA)
|
| 115 |
|
| 116 |
-
# X-label onder balk (afgekort indien lang)
|
| 117 |
show_lab = lab if len(lab) <= 10 else lab[:9] + "…"
|
| 118 |
(tw, th), _ = cv.getTextSize(show_lab, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
|
| 119 |
tx = x1 + (bar_w - tw) // 2
|
|
@@ -122,30 +105,36 @@ def draw_bar_chart_cv(stats: dict, width=640, height=320):
|
|
| 122 |
|
| 123 |
return cv.cvtColor(img, cv.COLOR_BGR2RGB)
|
| 124 |
|
| 125 |
-
def
|
| 126 |
-
|
| 127 |
-
emotion_stats[name] += 1
|
| 128 |
-
return draw_bar_chart_cv(emotion_stats)
|
| 129 |
-
|
| 130 |
-
def detect_expression(input_image):
|
| 131 |
image = cv.cvtColor(input_image, cv.COLOR_RGB2BGR)
|
| 132 |
h, w, _ = image.shape
|
| 133 |
detect_model.setInputSize([w, h])
|
| 134 |
dets = detect_model.infer(image)
|
| 135 |
-
|
| 136 |
if dets is None:
|
| 137 |
-
|
| 138 |
-
# Geen incremente — alleen huidige chart tonen
|
| 139 |
-
stats_plot = draw_bar_chart_cv(emotion_stats)
|
| 140 |
-
return cv.cvtColor(image, cv.COLOR_BGR2RGB), emotion_md, stats_plot
|
| 141 |
-
|
| 142 |
fer_res = [fer_model.infer(image, face_points[:-1])[0] for face_points in dets]
|
| 143 |
output = visualize(image, dets, fer_res)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
emotion_md = summarize_emotions(fer_res)
|
|
|
|
| 145 |
names_nl = [to_dutch(FacialExpressionRecog.getDesc(x)) for x in fer_res]
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
| 147 |
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
# Voorbeelden automatisch laden
|
| 151 |
IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".bmp", ".webp"}
|
|
@@ -164,8 +153,8 @@ custom_css = """
|
|
| 164 |
"""
|
| 165 |
|
| 166 |
with gr.Blocks(css=custom_css) as demo:
|
| 167 |
-
gr.Markdown("## Herkenning van gezichtsuitdrukkingen
|
| 168 |
-
gr.Markdown("Detecteert gezichten en herkent gezichtsuitdrukkingen
|
| 169 |
|
| 170 |
with gr.Row():
|
| 171 |
with gr.Column():
|
|
@@ -183,7 +172,6 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 183 |
return None, "## **Nog geen resultaat**", draw_bar_chart_cv(emotion_stats)
|
| 184 |
|
| 185 |
def clear_all_button():
|
| 186 |
-
# reset alleen UI; statistieken laten we staan
|
| 187 |
return None, None, "## **Nog geen resultaat**", draw_bar_chart_cv(emotion_stats)
|
| 188 |
|
| 189 |
input_image.change(fn=clear_all_on_new, outputs=[output_image, emotion_md, stats_image])
|
|
@@ -191,11 +179,12 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 191 |
clear_btn.click(fn=clear_all_button, outputs=[input_image, output_image, emotion_md, stats_image])
|
| 192 |
|
| 193 |
gr.Markdown("Klik op een voorbeeld om te testen.")
|
|
|
|
| 194 |
gr.Examples(
|
| 195 |
examples=example_list,
|
| 196 |
inputs=input_image,
|
| 197 |
outputs=[output_image, emotion_md, stats_image],
|
| 198 |
-
fn=
|
| 199 |
examples_per_page=20,
|
| 200 |
cache_examples=CACHE_EXAMPLES
|
| 201 |
)
|
|
|
|
| 66 |
|
| 67 |
# --- Staafdiagram tekenen met OpenCV (geen matplotlib nodig) ---
|
| 68 |
def draw_bar_chart_cv(stats: dict, width=640, height=320):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
img = np.full((height, width, 3), 255, dtype=np.uint8)
|
| 70 |
+
cv.putText(img, "Live emotie-statistieken", (12, 28), cv.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 0), 2, cv.LINE_AA)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
if not stats:
|
| 72 |
+
cv.putText(img, "Nog geen statistieken", (12, height//2), cv.FONT_HERSHEY_SIMPLEX, 0.9, (128, 128, 128), 2, cv.LINE_AA)
|
|
|
|
| 73 |
return cv.cvtColor(img, cv.COLOR_BGR2RGB)
|
| 74 |
|
|
|
|
| 75 |
left, right, top, bottom = 60, 20, 50, 40
|
| 76 |
plot_w = width - left - right
|
| 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]
|
|
|
|
| 88 |
gap = 12
|
| 89 |
bar_w = max(10, int((plot_w - gap * (n + 1)) / max(1, n)))
|
| 90 |
|
|
|
|
| 91 |
for i, (lab, val) in enumerate(zip(labels, values)):
|
| 92 |
x1 = left + gap + i * (bar_w + gap)
|
| 93 |
x2 = x1 + bar_w
|
|
|
|
| 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
|
|
|
|
| 105 |
|
| 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])
|
| 113 |
dets = detect_model.infer(image)
|
|
|
|
| 114 |
if dets is None:
|
| 115 |
+
return cv.cvtColor(image, cv.COLOR_BGR2RGB), []
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
fer_res = [fer_model.infer(image, face_points[:-1])[0] for face_points in dets]
|
| 117 |
output = visualize(image, dets, fer_res)
|
| 118 |
+
return cv.cvtColor(output, cv.COLOR_BGR2RGB), fer_res
|
| 119 |
+
|
| 120 |
+
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)
|
| 129 |
+
return output_img, emotion_md, stats_plot
|
| 130 |
|
| 131 |
+
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
|
| 140 |
IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".bmp", ".webp"}
|
|
|
|
| 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():
|
|
|
|
| 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])
|
|
|
|
| 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 |
)
|