srivatsavdamaraju's picture
Update app.py
d871c13 verified
raw
history blame
6.51 kB
import streamlit as st
import cv2
import mediapipe as mp
import matplotlib.pyplot as plt
import numpy as np
# Define the function to calculate angle between the legs
def angle_between_the_legs(image):
"""
Calculate the angle between the legs using MediaPipe pose estimation.
Args:
image: Input image in BGR format.
Returns:
A tuple containing:
- The annotated image with visualization
- Left leg angle (degrees)
- Right leg angle (degrees)
- Angle between legs (degrees)
"""
# Initialize MediaPipe Pose
mp_pose = mp.solutions.pose
mp_drawing = mp.solutions.drawing_utils
# Convert the image to RGB (MediaPipe requires RGB images)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Initialize the Pose model
with mp_pose.Pose(static_image_mode=True, model_complexity=2, enable_segmentation=False) as pose:
# Process the image
results = pose.process(image_rgb)
# Check if pose landmarks were detected
if not results.pose_landmarks:
print("No pose landmarks detected.")
return image, None, None, None
# Create a copy of the image for annotation
annotated_image = image.copy()
# Get landmark coordinates
landmarks = results.pose_landmarks.landmark
# Get relevant landmarks for angle calculation
# Center hip point (mid-point between left and right hip)
mid_hip_x = (landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].x +
landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].x) / 2
mid_hip_y = (landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y +
landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].y) / 2
# Get image dimensions for converting normalized coordinates
h, w, _ = annotated_image.shape
mid_hip = (int(mid_hip_x * w), int(mid_hip_y * h))
# Get coordinates for left and right ankles
left_ankle = (int(landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].x * w),
int(landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].y * h))
right_ankle = (int(landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value].x * w),
int(landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value].y * h))
# Draw the center vertical line from mid-hip down
center_bottom = (mid_hip[0], h)
cv2.line(annotated_image, mid_hip, center_bottom, (0, 255, 255), 2)
# Draw lines from mid-hip to each ankle
cv2.line(annotated_image, mid_hip, left_ankle, (255, 0, 0), 2) # Blue line to left ankle
cv2.line(annotated_image, mid_hip, right_ankle, (0, 0, 255), 2) # Red line to right ankle
# Calculate vectors
# Vector for center line (pointing down)
center_vector = np.array([0, 1]) # Vertical down
# Vector for left leg
left_leg_vector = np.array([left_ankle[0] - mid_hip[0], left_ankle[1] - mid_hip[1]])
if np.linalg.norm(left_leg_vector) > 0:
left_leg_vector = left_leg_vector / np.linalg.norm(left_leg_vector)
# Vector for right leg
right_leg_vector = np.array([right_ankle[0] - mid_hip[0], right_ankle[1] - mid_hip[1]])
if np.linalg.norm(right_leg_vector) > 0:
right_leg_vector = right_leg_vector / np.linalg.norm(right_leg_vector)
# Calculate angles using dot product: angle = arccos(dot(v1, v2))
# Note: We're using the normalized vectors for angle calculation
left_angle_rad = np.arccos(np.clip(np.dot(center_vector, left_leg_vector), -1.0, 1.0))
right_angle_rad = np.arccos(np.clip(np.dot(center_vector, right_leg_vector), -1.0, 1.0))
# Convert to degrees
left_angle_deg = np.degrees(left_angle_rad)
right_angle_deg = np.degrees(right_angle_rad)
# If left ankle is to the left of center, the angle is negative
if left_ankle[0] < mid_hip[0]:
left_angle_deg = -left_angle_deg
# If right ankle is to the right of center, the angle is positive
if right_ankle[0] > mid_hip[0]:
right_angle_deg = right_angle_deg
else:
right_angle_deg = -right_angle_deg
# Calculate the total angle between legs
angle_between_legs = 2 * (abs(left_angle_deg) + abs(right_angle_deg))
# Add text annotations with angle values
cv2.putText(annotated_image, f"Left angle: {left_angle_deg:.1f}°",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
cv2.putText(annotated_image, f"Right angle: {right_angle_deg:.1f}°",
(10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(annotated_image, f"Total angle: {angle_between_legs:.1f}°",
(10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# Add marker for center hip point
cv2.circle(annotated_image, mid_hip, 5, (255, 255, 0), -1)
# Draw pose landmarks on the image
mp_drawing.draw_landmarks(
annotated_image,
results.pose_landmarks,
mp_pose.POSE_CONNECTIONS,
landmark_drawing_spec=mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2, circle_radius=2),
connection_drawing_spec=mp_drawing.DrawingSpec(color=(255, 0, 0), thickness=2))
# Convert the annotated image back to RGB for display
annotated_image_rgb = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)
return annotated_image_rgb, left_angle_deg, right_angle_deg, angle_between_legs
# Streamlit app
st.title("Leg Angle Calculation using MediaPipe")
# Image uploader
uploaded_file = st.file_uploader("Upload an Image", type=["png", "jpg", "jpeg"])
if uploaded_file is not None:
# Read the image from the uploaded file
image = np.array(bytearray(uploaded_file.read()), dtype=np.uint8)
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
# Get the leg angle analysis
annotated_image_rgb, left_angle, right_angle, total_angle = angle_between_the_legs(image)
if annotated_image_rgb is not None:
# Display the annotated image
st.image(annotated_image_rgb, caption=f"Leg Angle Analysis: Total = {total_angle:.1f}°", use_column_width=True)
# Print the results
st.write(f"Left leg angle: {left_angle:.1f}°")
st.write(f"Right leg angle: {right_angle:.1f}°")
st.write(f"Total angle between legs: {total_angle:.1f}°")