David Driscoll
commited on
Commit
·
d33634b
1
Parent(s):
f6a647b
Fix text, connect bounding boxes
Browse files
app.py
CHANGED
@@ -11,8 +11,7 @@ from fer import FER # Facial emotion recognition
|
|
11 |
# -----------------------------
|
12 |
# Configuration
|
13 |
# -----------------------------
|
14 |
-
# For image processing, always run the analysis
|
15 |
-
SKIP_RATE = 1
|
16 |
|
17 |
# Use GPU if available
|
18 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
@@ -41,7 +40,7 @@ face_detection = mp_face_detection.FaceDetection(min_detection_confidence=0.5)
|
|
41 |
object_detection_model = models.detection.fasterrcnn_resnet50_fpn(
|
42 |
weights=FasterRCNN_ResNet50_FPN_Weights.DEFAULT
|
43 |
)
|
44 |
-
object_detection_model.eval().to(device) # Move model to GPU
|
45 |
|
46 |
obj_transform = transforms.Compose([transforms.ToTensor()])
|
47 |
|
@@ -52,7 +51,14 @@ emotion_detector = FER(mtcnn=True)
|
|
52 |
# Overlay Drawing Functions
|
53 |
# -----------------------------
|
54 |
def draw_posture_overlay(raw_frame, landmarks):
|
55 |
-
# Draw
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
for (x, y) in landmarks:
|
57 |
cv2.circle(raw_frame, (x, y), 4, (50, 205, 50), -1)
|
58 |
return raw_frame
|
@@ -159,7 +165,7 @@ def analyze_posture_current(image):
|
|
159 |
if posture_cache["landmarks"]:
|
160 |
output = draw_posture_overlay(output, posture_cache["landmarks"])
|
161 |
|
162 |
-
return output, f"<div style='color: lime;'>Posture Analysis: {posture_cache['text']}</div>"
|
163 |
|
164 |
def analyze_emotion_current(image):
|
165 |
global emotion_cache
|
@@ -169,7 +175,7 @@ def analyze_emotion_current(image):
|
|
169 |
text = compute_emotion_overlay(image)
|
170 |
emotion_cache["text"] = text
|
171 |
|
172 |
-
return current_frame, f"<div style='color: lime;'>Emotion Analysis: {emotion_cache['text']}</div>"
|
173 |
|
174 |
def analyze_objects_current(image):
|
175 |
global objects_cache
|
@@ -183,7 +189,7 @@ def analyze_objects_current(image):
|
|
183 |
output = current_frame.copy()
|
184 |
if objects_cache["boxes"]:
|
185 |
output = draw_boxes_overlay(output, objects_cache["boxes"], (255, 255, 0))
|
186 |
-
return output, f"<div style='color: lime;'>Object Detection: {objects_cache['text']}</div>"
|
187 |
|
188 |
def analyze_faces_current(image):
|
189 |
global faces_cache
|
@@ -197,7 +203,7 @@ def analyze_faces_current(image):
|
|
197 |
output = current_frame.copy()
|
198 |
if faces_cache["boxes"]:
|
199 |
output = draw_boxes_overlay(output, faces_cache["boxes"], (0, 0, 255))
|
200 |
-
return output, f"<div style='color: lime;'>Face Detection: {faces_cache['text']}</div>"
|
201 |
|
202 |
def analyze_all(image):
|
203 |
# Run all analyses on the same image
|
@@ -227,11 +233,11 @@ def analyze_all(image):
|
|
227 |
f"Object Detection: {objects_text}<br>"
|
228 |
f"Face Detection: {faces_text}"
|
229 |
)
|
230 |
-
combined_text_html = f"<div style='color: lime;'>{combined_text}</div>"
|
231 |
return current_frame, combined_text_html
|
232 |
|
233 |
# -----------------------------
|
234 |
-
# Custom CSS
|
235 |
# -----------------------------
|
236 |
custom_css = """
|
237 |
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
|
@@ -243,7 +249,9 @@ body {
|
|
243 |
padding: 0;
|
244 |
}
|
245 |
.gradio-container {
|
246 |
-
background: linear-gradient(135deg, #
|
|
|
|
|
247 |
border-radius: 10px;
|
248 |
padding: 20px;
|
249 |
max-width: 1200px;
|
@@ -251,15 +259,21 @@ body {
|
|
251 |
}
|
252 |
.gradio-title {
|
253 |
font-size: 2.5em;
|
254 |
-
color: #
|
255 |
text-align: center;
|
256 |
margin-bottom: 0.2em;
|
|
|
257 |
}
|
258 |
.gradio-description {
|
259 |
font-size: 1.2em;
|
260 |
text-align: center;
|
261 |
margin-bottom: 1em;
|
262 |
-
color: #
|
|
|
|
|
|
|
|
|
|
|
263 |
}
|
264 |
"""
|
265 |
|
@@ -271,7 +285,7 @@ posture_interface = gr.Interface(
|
|
271 |
inputs=gr.Image(label="Upload an Image for Posture Analysis"),
|
272 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Posture Analysis")],
|
273 |
title="Posture Analysis",
|
274 |
-
description="Detects your posture using MediaPipe.",
|
275 |
live=False
|
276 |
)
|
277 |
|
@@ -326,7 +340,7 @@ demo = gr.Blocks(css=custom_css)
|
|
326 |
with demo:
|
327 |
gr.Markdown("<h1 class='gradio-title'>Multi-Analysis Image App</h1>")
|
328 |
gr.Markdown(
|
329 |
-
"<p class='gradio-description'>Upload an image to run analysis for posture, emotions, objects, and faces.</p>"
|
330 |
)
|
331 |
tabbed_interface.render()
|
332 |
|
|
|
11 |
# -----------------------------
|
12 |
# Configuration
|
13 |
# -----------------------------
|
14 |
+
SKIP_RATE = 1 # For image processing, always run the analysis
|
|
|
15 |
|
16 |
# Use GPU if available
|
17 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
40 |
object_detection_model = models.detection.fasterrcnn_resnet50_fpn(
|
41 |
weights=FasterRCNN_ResNet50_FPN_Weights.DEFAULT
|
42 |
)
|
43 |
+
object_detection_model.eval().to(device) # Move model to GPU if available
|
44 |
|
45 |
obj_transform = transforms.Compose([transforms.ToTensor()])
|
46 |
|
|
|
51 |
# Overlay Drawing Functions
|
52 |
# -----------------------------
|
53 |
def draw_posture_overlay(raw_frame, landmarks):
|
54 |
+
# Draw connector lines using MediaPipe's POSE_CONNECTIONS
|
55 |
+
for connection in mp_pose.POSE_CONNECTIONS:
|
56 |
+
start_idx, end_idx = connection
|
57 |
+
if start_idx < len(landmarks) and end_idx < len(landmarks):
|
58 |
+
start_point = landmarks[start_idx]
|
59 |
+
end_point = landmarks[end_idx]
|
60 |
+
cv2.line(raw_frame, start_point, end_point, (50, 205, 50), 2)
|
61 |
+
# Draw landmark points in lime green (BGR: (50,205,50))
|
62 |
for (x, y) in landmarks:
|
63 |
cv2.circle(raw_frame, (x, y), 4, (50, 205, 50), -1)
|
64 |
return raw_frame
|
|
|
165 |
if posture_cache["landmarks"]:
|
166 |
output = draw_posture_overlay(output, posture_cache["landmarks"])
|
167 |
|
168 |
+
return output, f"<div style='color: lime !important;'>Posture Analysis: {posture_cache['text']}</div>"
|
169 |
|
170 |
def analyze_emotion_current(image):
|
171 |
global emotion_cache
|
|
|
175 |
text = compute_emotion_overlay(image)
|
176 |
emotion_cache["text"] = text
|
177 |
|
178 |
+
return current_frame, f"<div style='color: lime !important;'>Emotion Analysis: {emotion_cache['text']}</div>"
|
179 |
|
180 |
def analyze_objects_current(image):
|
181 |
global objects_cache
|
|
|
189 |
output = current_frame.copy()
|
190 |
if objects_cache["boxes"]:
|
191 |
output = draw_boxes_overlay(output, objects_cache["boxes"], (255, 255, 0))
|
192 |
+
return output, f"<div style='color: lime !important;'>Object Detection: {objects_cache['text']}</div>"
|
193 |
|
194 |
def analyze_faces_current(image):
|
195 |
global faces_cache
|
|
|
203 |
output = current_frame.copy()
|
204 |
if faces_cache["boxes"]:
|
205 |
output = draw_boxes_overlay(output, faces_cache["boxes"], (0, 0, 255))
|
206 |
+
return output, f"<div style='color: lime !important;'>Face Detection: {faces_cache['text']}</div>"
|
207 |
|
208 |
def analyze_all(image):
|
209 |
# Run all analyses on the same image
|
|
|
233 |
f"Object Detection: {objects_text}<br>"
|
234 |
f"Face Detection: {faces_text}"
|
235 |
)
|
236 |
+
combined_text_html = f"<div style='color: lime !important;'>{combined_text}</div>"
|
237 |
return current_frame, combined_text_html
|
238 |
|
239 |
# -----------------------------
|
240 |
+
# Custom CSS (High-Tech Theme)
|
241 |
# -----------------------------
|
242 |
custom_css = """
|
243 |
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
|
|
|
249 |
padding: 0;
|
250 |
}
|
251 |
.gradio-container {
|
252 |
+
background: linear-gradient(135deg, #1a1a1a, #333333);
|
253 |
+
border: 2px solid #32CD32;
|
254 |
+
box-shadow: 0 0 15px #32CD32;
|
255 |
border-radius: 10px;
|
256 |
padding: 20px;
|
257 |
max-width: 1200px;
|
|
|
259 |
}
|
260 |
.gradio-title {
|
261 |
font-size: 2.5em;
|
262 |
+
color: #32CD32;
|
263 |
text-align: center;
|
264 |
margin-bottom: 0.2em;
|
265 |
+
text-shadow: 0 0 10px #32CD32;
|
266 |
}
|
267 |
.gradio-description {
|
268 |
font-size: 1.2em;
|
269 |
text-align: center;
|
270 |
margin-bottom: 1em;
|
271 |
+
color: #32CD32;
|
272 |
+
text-shadow: 0 0 8px #32CD32;
|
273 |
+
}
|
274 |
+
input, button, .output, .tab-item {
|
275 |
+
border: 1px solid #32CD32;
|
276 |
+
box-shadow: 0 0 8px #32CD32;
|
277 |
}
|
278 |
"""
|
279 |
|
|
|
285 |
inputs=gr.Image(label="Upload an Image for Posture Analysis"),
|
286 |
outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Posture Analysis")],
|
287 |
title="Posture Analysis",
|
288 |
+
description="Detects your posture using MediaPipe with connector lines.",
|
289 |
live=False
|
290 |
)
|
291 |
|
|
|
340 |
with demo:
|
341 |
gr.Markdown("<h1 class='gradio-title'>Multi-Analysis Image App</h1>")
|
342 |
gr.Markdown(
|
343 |
+
"<p class='gradio-description'>Upload an image to run high-tech analysis for posture, emotions, objects, and faces.</p>"
|
344 |
)
|
345 |
tabbed_interface.render()
|
346 |
|