smurar commited on
Commit
ce3ee7d
·
verified ·
1 Parent(s): 867a0c6

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -0
app.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import mediapipe as mp
3
+ import numpy as np
4
+ import gradio as gr
5
+
6
+ mp_pose = mp.solutions.pose
7
+ pose = mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5)
8
+ mp_drawing = mp.solutions.drawing_utils
9
+
10
+ def calculate_angle(a, b, c):
11
+ a, b, c = np.array(a), np.array(b), np.array(c)
12
+ radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - np.arctan2(a[1]-b[1], a[0]-b[0])
13
+ return np.abs(radians * 180.0 / np.pi)
14
+
15
+ def check_pullup_feedback(landmarks):
16
+ shoulder = [landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x,
17
+ landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y]
18
+ elbow = [landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW.value].x,
19
+ landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW.value].y]
20
+ wrist = [landmarks[mp_pose.PoseLandmark.RIGHT_WRIST.value].x,
21
+ landmarks[mp_pose.PoseLandmark.RIGHT_WRIST.value].y]
22
+
23
+ angle = calculate_angle(shoulder, elbow, wrist)
24
+ target_angle = 70
25
+ tolerance = 20
26
+ accuracy = max(0, min(100, (1 - abs(angle - target_angle) / tolerance) * 100))
27
+
28
+ if angle > (target_angle + tolerance / 2):
29
+ feedback = ("Incomplete Pull-up - Your elbows remain too extended. Engage your back muscles to pull higher.")
30
+ elif angle < (target_angle - tolerance / 2):
31
+ feedback = ("Over-bending - Your elbows are too flexed. Try to control your descent.")
32
+ else:
33
+ feedback = "Correct Pull-up - Great form!"
34
+ return feedback, int(accuracy)
35
+
36
+ def draw_accuracy_bar(image, accuracy):
37
+ bar_x, bar_y = 50, image.shape[0] - 50
38
+ bar_width, bar_height = 200, 20
39
+ fill_width = int((accuracy / 100) * bar_width)
40
+ color = (0, 255, 0) if accuracy >= 80 else (0, 0, 255) if accuracy < 50 else (0, 255, 255)
41
+ cv2.rectangle(image, (bar_x, bar_y), (bar_x + bar_width, bar_y + bar_height), (200,200,200), 2)
42
+ cv2.rectangle(image, (bar_x, bar_y), (bar_x + fill_width, bar_y + bar_height), color, -1)
43
+ cv2.putText(image, f"Accuracy: {accuracy}%", (bar_x, bar_y-10),
44
+ cv2.FONT_HERSHEY_DUPLEX, 0.6, (255,255,255), 2)
45
+
46
+ def analyze_pullups(video_path):
47
+ cap = cv2.VideoCapture(video_path)
48
+ frame_width, frame_height = int(cap.get(3)), int(cap.get(4))
49
+ fps = cap.get(cv2.CAP_PROP_FPS) if cap.get(cv2.CAP_PROP_FPS) > 0 else 30
50
+
51
+ output_video = "output_pullups.mp4"
52
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
53
+ out = cv2.VideoWriter(output_video, fourcc, fps, (frame_width, frame_height))
54
+
55
+ while cap.isOpened():
56
+ ret, frame = cap.read()
57
+ if not ret:
58
+ break
59
+ image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
60
+ results = pose.process(image)
61
+ image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
62
+ if results.pose_landmarks:
63
+ mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
64
+ landmarks = results.pose_landmarks.landmark
65
+ feedback, accuracy = check_pullup_feedback(landmarks)
66
+ draw_accuracy_bar(image, accuracy)
67
+ text_color = (0, 255, 0) if "Correct" in feedback else (0, 0, 255)
68
+ cv2.putText(image, feedback, (50, 50),
69
+ cv2.FONT_HERSHEY_COMPLEX, 1, text_color, 3)
70
+ out.write(image)
71
+ cap.release()
72
+ out.release()
73
+ return output_video
74
+
75
+ gr.Interface(
76
+ fn=analyze_pullups,
77
+ inputs=gr.Video(),
78
+ outputs=gr.Video(),
79
+ title="Pull-ups Form Analyzer",
80
+ description="Upload a video of your pull-ups and receive form feedback!"
81
+ ).launch()