David Driscoll commited on
Commit
0b4ab6d
·
1 Parent(s): 4f14988
Files changed (1) hide show
  1. app.py +60 -30
app.py CHANGED
@@ -4,6 +4,9 @@ import numpy as np
4
  from PIL import Image
5
  import mediapipe as mp
6
  from fer import FER # Facial emotion recognition
 
 
 
7
 
8
  # -----------------------------
9
  # Configuration
@@ -11,6 +14,17 @@ from fer import FER # Facial emotion recognition
11
  SKIP_RATE = 1 # For image processing, always run the analysis
12
  DESIRED_SIZE = (640, 480)
13
 
 
 
 
 
 
 
 
 
 
 
 
14
  # -----------------------------
15
  # Global caches for overlay info and frame counters
16
  # -----------------------------
@@ -21,17 +35,20 @@ faces_cache = {"boxes": None, "text": "Initializing...", "counter": 0}
21
  # -----------------------------
22
  # Initialize Models and Helpers
23
  # -----------------------------
24
- # MediaPipe Pose, Face Detection, and Face Mesh
25
  mp_pose = mp.solutions.pose
26
  pose = mp_pose.Pose()
27
  mp_drawing = mp.solutions.drawing_utils
28
 
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
  # -----------------------------
@@ -86,21 +103,18 @@ def compute_emotion_overlay(image):
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
91
- frame_bgr_small = cv2.resize(frame_bgr, DESIRED_SIZE)
92
- small_h, small_w, _ = frame_bgr_small.shape
93
- frame_rgb_small = cv2.cvtColor(frame_bgr_small, cv2.COLOR_BGR2RGB)
94
- face_results = face_detection.process(frame_rgb_small)
 
95
  boxes = []
96
- if face_results.detections:
97
- for detection in face_results.detections:
98
- bbox = detection.location_data.relative_bounding_box
99
- x = int(bbox.xmin * small_w)
100
- y = int(bbox.ymin * small_h)
101
- box_w = int(bbox.width * small_w)
102
- box_h = int(bbox.height * small_h)
103
- boxes.append((x, y, x + box_w, y + box_h))
104
  text = f"Detected {len(boxes)} face(s)"
105
  else:
106
  text = "No faces detected"
@@ -157,8 +171,11 @@ def compute_facemesh_overlay(image):
157
 
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
@@ -203,11 +220,13 @@ def analyze_faces_current(image):
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;
@@ -217,10 +236,13 @@ body {
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;
@@ -236,8 +258,9 @@ posture_interface = gr.Interface(
236
  fn=analyze_posture_current,
237
  inputs=gr.Image(label="Upload an Image for Posture Analysis"),
238
  outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Posture Analysis")],
239
- title="Posture",
240
- description="Detects your posture using MediaPipe with connector lines.",
 
241
  live=False
242
  )
243
 
@@ -245,8 +268,9 @@ emotion_interface = gr.Interface(
245
  fn=analyze_emotion_current,
246
  inputs=gr.Image(label="Upload an Image for Emotion Analysis"),
247
  outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Emotion Analysis")],
248
- title="Emotion",
249
- description="Detects facial emotions using FER.",
 
250
  live=False
251
  )
252
 
@@ -254,8 +278,9 @@ faces_interface = gr.Interface(
254
  fn=analyze_faces_current,
255
  inputs=gr.Image(label="Upload an Image for Face Detection"),
256
  outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Face Detection")],
257
- title="Faces",
258
- description="Detects faces using MediaPipe.",
 
259
  live=False
260
  )
261
 
@@ -267,8 +292,9 @@ facemesh_interface = gr.Interface(
267
  gr.Image(type="numpy", label="Mask Output"),
268
  gr.HTML(label="Facemesh Analysis")
269
  ],
270
- title="Facemesh",
271
- description="Detects facial landmarks using MediaPipe Face Mesh and outputs both an annotated image and a mask on a black background.",
 
272
  live=False
273
  )
274
 
@@ -294,6 +320,10 @@ 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__":
 
4
  from PIL import Image
5
  import mediapipe as mp
6
  from fer import FER # Facial emotion recognition
7
+ from ultralytics import YOLO # YOLOv8 for face detection
8
+ from huggingface_hub import hf_hub_download
9
+ from supervision import Detections
10
 
11
  # -----------------------------
12
  # Configuration
 
14
  SKIP_RATE = 1 # For image processing, always run the analysis
15
  DESIRED_SIZE = (640, 480)
16
 
17
+ # -----------------------------
18
+ # Sample Images (Preset Suggested Photos)
19
+ # -----------------------------
20
+ SAMPLE_IMAGES = [
21
+ "https://upload.wikimedia.org/wikipedia/commons/7/76/Daniel_Diermeier_2020_%28cropped%29.jpg",
22
+ "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Gilbert_Stuart_Williamstown_Portrait_of_George_Washington.jpg/1200px-Gilbert_Stuart_Williamstown_Portrait_of_George_Washington.jpg",
23
+ "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/President_Barack_Obama.jpg/800px-President_Barack_Obama.jpg",
24
+ "https://images.wsj.net/im-98527587?width=1280&size=1",
25
+ "https://media.npr.org/assets/img/2023/11/28/dr.buolamwiniheadshot_c-naima-green-1-_custom-05cd4ce4570c688d00cc558d16c76745abd07539.png"
26
+ ]
27
+
28
  # -----------------------------
29
  # Global caches for overlay info and frame counters
30
  # -----------------------------
 
35
  # -----------------------------
36
  # Initialize Models and Helpers
37
  # -----------------------------
38
+ # MediaPipe Pose and Drawing
39
  mp_pose = mp.solutions.pose
40
  pose = mp_pose.Pose()
41
  mp_drawing = mp.solutions.drawing_utils
42
 
 
 
 
43
  # Initialize the FER emotion detector (using the FER package)
44
  emotion_detector = FER(mtcnn=True)
45
 
46
+ # -----------------------------
47
+ # Download YOLOv8 face detection model from Hugging Face
48
+ # -----------------------------
49
+ model_path = hf_hub_download(repo_id="arnabdhar/YOLOv8-Face-Detection", filename="model.pt")
50
+ yolo_face_model = YOLO(model_path)
51
+
52
  # -----------------------------
53
  # Overlay Drawing Functions
54
  # -----------------------------
 
103
  return text
104
 
105
  def compute_faces_overlay(image):
106
+ """
107
+ Uses the YOLOv8 face detection model from Hugging Face.
108
+ Processes the input image and returns bounding boxes using Supervision Detections.
109
+ """
110
+ pil_image = image if isinstance(image, Image.Image) else Image.fromarray(image)
111
+ output = yolo_face_model(pil_image)
112
+ results = Detections.from_ultralytics(output[0])
113
  boxes = []
114
+ if results.xyxy.shape[0] > 0:
115
+ for box in results.xyxy:
116
+ x1, y1, x2, y2 = map(int, box)
117
+ boxes.append((x1, y1, x2, y2))
 
 
 
 
118
  text = f"Detected {len(boxes)} face(s)"
119
  else:
120
  text = "No faces detected"
 
171
 
172
  def analyze_facemesh(image):
173
  annotated_image, mask_image, text = compute_facemesh_overlay(image)
174
+ return (
175
+ annotated_image,
176
+ mask_image,
177
+ f"<div style='color: #00ff00 !important;'>Facemesh Analysis: {text}</div>"
178
+ )
179
 
180
  # -----------------------------
181
  # Main Analysis Functions for Single Image
 
220
  # -----------------------------
221
  custom_css = """
222
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
223
+
224
  body {
225
  background-color: #121212;
226
  font-family: 'Orbitron', sans-serif;
227
+ color: #00ff00 !important;
228
  }
229
+
230
  .gradio-container {
231
  background: linear-gradient(135deg, #2d2d2d, #1a1a1a);
232
  border: 2px solid #00ff00;
 
236
  max-width: 1200px;
237
  margin: auto;
238
  }
239
+
240
+ .gradio-title, .gradio-description, .tab-item, .tab-item *,
241
+ label, .label, .wrap .label, .wrap .input, .wrap .output, .wrap .description {
242
  color: #00ff00 !important;
243
  text-shadow: 0 0 10px #00ff00;
244
  }
245
+
246
  input, button, .output {
247
  border: 1px solid #00ff00;
248
  box-shadow: 0 0 8px #00ff00;
 
258
  fn=analyze_posture_current,
259
  inputs=gr.Image(label="Upload an Image for Posture Analysis"),
260
  outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Posture Analysis")],
261
+ title="<div style='color:#00ff00;'>Posture",
262
+ description="<div style='color:#00ff00;'>Detects posture using MediaPipe with connector lines.</div>",
263
+ examples=SAMPLE_IMAGES, # clickable examples at bottom
264
  live=False
265
  )
266
 
 
268
  fn=analyze_emotion_current,
269
  inputs=gr.Image(label="Upload an Image for Emotion Analysis"),
270
  outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Emotion Analysis")],
271
+ title="<div style='color:#00ff00;'>Emotion",
272
+ description="<div style='color:#00ff00;'>Detects facial emotions using FER.</div>",
273
+ examples=SAMPLE_IMAGES,
274
  live=False
275
  )
276
 
 
278
  fn=analyze_faces_current,
279
  inputs=gr.Image(label="Upload an Image for Face Detection"),
280
  outputs=[gr.Image(type="numpy", label="Annotated Output"), gr.HTML(label="Face Detection")],
281
+ title="<div style='color:#00ff00;'>Faces",
282
+ description="<div style='color:#00ff00;'>Detects faces using fine-tuned YOLOv8 model.</div>",
283
+ examples=SAMPLE_IMAGES,
284
  live=False
285
  )
286
 
 
292
  gr.Image(type="numpy", label="Mask Output"),
293
  gr.HTML(label="Facemesh Analysis")
294
  ],
295
+ title="<div style='color:#00ff00;'>Facemesh",
296
+ description="<div style='color:#00ff00;'>Detects facial landmarks using MediaPipe Face Mesh.</div>",
297
+ examples=SAMPLE_IMAGES,
298
  live=False
299
  )
300
 
 
320
  with demo:
321
  gr.Markdown("<h1 class='gradio-title'>Multi-Analysis Image App</h1>")
322
  gr.Markdown("<p class='gradio-description'>Upload an image to run high-tech analysis for posture, emotions, faces, and facemesh landmarks.</p>")
323
+
324
+ # We removed the top-row sample images and now rely on
325
+ # the built-in Gradio examples at the bottom of each tab.
326
+
327
  tabbed_interface.render()
328
 
329
  if __name__ == "__main__":