David Driscoll
commited on
Commit
·
8947b35
1
Parent(s):
2553966
Output restoration
Browse files
app.py
CHANGED
@@ -10,7 +10,7 @@ from fer import FER # Facial emotion recognition
|
|
10 |
from concurrent.futures import ThreadPoolExecutor
|
11 |
|
12 |
# -----------------------------
|
13 |
-
#
|
14 |
# -----------------------------
|
15 |
executor = ThreadPoolExecutor(max_workers=4)
|
16 |
latest_results = {
|
@@ -27,22 +27,24 @@ futures = {
|
|
27 |
}
|
28 |
|
29 |
def async_analyze(key, func, image):
|
30 |
-
|
31 |
-
|
32 |
-
Returns the last computed result (if available) so that the output
|
33 |
-
FPS remains high even if the detection lags.
|
34 |
-
"""
|
35 |
-
if futures[key] is None or futures[key].done():
|
36 |
-
futures[key] = executor.submit(func, image)
|
37 |
-
if futures[key].done():
|
38 |
latest_results[key] = futures[key].result()
|
39 |
-
|
40 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
# -----------------------------
|
43 |
# Initialize Models and Helpers
|
44 |
# -----------------------------
|
45 |
-
|
46 |
# MediaPipe Pose for posture analysis
|
47 |
mp_pose = mp.solutions.pose
|
48 |
pose = mp_pose.Pose()
|
@@ -65,9 +67,7 @@ emotion_detector = FER(mtcnn=True)
|
|
65 |
# -----------------------------
|
66 |
# Heavy (Synchronous) Analysis Functions
|
67 |
# -----------------------------
|
68 |
-
|
69 |
def _analyze_posture(image):
|
70 |
-
# Convert from PIL (RGB) to OpenCV BGR format
|
71 |
frame = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
|
72 |
output_frame = frame.copy()
|
73 |
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
@@ -132,18 +132,18 @@ def _analyze_faces(image):
|
|
132 |
return annotated_image, f"Face Detection: {face_result}"
|
133 |
|
134 |
# -----------------------------
|
135 |
-
# Asynchronous
|
136 |
# -----------------------------
|
137 |
-
def
|
138 |
return async_analyze("posture", _analyze_posture, image)
|
139 |
|
140 |
-
def
|
141 |
return async_analyze("emotion", _analyze_emotion, image)
|
142 |
|
143 |
-
def
|
144 |
return async_analyze("objects", _analyze_objects, image)
|
145 |
|
146 |
-
def
|
147 |
return async_analyze("faces", _analyze_faces, image)
|
148 |
|
149 |
# -----------------------------
|
@@ -183,7 +183,7 @@ body {
|
|
183 |
# Create Individual Interfaces for Each Analysis
|
184 |
# -----------------------------
|
185 |
posture_interface = gr.Interface(
|
186 |
-
fn=
|
187 |
inputs=gr.Image(sources=["webcam"], streaming=True, label="Capture Your Posture"),
|
188 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.Textbox(label="Posture Analysis")],
|
189 |
title="Posture Analysis",
|
@@ -192,7 +192,7 @@ posture_interface = gr.Interface(
|
|
192 |
)
|
193 |
|
194 |
emotion_interface = gr.Interface(
|
195 |
-
fn=
|
196 |
inputs=gr.Image(sources=["webcam"], streaming=True, label="Capture Your Face"),
|
197 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.Textbox(label="Emotion Analysis")],
|
198 |
title="Emotion Analysis",
|
@@ -201,7 +201,7 @@ emotion_interface = gr.Interface(
|
|
201 |
)
|
202 |
|
203 |
objects_interface = gr.Interface(
|
204 |
-
fn=
|
205 |
inputs=gr.Image(sources=["webcam"], streaming=True, label="Capture the Scene"),
|
206 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.Textbox(label="Object Detection")],
|
207 |
title="Object Detection",
|
@@ -210,7 +210,7 @@ objects_interface = gr.Interface(
|
|
210 |
)
|
211 |
|
212 |
faces_interface = gr.Interface(
|
213 |
-
fn=
|
214 |
inputs=gr.Image(sources=["webcam"], streaming=True, label="Capture Your Face"),
|
215 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.Textbox(label="Face Detection")],
|
216 |
title="Face Detection",
|
|
|
10 |
from concurrent.futures import ThreadPoolExecutor
|
11 |
|
12 |
# -----------------------------
|
13 |
+
# Asynchronous Processing Setup
|
14 |
# -----------------------------
|
15 |
executor = ThreadPoolExecutor(max_workers=4)
|
16 |
latest_results = {
|
|
|
27 |
}
|
28 |
|
29 |
def async_analyze(key, func, image):
|
30 |
+
# If a background task is done, update our cache.
|
31 |
+
if futures[key] is not None and futures[key].done():
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
latest_results[key] = futures[key].result()
|
33 |
+
futures[key] = None
|
34 |
+
# If we already have a cached result, return it immediately and schedule a new update if none is running.
|
35 |
+
if latest_results[key] is not None:
|
36 |
+
if futures[key] is None:
|
37 |
+
futures[key] = executor.submit(func, image)
|
38 |
+
return latest_results[key]
|
39 |
+
# Otherwise, compute synchronously (blocking) to initialize the cache.
|
40 |
+
result = func(image)
|
41 |
+
latest_results[key] = result
|
42 |
+
futures[key] = executor.submit(func, image)
|
43 |
+
return result
|
44 |
|
45 |
# -----------------------------
|
46 |
# Initialize Models and Helpers
|
47 |
# -----------------------------
|
|
|
48 |
# MediaPipe Pose for posture analysis
|
49 |
mp_pose = mp.solutions.pose
|
50 |
pose = mp_pose.Pose()
|
|
|
67 |
# -----------------------------
|
68 |
# Heavy (Synchronous) Analysis Functions
|
69 |
# -----------------------------
|
|
|
70 |
def _analyze_posture(image):
|
|
|
71 |
frame = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
|
72 |
output_frame = frame.copy()
|
73 |
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
|
|
132 |
return annotated_image, f"Face Detection: {face_result}"
|
133 |
|
134 |
# -----------------------------
|
135 |
+
# Asynchronous Wrappers for Each Analysis
|
136 |
# -----------------------------
|
137 |
+
def analyze_posture_async(image):
|
138 |
return async_analyze("posture", _analyze_posture, image)
|
139 |
|
140 |
+
def analyze_emotion_async(image):
|
141 |
return async_analyze("emotion", _analyze_emotion, image)
|
142 |
|
143 |
+
def analyze_objects_async(image):
|
144 |
return async_analyze("objects", _analyze_objects, image)
|
145 |
|
146 |
+
def analyze_faces_async(image):
|
147 |
return async_analyze("faces", _analyze_faces, image)
|
148 |
|
149 |
# -----------------------------
|
|
|
183 |
# Create Individual Interfaces for Each Analysis
|
184 |
# -----------------------------
|
185 |
posture_interface = gr.Interface(
|
186 |
+
fn=analyze_posture_async,
|
187 |
inputs=gr.Image(sources=["webcam"], streaming=True, label="Capture Your Posture"),
|
188 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.Textbox(label="Posture Analysis")],
|
189 |
title="Posture Analysis",
|
|
|
192 |
)
|
193 |
|
194 |
emotion_interface = gr.Interface(
|
195 |
+
fn=analyze_emotion_async,
|
196 |
inputs=gr.Image(sources=["webcam"], streaming=True, label="Capture Your Face"),
|
197 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.Textbox(label="Emotion Analysis")],
|
198 |
title="Emotion Analysis",
|
|
|
201 |
)
|
202 |
|
203 |
objects_interface = gr.Interface(
|
204 |
+
fn=analyze_objects_async,
|
205 |
inputs=gr.Image(sources=["webcam"], streaming=True, label="Capture the Scene"),
|
206 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.Textbox(label="Object Detection")],
|
207 |
title="Object Detection",
|
|
|
210 |
)
|
211 |
|
212 |
faces_interface = gr.Interface(
|
213 |
+
fn=analyze_faces_async,
|
214 |
inputs=gr.Image(sources=["webcam"], streaming=True, label="Capture Your Face"),
|
215 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.Textbox(label="Face Detection")],
|
216 |
title="Face Detection",
|