David Driscoll commited on
Commit
4f14988
·
1 Parent(s): fd8b339

Restructure

Browse files
Files changed (1) hide show
  1. app.py +18 -121
app.py CHANGED
@@ -1,9 +1,6 @@
1
  import gradio as gr
2
  import cv2
3
  import numpy as np
4
- import torch
5
- from torchvision import models, transforms
6
- from torchvision.models.detection import FasterRCNN_ResNet50_FPN_Weights
7
  from PIL import Image
8
  import mediapipe as mp
9
  from fer import FER # Facial emotion recognition
@@ -12,7 +9,6 @@ from fer import FER # Facial emotion recognition
12
  # Configuration
13
  # -----------------------------
14
  SKIP_RATE = 1 # For image processing, always run the analysis
15
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
16
  DESIRED_SIZE = (640, 480)
17
 
18
  # -----------------------------
@@ -20,7 +16,6 @@ DESIRED_SIZE = (640, 480)
20
  # -----------------------------
21
  posture_cache = {"landmarks": None, "text": "Initializing...", "counter": 0}
22
  emotion_cache = {"text": "Initializing...", "counter": 0}
23
- objects_cache = {"boxes": None, "text": "Initializing...", "object_list_text": "", "counter": 0}
24
  faces_cache = {"boxes": None, "text": "Initializing...", "counter": 0}
25
 
26
  # -----------------------------
@@ -34,19 +29,9 @@ mp_drawing = mp.solutions.drawing_utils
34
  mp_face_detection = mp.solutions.face_detection
35
  face_detection = mp_face_detection.FaceDetection(min_detection_confidence=0.5)
36
 
37
- # Object Detection using Faster R-CNN
38
- object_detection_model = models.detection.fasterrcnn_resnet50_fpn(
39
- weights=FasterRCNN_ResNet50_FPN_Weights.DEFAULT
40
- )
41
- object_detection_model.eval().to(device)
42
- obj_transform = transforms.Compose([transforms.ToTensor()])
43
-
44
  # Initialize the FER emotion detector (using the FER package)
45
  emotion_detector = FER(mtcnn=True)
46
 
47
- # Retrieve object categories from model weights metadata
48
- object_categories = FasterRCNN_ResNet50_FPN_Weights.DEFAULT.meta["categories"]
49
-
50
  # -----------------------------
51
  # Overlay Drawing Functions
52
  # -----------------------------
@@ -100,27 +85,6 @@ def compute_emotion_overlay(image):
100
  text = "No face detected"
101
  return text
102
 
103
- def compute_objects_overlay(image):
104
- frame_bgr = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
105
- frame_bgr_small = cv2.resize(frame_bgr, DESIRED_SIZE)
106
- frame_rgb_small = cv2.cvtColor(frame_bgr_small, cv2.COLOR_BGR2RGB)
107
- image_pil = Image.fromarray(frame_rgb_small)
108
- img_tensor = obj_transform(image_pil).to(device)
109
- with torch.no_grad():
110
- detections = object_detection_model([img_tensor])[0]
111
- threshold = 0.8
112
- boxes = []
113
- object_list = []
114
- for box, score, label in zip(detections["boxes"], detections["scores"], detections["labels"]):
115
- if score > threshold:
116
- boxes.append(tuple(box.int().cpu().numpy()))
117
- label_idx = int(label)
118
- label_name = object_categories[label_idx] if label_idx < len(object_categories) else "Unknown"
119
- object_list.append(f"{label_name} ({score:.2f})")
120
- text = f"Detected {len(boxes)} object(s)" if boxes else "No objects detected"
121
- object_list_text = " | ".join(object_list) if object_list else "None"
122
- return boxes, text, object_list_text
123
-
124
  def compute_faces_overlay(image):
125
  frame_bgr = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
126
  h, w, _ = frame_bgr.shape
@@ -179,8 +143,8 @@ def compute_facemesh_overlay(image):
179
  if start_idx < len(landmark_points) and end_idx < len(landmark_points):
180
  pt1 = landmark_points[start_idx]
181
  pt2 = landmark_points[end_idx]
182
- cv2.line(annotated, pt1, pt2, (0, 0, 255), 1)
183
- cv2.line(mask, pt1, pt2, (0, 0, 255), 1)
184
  # Draw green dots for each landmark
185
  for pt in landmark_points:
186
  cv2.circle(annotated, pt, 2, (0, 255, 0), -1)
@@ -194,7 +158,7 @@ def compute_facemesh_overlay(image):
194
  def analyze_facemesh(image):
195
  annotated_image, mask_image, text = compute_facemesh_overlay(image)
196
  return (annotated_image, mask_image,
197
- f"<div style='color: #ff6347 !important;'>Facemesh Analysis: {text}</div>")
198
 
199
  # -----------------------------
200
  # Main Analysis Functions for Single Image
@@ -210,7 +174,7 @@ def analyze_posture_current(image):
210
  output = current_frame.copy()
211
  if posture_cache["landmarks"]:
212
  output = draw_posture_overlay(output, posture_cache["landmarks"])
213
- return output, f"<div style='color: #ff6347 !important;'>Posture Analysis: {posture_cache['text']}</div>"
214
 
215
  def analyze_emotion_current(image):
216
  global emotion_cache
@@ -219,22 +183,7 @@ def analyze_emotion_current(image):
219
  if emotion_cache["counter"] % SKIP_RATE == 0 or emotion_cache["text"] is None:
220
  text = compute_emotion_overlay(image)
221
  emotion_cache["text"] = text
222
- return current_frame, f"<div style='color: #ff6347 !important;'>Emotion Analysis: {emotion_cache['text']}</div>"
223
-
224
- def analyze_objects_current(image):
225
- global objects_cache
226
- objects_cache["counter"] += 1
227
- current_frame = np.array(image)
228
- if objects_cache["counter"] % SKIP_RATE == 0 or objects_cache["boxes"] is None:
229
- boxes, text, object_list_text = compute_objects_overlay(image)
230
- objects_cache["boxes"] = boxes
231
- objects_cache["text"] = text
232
- objects_cache["object_list_text"] = object_list_text
233
- output = current_frame.copy()
234
- if objects_cache["boxes"]:
235
- output = draw_boxes_overlay(output, objects_cache["boxes"], (255, 255, 0))
236
- combined_text = f"Object Detection: {objects_cache['text']}<br>Details: {objects_cache['object_list_text']}"
237
- return output, f"<div style='color: #ff6347 !important;'>{combined_text}</div>"
238
 
239
  def analyze_faces_current(image):
240
  global faces_cache
@@ -247,62 +196,35 @@ def analyze_faces_current(image):
247
  output = current_frame.copy()
248
  if faces_cache["boxes"]:
249
  output = draw_boxes_overlay(output, faces_cache["boxes"], (0, 0, 255))
250
- return output, f"<div style='color: #ff6347 !important;'>Face Detection: {faces_cache['text']}</div>"
251
-
252
- def analyze_all(image):
253
- current_frame = np.array(image).copy()
254
- landmarks, posture_text = compute_posture_overlay(image)
255
- if landmarks:
256
- current_frame = draw_posture_overlay(current_frame, landmarks)
257
- emotion_text = compute_emotion_overlay(image)
258
- boxes_obj, objects_text, object_list_text = compute_objects_overlay(image)
259
- if boxes_obj:
260
- current_frame = draw_boxes_overlay(current_frame, boxes_obj, (255, 255, 0))
261
- boxes_face, faces_text = compute_faces_overlay(image)
262
- if boxes_face:
263
- current_frame = draw_boxes_overlay(current_frame, boxes_face, (0, 0, 255))
264
- combined_text = (
265
- f"<b>Posture Analysis:</b> {posture_text}<br>"
266
- f"<b>Emotion Analysis:</b> {emotion_text}<br>"
267
- f"<b>Object Detection:</b> {objects_text}<br>"
268
- f"<b>Detected Objects:</b> {object_list_text}<br>"
269
- f"<b>Face Detection:</b> {faces_text}"
270
- )
271
- if object_list_text and object_list_text != "None":
272
- description_text = f"Image Description: The scene features {object_list_text}."
273
- else:
274
- description_text = "Image Description: No prominent objects detected."
275
- combined_text += f"<br><br><div style='border:1px solid #ff6347; padding:10px; box-shadow: 0 0 10px #ff6347;'><b>{description_text}</b></div>"
276
- combined_text_html = f"<div style='color: #ff6347 !important;'>{combined_text}</div>"
277
- return current_frame, combined_text_html
278
 
279
  # -----------------------------
280
- # Custom CSS (Revamped High-Contrast Neon Theme)
281
  # -----------------------------
282
  custom_css = """
283
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
284
  body {
285
  background-color: #121212;
286
  font-family: 'Orbitron', sans-serif;
287
- color: #ffffff;
288
  }
289
  .gradio-container {
290
  background: linear-gradient(135deg, #2d2d2d, #1a1a1a);
291
- border: 2px solid #ff6347;
292
- box-shadow: 0 0 15px #ff6347;
293
  border-radius: 10px;
294
  padding: 20px;
295
  max-width: 1200px;
296
  margin: auto;
297
  }
298
  .gradio-title, .gradio-description, .tab-item, .tab-item * {
299
- color: #ff6347 !important;
300
- text-shadow: 0 0 10px #ff6347;
301
  }
302
  input, button, .output {
303
- border: 1px solid #ff6347;
304
- box-shadow: 0 0 8px #ff6347;
305
- color: #ffffff;
306
  background-color: #1a1a1a;
307
  }
308
  """
@@ -328,15 +250,6 @@ emotion_interface = gr.Interface(
328
  live=False
329
  )
330
 
331
- objects_interface = gr.Interface(
332
- fn=analyze_objects_current,
333
- inputs=gr.Image(label="Upload an Image for Object Detection"),
334
- outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Object Detection")],
335
- title="Objects",
336
- description="Detects objects using a pretrained Faster R-CNN.",
337
- live=False
338
- )
339
-
340
  faces_interface = gr.Interface(
341
  fn=analyze_faces_current,
342
  inputs=gr.Image(label="Upload an Image for Face Detection"),
@@ -346,9 +259,6 @@ faces_interface = gr.Interface(
346
  live=False
347
  )
348
 
349
- # -----------------------------
350
- # New Facemesh Interface (Outputs annotated image and mask)
351
- # -----------------------------
352
  facemesh_interface = gr.Interface(
353
  fn=analyze_facemesh,
354
  inputs=gr.Image(label="Upload an Image for Facemesh"),
@@ -362,31 +272,18 @@ facemesh_interface = gr.Interface(
362
  live=False
363
  )
364
 
365
- all_interface = gr.Interface(
366
- fn=analyze_all,
367
- inputs=gr.Image(label="Upload an Image for All Inferences"),
368
- outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Combined Analysis")],
369
- title="All Inferences",
370
- description="Runs posture, emotion, object, and face detection all at once.",
371
- live=False
372
- )
373
-
374
  tabbed_interface = gr.TabbedInterface(
375
  interface_list=[
376
  posture_interface,
377
  emotion_interface,
378
- objects_interface,
379
  faces_interface,
380
- facemesh_interface,
381
- all_interface
382
  ],
383
  tab_names=[
384
  "Posture",
385
  "Emotion",
386
- "Objects",
387
  "Faces",
388
- "Facemesh",
389
- "All Inferences"
390
  ]
391
  )
392
 
@@ -396,7 +293,7 @@ tabbed_interface = gr.TabbedInterface(
396
  demo = gr.Blocks(css=custom_css)
397
  with demo:
398
  gr.Markdown("<h1 class='gradio-title'>Multi-Analysis Image App</h1>")
399
- gr.Markdown("<p class='gradio-description'>Upload an image to run high-tech analysis for posture, emotions, objects, faces, and facemesh landmarks.</p>")
400
  tabbed_interface.render()
401
 
402
  if __name__ == "__main__":
 
1
  import gradio as gr
2
  import cv2
3
  import numpy as np
 
 
 
4
  from PIL import Image
5
  import mediapipe as mp
6
  from fer import FER # Facial emotion recognition
 
9
  # Configuration
10
  # -----------------------------
11
  SKIP_RATE = 1 # For image processing, always run the analysis
 
12
  DESIRED_SIZE = (640, 480)
13
 
14
  # -----------------------------
 
16
  # -----------------------------
17
  posture_cache = {"landmarks": None, "text": "Initializing...", "counter": 0}
18
  emotion_cache = {"text": "Initializing...", "counter": 0}
 
19
  faces_cache = {"boxes": None, "text": "Initializing...", "counter": 0}
20
 
21
  # -----------------------------
 
29
  mp_face_detection = mp.solutions.face_detection
30
  face_detection = mp_face_detection.FaceDetection(min_detection_confidence=0.5)
31
 
 
 
 
 
 
 
 
32
  # Initialize the FER emotion detector (using the FER package)
33
  emotion_detector = FER(mtcnn=True)
34
 
 
 
 
35
  # -----------------------------
36
  # Overlay Drawing Functions
37
  # -----------------------------
 
85
  text = "No face detected"
86
  return text
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  def compute_faces_overlay(image):
89
  frame_bgr = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
90
  h, w, _ = frame_bgr.shape
 
143
  if start_idx < len(landmark_points) and end_idx < len(landmark_points):
144
  pt1 = landmark_points[start_idx]
145
  pt2 = landmark_points[end_idx]
146
+ cv2.line(annotated, pt1, pt2, (255, 0, 0), 1)
147
+ cv2.line(mask, pt1, pt2, (255, 0, 0), 1)
148
  # Draw green dots for each landmark
149
  for pt in landmark_points:
150
  cv2.circle(annotated, pt, 2, (0, 255, 0), -1)
 
158
  def analyze_facemesh(image):
159
  annotated_image, mask_image, text = compute_facemesh_overlay(image)
160
  return (annotated_image, mask_image,
161
+ f"<div style='color: #00ff00 !important;'>Facemesh Analysis: {text}</div>")
162
 
163
  # -----------------------------
164
  # Main Analysis Functions for Single Image
 
174
  output = current_frame.copy()
175
  if posture_cache["landmarks"]:
176
  output = draw_posture_overlay(output, posture_cache["landmarks"])
177
+ return output, f"<div style='color: #00ff00 !important;'>Posture Analysis: {posture_cache['text']}</div>"
178
 
179
  def analyze_emotion_current(image):
180
  global emotion_cache
 
183
  if emotion_cache["counter"] % SKIP_RATE == 0 or emotion_cache["text"] is None:
184
  text = compute_emotion_overlay(image)
185
  emotion_cache["text"] = text
186
+ return current_frame, f"<div style='color: #00ff00 !important;'>Emotion Analysis: {emotion_cache['text']}</div>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
  def analyze_faces_current(image):
189
  global faces_cache
 
196
  output = current_frame.copy()
197
  if faces_cache["boxes"]:
198
  output = draw_boxes_overlay(output, faces_cache["boxes"], (0, 0, 255))
199
+ return output, f"<div style='color: #00ff00 !important;'>Face Detection: {faces_cache['text']}</div>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
  # -----------------------------
202
+ # Custom CSS (Revamped High-Contrast Neon Theme with Green Glows)
203
  # -----------------------------
204
  custom_css = """
205
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
206
  body {
207
  background-color: #121212;
208
  font-family: 'Orbitron', sans-serif;
209
+ color: #00ff00;
210
  }
211
  .gradio-container {
212
  background: linear-gradient(135deg, #2d2d2d, #1a1a1a);
213
+ border: 2px solid #00ff00;
214
+ box-shadow: 0 0 15px #00ff00;
215
  border-radius: 10px;
216
  padding: 20px;
217
  max-width: 1200px;
218
  margin: auto;
219
  }
220
  .gradio-title, .gradio-description, .tab-item, .tab-item * {
221
+ color: #00ff00 !important;
222
+ text-shadow: 0 0 10px #00ff00;
223
  }
224
  input, button, .output {
225
+ border: 1px solid #00ff00;
226
+ box-shadow: 0 0 8px #00ff00;
227
+ color: #00ff00;
228
  background-color: #1a1a1a;
229
  }
230
  """
 
250
  live=False
251
  )
252
 
 
 
 
 
 
 
 
 
 
253
  faces_interface = gr.Interface(
254
  fn=analyze_faces_current,
255
  inputs=gr.Image(label="Upload an Image for Face Detection"),
 
259
  live=False
260
  )
261
 
 
 
 
262
  facemesh_interface = gr.Interface(
263
  fn=analyze_facemesh,
264
  inputs=gr.Image(label="Upload an Image for Facemesh"),
 
272
  live=False
273
  )
274
 
 
 
 
 
 
 
 
 
 
275
  tabbed_interface = gr.TabbedInterface(
276
  interface_list=[
277
  posture_interface,
278
  emotion_interface,
 
279
  faces_interface,
280
+ facemesh_interface
 
281
  ],
282
  tab_names=[
283
  "Posture",
284
  "Emotion",
 
285
  "Faces",
286
+ "Facemesh"
 
287
  ]
288
  )
289
 
 
293
  demo = gr.Blocks(css=custom_css)
294
  with demo:
295
  gr.Markdown("<h1 class='gradio-title'>Multi-Analysis Image App</h1>")
296
+ gr.Markdown("<p class='gradio-description'>Upload an image to run high-tech analysis for posture, emotions, faces, and facemesh landmarks.</p>")
297
  tabbed_interface.render()
298
 
299
  if __name__ == "__main__":