Muscle_Memory / app.py
zforkash's picture
u2
cc46889 verified
# Streamlit App for Workout Tracker
import streamlit as st
import cv2
import mediapipe as mp
import numpy as np
import time
from sklearn.ensemble import IsolationForest
# Title and Introduction
st.title("Muscle Memory")
st.markdown("""
Welcome to the **Workout Tracker App**!
Select your desired workout below, and the app will guide you through the exercise with real-time feedback.
""")
# Workout Options
st.header("Choose Your Workout")
workout_option = st.selectbox(
"Available Workouts:",
["Bicep Curl", "Lateral Raise", "Shoulder Press"]
)
# Mediapipe utilities
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose
# Helper Functions
def calculate_angle(a, b, c):
"""Calculate the angle between three points."""
a = np.array(a)
b = np.array(b)
c = np.array(c)
radians = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0])
angle = np.abs(np.degrees(radians))
if angle > 180.0:
angle = 360 - angle
return angle
def draw_text_with_background(image, text, position, font, font_scale, color, thickness, bg_color, padding=10):
"""Draw text with a background on an image."""
text_size = cv2.getTextSize(text, font, font_scale, thickness)[0]
text_x, text_y = position
box_coords = (
(text_x - padding, text_y - padding),
(text_x + text_size[0] + padding, text_y + text_size[1] + padding),
)
cv2.rectangle(image, box_coords[0], box_coords[1], bg_color, cv2.FILLED)
cv2.putText(image, text, (text_x, text_y + text_size[1]), font, font_scale, color, thickness)
# Main Function to Track Workout
def track_workout():
cap = cv2.VideoCapture(0)
counter = 0 # Rep counter
stage = None # Movement stage
max_reps = 10 # Max reps
feedback = "" # Real-time feedback for the video feed
with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose:
while cap.isOpened():
ret, frame = cap.read()
if not ret:
st.error("Failed to access the webcam. Please ensure your webcam is enabled.")
break
# Convert frame to RGB
image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image.flags.writeable = False
results = pose.process(image)
# Convert back to BGR
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
# Check if pose landmarks are detected
if results.pose_landmarks:
landmarks = results.pose_landmarks.landmark
# Extract key joints
shoulder = [
landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x,
landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y,
]
elbow = [
landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].x,
landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].y,
]
wrist = [
landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].x,
landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].y,
]
# Calculate the angle
angle = calculate_angle(shoulder, elbow, wrist)
# Stage logic for counting reps
if angle > 160 and stage != "down":
stage = "down"
elif angle < 40 and stage == "down":
stage = "up"
counter += 1
# Feedback
if counter == max_reps:
feedback = "Workout Complete!"
break
else:
feedback = f"Rep {counter} completed!"
# Draw the feedback on the frame
draw_text_with_background(image, f"Reps: {counter}", (50, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, (0, 0, 0))
draw_text_with_background(image, feedback, (50, 100),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, (0, 0, 0))
# Draw landmarks
mp_drawing.draw_landmarks(
image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS,
mp_drawing.DrawingSpec(color=(245, 117, 66), thickness=2, circle_radius=2),
mp_drawing.DrawingSpec(color=(245, 66, 230), thickness=2, circle_radius=2)
)
# Display the video feed
cv2.imshow("Workout Tracker", image)
# Break if 'q' is pressed
if cv2.waitKey(10) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
# Button to Start the Workout
if st.button("Start Workout"):
st.write(f"Starting {workout_option} workout...")
track_workout()
# Footer
st.markdown("""
---
**Note**: Press "q" in the webcam feed to stop the workout. Ensure your webcam is enabled.
""")