Spaces:
Sleeping
Sleeping
| # 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. | |
| """) | |