build a web app that uses the camera that detects human and shows the skeleton detected (like a virtual mirror). The screen should show the camera feed and the skeletone should be presented over the camera canvas in real time. Make use of mediapipe (MediaPipe BlazePose GHUM model) libraries. Show each skeleton line and add to it the REAL cm length. use the shoulder length of 35 cm as scale and overlay on the screen in real-time. make use of the 3d ponts (x,y,z) for the distance.
To upload files, please first save the app
import streamlit as st
import mediapipe as mp
import cv2
import numpy as np
from PIL import Image
# Initialize MediaPipe Pose
mp_pose = mp.solutions.pose
mp_drawing = mp.solutions.drawing_utils
pose = mp_pose.Pose(
min_detection_confidence=0.5,
min_tracking_confidence=0.5,
model_complexity=1
)
# Function to calculate distance between 3D points
def calculate_distance(point1, point2):
return np.sqrt(
(point1.x - point2.x)**2 +
(point1.y - point2.y)**2 +
(point1.z - point2.z)**2
)
# Function to convert normalized distance to cm using shoulder width as reference
def normalize_distance(distance, shoulder_distance):
REFERENCE_SHOULDER_WIDTH_CM = 35.0 # Average shoulder width in cm
scale = REFERENCE_SHOULDER_WIDTH_CM / shoulder_distance
return distance * scale
# Define the connections we want to measure
CONNECTIONS_TO_MEASURE = [
(mp_pose.PoseLandmark.LEFT_SHOULDER, mp_pose.PoseLandmark.RIGHT_SHOULDER, "Shoulder Width"),
(mp_pose.PoseLandmark.LEFT_SHOULDER, mp_pose.PoseLandmark.LEFT_ELBOW, "Left Upper Arm"),
(mp_pose.PoseLandmark.RIGHT_SHOULDER, mp_pose.PoseLandmark.RIGHT_ELBOW, "Right Upper Arm"),
(mp_pose.PoseLandmark.LEFT_ELBOW, mp_pose.PoseLandmark.LEFT_WRIST, "Left Lower Arm"),
(mp_pose.PoseLandmark.RIGHT_ELBOW, mp_pose.PoseLandmark.RIGHT_WRIST, "Right Lower Arm"),
(mp_pose.PoseLandmark.LEFT_HIP, mp_pose.PoseLandmark.RIGHT_HIP, "Hip Width"),
(mp_pose.PoseLandmark.LEFT_HIP, mp_pose.PoseLandmark.LEFT_KNEE, "Left Upper Leg"),
(mp_pose.PoseLandmark.RIGHT_HIP, mp_pose.PoseLandmark.RIGHT_KNEE, "Right Upper Leg"),
(mp_pose.PoseLandmark.LEFT_KNEE, mp_pose.PoseLandmark.LEFT_ANKLE, "Left Lower Leg"),
(mp_pose.PoseLandmark.RIGHT_KNEE, mp_pose.PoseLandmark.RIGHT_ANKLE, "Right Lower Leg"),
]
st.title("Real-time Body Measurements")
st.write("Stand in front of the camera to see your body measurements")
# Initialize the webcam
camera = st.camera_input("Take a picture")
if camera is not None:
# Convert the image from bytes to numpy array
bytes_data = camera.getvalue()
image = cv2.imdecode(np.frombuffer(bytes_data, np.uint8), cv2.IMREAD_COLOR)
# Convert BGR to RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Process the image and get pose landmarks
results = pose.process(image_rgb)
if results.pose_landmarks:
# Draw the pose landmarks on the image
annotated_image = image_rgb.copy()
mp_drawing.draw_landmarks(
annotated_image,
results.pose_landmarks,
mp_pose.POSE_CONNECTIONS
)
# Calculate shoulder width as reference
left_shoulder = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_SHOULDER]
right_shoulder = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_SHOULDER]
shoulder_distance = calculate_distance(left_shoulder, right_shoulder)
# Draw measurements for each connection
for start_point, end_point, name in CONNECTIONS_TO_MEASURE:
start = results.pose_landmarks.landmark[start_point]
end = results.pose_landmarks.landmark[end_point]
# Calculate distance and convert to cm
distance = calculate_distance(start, end)
distance_cm = normalize_distance(distance, shoulder_distance)
# Calculate midpoint for text placement
mid_x = int((start.x + end.x) * image.shape[1] / 2)
mid_y = int((start.y + end.y) * image.shape[0] / 2)
# Draw the measurement text
cv2.putText(
annotated_image,
f"{distance_cm:.1f}cm",
(mid_x, mid_y),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
(255, 255, 255),
2
)
# Display the annotated image
st.image(annotated_image, channels="RGB", use_column_width=True)
else:
st.warning("No pose detected. Please make sure your full body is visible in the camera.")
st.markdown("""
### Instructions:
1. Stand about 2-3 meters away from the camera
2. Make sure your full body is visible
3. The measurements will be shown in real-time
4. Measurements are approximate and use shoulder width (35cm) as reference
""")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?