smurar commited on
Commit
6700c1a
·
verified ·
1 Parent(s): 43f44ab

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -0
app.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import mediapipe as mp
3
+ import numpy as np
4
+ import gradio as gr
5
+
6
+ # Initialize MediaPipe Pose and drawing utils.
7
+ mp_pose = mp.solutions.pose
8
+ pose = mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5)
9
+ mp_drawing = mp.solutions.drawing_utils
10
+
11
+ # Calculate angle between three points.
12
+ def calculate_angle(a, b, c):
13
+ a, b, c = np.array(a), np.array(b), np.array(c)
14
+ radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - np.arctan2(a[1]-b[1], a[0]-b[0])
15
+ angle = np.abs(radians * 180.0 / np.pi)
16
+ return angle
17
+
18
+ # Process the video and overlay pushup feedback.
19
+ def analyze_pushups(video_path):
20
+ cap = cv2.VideoCapture(video_path)
21
+ frame_width = int(cap.get(3))
22
+ frame_height = int(cap.get(4))
23
+ fps = cap.get(cv2.CAP_PROP_FPS) if cap.get(cv2.CAP_PROP_FPS) > 0 else 30
24
+
25
+ output_video = "output_pushup.mp4"
26
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
27
+ out = cv2.VideoWriter(output_video, fourcc, fps, (frame_width, frame_height))
28
+
29
+ # Check pushup form based on elbow angles.
30
+ def check_pushup_feedback(landmarks):
31
+ def get_landmark(part):
32
+ return [landmarks[part].x, landmarks[part].y]
33
+ left_shoulder = get_landmark(mp_pose.PoseLandmark.LEFT_SHOULDER)
34
+ left_elbow = get_landmark(mp_pose.PoseLandmark.LEFT_ELBOW)
35
+ left_wrist = get_landmark(mp_pose.PoseLandmark.LEFT_WRIST)
36
+ right_shoulder = get_landmark(mp_pose.PoseLandmark.RIGHT_SHOULDER)
37
+ right_elbow = get_landmark(mp_pose.PoseLandmark.RIGHT_ELBOW)
38
+ right_wrist = get_landmark(mp_pose.PoseLandmark.RIGHT_WRIST)
39
+ left_elbow_angle = calculate_angle(left_shoulder, left_elbow, left_wrist)
40
+ right_elbow_angle = calculate_angle(right_shoulder, right_elbow, right_wrist)
41
+ avg_elbow_angle = (left_elbow_angle + right_elbow_angle) / 2
42
+ accuracy = max(0, min(100, (1 - abs(avg_elbow_angle - 90) / 45) * 100))
43
+ feedback = "Correct Push-Up" if 45 <= avg_elbow_angle <= 120 else "Incorrect Form"
44
+ if avg_elbow_angle < 45:
45
+ feedback += " - Go Higher"
46
+ elif avg_elbow_angle > 120:
47
+ feedback += " - Lower Your Chest"
48
+ return feedback, int(accuracy)
49
+
50
+ # Draw feedback and an accuracy bar on the frame.
51
+ def draw_feedback(image, accuracy, feedback):
52
+ bar_x, bar_y, bar_width, bar_height = 50, 400, 200, 20
53
+ fill_width = int((accuracy / 100) * bar_width)
54
+ cv2.rectangle(image, (bar_x, bar_y), (bar_x + bar_width, bar_y + bar_height), (200, 200, 200), 2)
55
+ cv2.rectangle(image, (bar_x, bar_y), (bar_x + fill_width, bar_y + bar_height), (0, 255, 0), -1)
56
+ cv2.putText(image, f"Accuracy: {accuracy}%", (bar_x, bar_y - 10),
57
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
58
+ color = (0, 255, 0) if "Correct" in feedback else (0, 0, 255)
59
+ cv2.putText(image, feedback, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 3)
60
+
61
+ while cap.isOpened():
62
+ ret, frame = cap.read()
63
+ if not ret:
64
+ break
65
+ # Process frame with MediaPipe.
66
+ image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
67
+ results = pose.process(image)
68
+ image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
69
+ if results.pose_landmarks:
70
+ mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
71
+ feedback, accuracy = check_pushup_feedback(results.pose_landmarks.landmark)
72
+ draw_feedback(image, accuracy, feedback)
73
+ out.write(image)
74
+ cap.release()
75
+ out.release()
76
+ return output_video
77
+
78
+ # Gradio Interface for pushup analysis.
79
+ gr.Interface(
80
+ fn=analyze_pushups,
81
+ inputs=gr.Video(),
82
+ outputs=gr.Video(),
83
+ title="Pushup Form Analyzer",
84
+ description="Upload a video of your pushups, and get feedback on your form!",
85
+ ).launch()