Face_Body_Mask / app.py
David Driscoll
Start
568b799
raw
history blame
4.84 kB
import cv2
import mediapipe as mp
import numpy as np
import gradio as gr
# Initialize MediaPipe Pose.
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(
static_image_mode=False,
model_complexity=1,
enable_segmentation=False,
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)
# Initialize MediaPipe Face Mesh.
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(
static_image_mode=False,
max_num_faces=1,
refine_landmarks=True,
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)
def process_frame(image):
"""
Processes an input image (from the webcam) by:
1. Converting from RGB (Gradio default) to BGR for OpenCV.
2. Flipping the frame for a mirror view.
3. Creating a black background.
4. Using MediaPipe Pose to draw body landmarks (excluding facial parts) and compute the shoulder center.
5. Using MediaPipe Face Mesh to draw the full facial mesh and extract the chin point.
6. Drawing a neck line from the shoulder center to the chin.
7. Converting the result back to RGB for display.
"""
# Convert the input image from RGB (Gradio default) to BGR.
frame = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
# Flip the frame horizontally for a mirror view.
frame = cv2.flip(frame, 1)
# Create a black background image of the same size.
output = np.zeros_like(frame)
# Convert frame to RGB for MediaPipe processing.
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# --- Body Posture Analysis using MediaPipe Pose ---
pose_results = pose.process(rgb_frame)
shoulder_center = None
if pose_results.pose_landmarks:
h, w, _ = frame.shape
landmarks = [(int(lm.x * w), int(lm.y * h)) for lm in pose_results.pose_landmarks.landmark]
# Draw body skeleton (only drawing non-facial landmarks, i.e. indices 11 and above).
for connection in mp_pose.POSE_CONNECTIONS:
start_idx, end_idx = connection
if start_idx >= 11 and end_idx >= 11:
if start_idx < len(landmarks) and end_idx < len(landmarks):
cv2.line(output, landmarks[start_idx], landmarks[end_idx], (255, 255, 0), 2)
# Draw landmarks as yellow circles.
for i, pt in enumerate(landmarks):
if i >= 11:
cv2.circle(output, pt, 3, (255, 255, 0), -1)
# Calculate shoulder center using landmarks 11 (left shoulder) and 12 (right shoulder).
if len(landmarks) > 12:
left_shoulder = landmarks[11]
right_shoulder = landmarks[12]
shoulder_center = ((left_shoulder[0] + right_shoulder[0]) // 2,
(left_shoulder[1] + right_shoulder[1]) // 2)
cv2.circle(output, shoulder_center, 4, (0, 255, 255), -1)
# --- Facemesh Analysis using MediaPipe Face Mesh ---
chin_point = None
fm_results = face_mesh.process(rgb_frame)
if fm_results.multi_face_landmarks:
for face_landmarks in fm_results.multi_face_landmarks:
h, w, _ = frame.shape
fm_points = [(int(lm.x * w), int(lm.y * h)) for lm in face_landmarks.landmark]
# Draw red lines connecting facial landmarks.
for connection in mp_face_mesh.FACEMESH_TESSELATION:
start_idx, end_idx = connection
if start_idx < len(fm_points) and end_idx < len(fm_points):
cv2.line(output, fm_points[start_idx], fm_points[end_idx], (0, 0, 255), 1)
# Draw green dots for each facial landmark.
for pt in fm_points:
cv2.circle(output, pt, 2, (0, 255, 0), -1)
# Extract the chin point (landmark 152 is generally at the bottom of the chin).
if len(face_landmarks.landmark) > 152:
lm = face_landmarks.landmark[152]
chin_point = (int(lm.x * w), int(lm.y * h))
cv2.circle(output, chin_point, 4, (0, 0, 255), -1)
break # Process only the first detected face.
# --- Draw the Neck Line ---
if shoulder_center and chin_point:
cv2.line(output, shoulder_center, chin_point, (0, 255, 255), 2)
# Convert the processed image back to RGB for display.
output_rgb = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)
return output_rgb
# Create the Gradio interface.
iface = gr.Interface(
fn=process_frame,
inputs=gr.Image(source="webcam", type="numpy", label="Webcam"),
outputs=gr.Image(type="numpy", label="Processed Output"),
live=True,
title="Body Posture & Neck Analysis (No Face Pose)",
description="Webcam-based analysis using MediaPipe Pose and Face Mesh."
)
# Launch the Gradio app.
iface.launch()