pjxcharya commited on
Commit
9cbbabb
Β·
verified Β·
1 Parent(s): fb6cbb1

Upload 4 files

Browse files
exercises/__init__.py ADDED
File without changes
exercises/hammer_curl.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ from pose_estimation.angle_calculation import calculate_angle
4
+ from voice_feedback.feedback import provide_hammer_curl_feedback , speak
5
+
6
+
7
+ class HammerCurl:
8
+ def __init__(self):
9
+ self.counter_right = 0
10
+ self.counter_left = 0
11
+ self.stage_right = None # 'up' or 'down' for right arm
12
+ self.stage_left = None # 'up' or 'down' for left arm
13
+
14
+ self.angle_threshold = 40 # Angle threshold for misalignment
15
+ self.flexion_angle_up = 155 # Flexion angle for 'up' stage
16
+ self.flexion_angle_down = 35 # Flexion angle for 'down' stage
17
+
18
+ self.angle_threshold_up = 155 # Upper threshold for 'up' stage
19
+ self.angle_threshold_down = 47 # Lower threshold for 'down' stage
20
+
21
+ def calculate_shoulder_elbow_hip_angle(self, shoulder, elbow, hip):
22
+ """Calculate the angle between shoulder, elbow, and hip."""
23
+ return calculate_angle(elbow, shoulder, hip)
24
+
25
+ def calculate_shoulder_elbow_wrist(self, shoulder, elbow, wrist):
26
+ """Calculate the angle between shoulder, elbow, and wrist."""
27
+ return calculate_angle(shoulder, elbow, wrist)
28
+
29
+ def track_hammer_curl(self, landmarks, frame):
30
+ # Right arm landmarks (shoulder, elbow, hip, wrist)
31
+ shoulder_right = [int(landmarks[11].x * frame.shape[1]), int(landmarks[11].y * frame.shape[0])]
32
+ elbow_right = [int(landmarks[13].x * frame.shape[1]), int(landmarks[13].y * frame.shape[0])]
33
+ hip_right = [int(landmarks[23].x * frame.shape[1]), int(landmarks[23].y * frame.shape[0])]
34
+ wrist_right = [int(landmarks[15].x * frame.shape[1]), int(landmarks[15].y * frame.shape[0])]
35
+
36
+ # Left arm landmarks (shoulder, elbow, hip, wrist)
37
+ shoulder_left = [int(landmarks[12].x * frame.shape[1]), int(landmarks[12].y * frame.shape[0])]
38
+ elbow_left = [int(landmarks[14].x * frame.shape[1]), int(landmarks[14].y * frame.shape[0])]
39
+ hip_left = [int(landmarks[24].x * frame.shape[1]), int(landmarks[24].y * frame.shape[0])]
40
+ wrist_left = [int(landmarks[16].x * frame.shape[1]), int(landmarks[16].y * frame.shape[0])]
41
+
42
+ # Calculate the angle for counting (elbow flexion angle)
43
+ angle_right_counter = self.calculate_shoulder_elbow_wrist(shoulder_right, elbow_right, wrist_right)
44
+ angle_left_counter = self.calculate_shoulder_elbow_wrist(shoulder_left, elbow_left, wrist_left)
45
+
46
+ # Calculate the angle for the right arm (shoulder, elbow, hip)
47
+ angle_right = self.calculate_shoulder_elbow_hip_angle(shoulder_right, elbow_right, hip_right)
48
+
49
+ # Calculate the angle for the left arm (shoulder, elbow, hip)
50
+ angle_left = self.calculate_shoulder_elbow_hip_angle(shoulder_left, elbow_left, hip_left)
51
+
52
+ # Draw lines with improved style
53
+ self.draw_line_with_style(frame, shoulder_left, elbow_left, (0, 0, 255), 4)
54
+ self.draw_line_with_style(frame, elbow_left, wrist_left, (0, 0, 255), 4)
55
+
56
+ self.draw_line_with_style(frame, shoulder_right, elbow_right, (0, 0, 255), 4)
57
+ self.draw_line_with_style(frame, elbow_right, wrist_right, (0, 0, 255), 4)
58
+
59
+ # Add circles to highlight key points
60
+ self.draw_circle(frame, shoulder_left, (0, 0, 255), 8)
61
+ self.draw_circle(frame, elbow_left, (0, 0, 255), 8)
62
+ self.draw_circle(frame, wrist_left, (0, 0, 255), 8)
63
+
64
+ self.draw_circle(frame, shoulder_right, (0, 0, 255), 8)
65
+ self.draw_circle(frame, elbow_right, (0, 0, 255), 8)
66
+ self.draw_circle(frame, wrist_right, (0, 0, 255), 8)
67
+
68
+ # Convert the angles to integers and update the text positions
69
+ angle_text_position_left = (elbow_left[0] + 10, elbow_left[1] - 10)
70
+ cv2.putText(frame, f'Angle: {int(angle_left_counter)}', angle_text_position_left, cv2.FONT_HERSHEY_SIMPLEX, 0.5,
71
+ (255, 255, 255), 2)
72
+
73
+ angle_text_position_right = (elbow_right[0] + 10, elbow_right[1] - 10)
74
+ cv2.putText(frame, f'Angle: {int(angle_right_counter)}', angle_text_position_right, cv2.FONT_HERSHEY_SIMPLEX,
75
+ 0.5,
76
+ (255, 255, 255), 2)
77
+
78
+ warning_message_right = None
79
+ warning_message_left = None
80
+
81
+ # Check for misalignment based on shoulder-elbow-hip angle
82
+ if abs(angle_right) > self.angle_threshold:
83
+ warning_message_right = f"Right Shoulder-Elbow-Hip Misalignment! Angle: {angle_right:.2f}Β°"
84
+ if abs(angle_left) > self.angle_threshold:
85
+ warning_message_left = f"Left Shoulder-Elbow-Hip Misalignment! Angle: {angle_left:.2f}Β°"
86
+
87
+ if angle_right_counter > self.angle_threshold_up:
88
+ self.stage_right = "Flex"
89
+ elif self.angle_threshold_down < angle_right_counter < self.angle_threshold_up and self.stage_right == "Flex":
90
+ self.stage_right = "Up"
91
+ elif angle_right_counter < self.angle_threshold_down and self.stage_right=="Up":
92
+ self.stage_right = "Down"
93
+ self.counter_right +=1
94
+
95
+ if angle_left_counter > self.angle_threshold_up:
96
+ self.stage_left = "Flex"
97
+ elif self.angle_threshold_down < angle_left_counter < self.angle_threshold_up and self.stage_left == "Flex":
98
+ self.stage_left = "Up"
99
+ elif angle_left_counter < self.angle_threshold_down and self.stage_left == "Up":
100
+ self.stage_left = "Down"
101
+ self.counter_left +=1
102
+
103
+ # Progress percentages: 1 for "up", 0 for "down"
104
+ progress_right = 1 if self.stage_right == "up" else 0 # Note: your stage names are 'Flex', 'Up', 'Down'
105
+ progress_left = 1 if self.stage_left == "up" else 0 # This logic might need adjusting based on stage names
106
+
107
+ return self.counter_right, angle_right_counter, self.counter_left, angle_left_counter, warning_message_right, warning_message_left, progress_right, progress_left, self.stage_right, self.stage_left
108
+
109
+ def draw_line_with_style(self, frame, start_point, end_point, color, thickness):
110
+ cv2.line(frame, start_point, end_point, color, thickness, lineType=cv2.LINE_AA)
111
+
112
+ def draw_circle(self, frame, center, color, radius):
113
+ """Draw a circle with specified style."""
114
+ cv2.circle(frame, center, radius, color, -1) # -1 to fill the circle
115
+
116
+ # Inside the HammerCurl class in hammer_curl.py
117
+ def reset_reps(self):
118
+ self.counter_right = 0
119
+ self.counter_left = 0
120
+ self.stage_right = None # Or your desired initial stage, e.g., "Down" or "Flex"
121
+ self.stage_left = None # Or your desired initial stage
122
+ print("HammerCurl reps and stages reset for new set.")
exercises/push_up.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import mediapipe as mp
2
+ import time
3
+ from pose_estimation.angle_calculation import calculate_angle
4
+
5
+ class PushUp:
6
+ def __init__(self):
7
+ self.counter = 0
8
+ self.stage = "up" # Changed from "Initial"
9
+ self.angle_threshold_up = 150
10
+ self.angle_threshold_down = 70
11
+ self.last_counter_update = time.time()
12
+ self.mp_pose = mp.solutions.pose # Added
13
+
14
+ def calculate_shoulder_elbow_wrist_angle(self, shoulder, elbow, wrist):
15
+ """Calculate the angle between shoulder, elbow, and wrist."""
16
+ return calculate_angle(shoulder, elbow, wrist)
17
+
18
+ def track_push_up(self, landmarks_mp, frame_width, frame_height):
19
+ lm = landmarks_mp # shortcut
20
+
21
+ # Left side landmarks
22
+ shoulder_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].x * frame_width),
23
+ int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].y * frame_height)]
24
+ elbow_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_ELBOW.value].x * frame_width),
25
+ int(lm[self.mp_pose.PoseLandmark.LEFT_ELBOW.value].y * frame_height)]
26
+ wrist_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_WRIST.value].x * frame_width),
27
+ int(lm[self.mp_pose.PoseLandmark.LEFT_WRIST.value].y * frame_height)]
28
+
29
+ # Right side landmarks
30
+ shoulder_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x * frame_width),
31
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y * frame_height)]
32
+ elbow_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_ELBOW.value].x * frame_width),
33
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_ELBOW.value].y * frame_height)]
34
+ wrist_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_WRIST.value].x * frame_width),
35
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_WRIST.value].y * frame_height)]
36
+
37
+ # Calculate angles
38
+ angle_left = self.calculate_shoulder_elbow_wrist_angle(shoulder_left, elbow_left, wrist_left)
39
+ angle_right = self.calculate_shoulder_elbow_wrist_angle(shoulder_right, elbow_right, wrist_right)
40
+
41
+ # Stage and Counter Logic
42
+ current_angle_for_logic = angle_left
43
+ current_time = time.time()
44
+
45
+ if current_angle_for_logic > self.angle_threshold_up:
46
+ self.stage = "up"
47
+ elif self.angle_threshold_down < current_angle_for_logic < self.angle_threshold_up and self.stage == "up":
48
+ self.stage = "down"
49
+ elif current_angle_for_logic < self.angle_threshold_down and self.stage == "down":
50
+ if current_time - self.last_counter_update > 1: # 1 second debounce
51
+ self.counter += 1
52
+ self.last_counter_update = current_time
53
+ self.stage = "up" # Transition back to up
54
+
55
+ feedback = self._get_push_up_feedback(angle_left, angle_right, self.stage)
56
+
57
+ return {
58
+ "counter": self.counter,
59
+ "stage": self.stage,
60
+ "angle_left": angle_left,
61
+ "angle_right": angle_right,
62
+ "feedback": feedback
63
+ }
64
+
65
+ def _get_push_up_feedback(self, angle_left, angle_right, stage):
66
+ feedback = "Keep going!" # Default
67
+
68
+ if stage == "down":
69
+ if min(angle_left, angle_right) < self.angle_threshold_down - 5:
70
+ feedback = "Good depth!"
71
+ elif min(angle_left, angle_right) > self.angle_threshold_down + 10:
72
+ feedback = "Go lower."
73
+ elif stage == "up":
74
+ feedback = "Push up!" # Or "Ready"
75
+
76
+ if abs(angle_left - angle_right) > 25:
77
+ feedback += " Try to keep your push-up even." if feedback != "Keep going!" else "Try to keep your push-up even."
78
+
79
+ return feedback.strip()
80
+
81
+ def get_drawing_annotations(self, landmarks_mp, frame_width, frame_height, exercise_data_dict):
82
+ annotations = []
83
+ lm = landmarks_mp # shortcut
84
+
85
+ # Pixel coordinates
86
+ shoulder_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].x * frame_width),
87
+ int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].y * frame_height)]
88
+ elbow_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_ELBOW.value].x * frame_width),
89
+ int(lm[self.mp_pose.PoseLandmark.LEFT_ELBOW.value].y * frame_height)]
90
+ wrist_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_WRIST.value].x * frame_width),
91
+ int(lm[self.mp_pose.PoseLandmark.LEFT_WRIST.value].y * frame_height)]
92
+
93
+ shoulder_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x * frame_width),
94
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y * frame_height)]
95
+ elbow_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_ELBOW.value].x * frame_width),
96
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_ELBOW.value].y * frame_height)]
97
+ wrist_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_WRIST.value].x * frame_width),
98
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_WRIST.value].y * frame_height)]
99
+
100
+ # Lines (original colors: left (0,0,255) -> BGR [255,0,0], right (102,0,0) -> BGR [0,0,102])
101
+ annotations.append({"type": "line", "start_point": shoulder_left, "end_point": elbow_left, "color_bgr": [255, 0, 0], "thickness": 2})
102
+ annotations.append({"type": "line", "start_point": elbow_left, "end_point": wrist_left, "color_bgr": [255, 0, 0], "thickness": 2})
103
+ annotations.append({"type": "line", "start_point": shoulder_right, "end_point": elbow_right, "color_bgr": [0, 0, 102], "thickness": 2})
104
+ annotations.append({"type": "line", "start_point": elbow_right, "end_point": wrist_right, "color_bgr": [0, 0, 102], "thickness": 2})
105
+
106
+ # Circles
107
+ annotations.append({"type": "circle", "center_point": shoulder_left, "radius": 8, "color_bgr": [255, 0, 0], "filled": True})
108
+ annotations.append({"type": "circle", "center_point": elbow_left, "radius": 8, "color_bgr": [255, 0, 0], "filled": True})
109
+ annotations.append({"type": "circle", "center_point": wrist_left, "radius": 8, "color_bgr": [255, 0, 0], "filled": True})
110
+ annotations.append({"type": "circle", "center_point": shoulder_right, "radius": 8, "color_bgr": [0, 0, 102], "filled": True})
111
+ annotations.append({"type": "circle", "center_point": elbow_right, "radius": 8, "color_bgr": [0, 0, 102], "filled": True})
112
+ annotations.append({"type": "circle", "center_point": wrist_right, "radius": 8, "color_bgr": [0, 0, 102], "filled": True})
113
+
114
+ # Text for angles
115
+ if 'angle_left' in exercise_data_dict:
116
+ annotations.append({"type": "text", "text_content": f"Angle L: {int(exercise_data_dict['angle_left'])}",
117
+ "position": [elbow_left[0] + 10, elbow_left[1] - 10],
118
+ "font_scale": 0.5, "color_bgr": [255, 255, 255], "thickness": 2})
119
+ if 'angle_right' in exercise_data_dict:
120
+ annotations.append({"type": "text", "text_content": f"Angle R: {int(exercise_data_dict['angle_right'])}",
121
+ "position": [elbow_right[0] + 10, elbow_right[1] - 10],
122
+ "font_scale": 0.5, "color_bgr": [255, 255, 255], "thickness": 2})
123
+
124
+ # Display main feedback from exercise_data_dict
125
+ if 'feedback' in exercise_data_dict:
126
+ annotations.append({"type": "text", "text_content": exercise_data_dict['feedback'],
127
+ "position": [frame_width // 2 - 150, frame_height - 40], # Adjusted for longer text
128
+ "font_scale": 0.7, "color_bgr": [0, 255, 0], "thickness": 2}) # Green for feedback
129
+
130
+ return annotations
131
+
132
+ # Inside the PushUp class in push_up.py
133
+ def reset_reps(self):
134
+ self.counter = 0
135
+ self.stage = "up" # Reset to the initial stage
136
+ self.last_counter_update = time.time() # Important to reset debounce timer
137
+ print("PushUp reps and stage reset for new set.")
exercises/squat.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import mediapipe as mp
2
+ from pose_estimation.angle_calculation import calculate_angle
3
+
4
+ class Squat:
5
+ def __init__(self):
6
+ self.counter = 0
7
+ self.stage = "up" # Initial stage
8
+ self.mp_pose = mp.solutions.pose # Added for convenience
9
+
10
+ def calculate_angle(self, point1, point2, point3): # Assuming these are pixel coordinates
11
+ return calculate_angle(point1, point2, point3)
12
+
13
+ def track_squat(self, landmarks_mp, frame_width, frame_height):
14
+ lm = landmarks_mp # shortcut
15
+
16
+ # Left side landmarks
17
+ shoulder_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].x * frame_width),
18
+ int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].y * frame_height)]
19
+ hip_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_HIP.value].x * frame_width),
20
+ int(lm[self.mp_pose.PoseLandmark.LEFT_HIP.value].y * frame_height)]
21
+ knee_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_KNEE.value].x * frame_width),
22
+ int(lm[self.mp_pose.PoseLandmark.LEFT_KNEE.value].y * frame_height)]
23
+ # ankle_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_ANKLE.value].x * frame_width),
24
+ # int(lm[self.mp_pose.PoseLandmark.LEFT_ANKLE.value].y * frame_height)]
25
+
26
+
27
+ # Right side landmarks
28
+ shoulder_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x * frame_width),
29
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y * frame_height)]
30
+ hip_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_HIP.value].x * frame_width),
31
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_HIP.value].y * frame_height)]
32
+ knee_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_KNEE.value].x * frame_width),
33
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_KNEE.value].y * frame_height)]
34
+ # ankle_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_ANKLE.value].x * frame_width),
35
+ # int(lm[self.mp_pose.PoseLandmark.RIGHT_ANKLE.value].y * frame_height)]
36
+
37
+ # Calculate angles
38
+ angle_left = self.calculate_angle(shoulder_left, hip_left, knee_left)
39
+ angle_right = self.calculate_angle(shoulder_right, hip_right, knee_right)
40
+
41
+ # Stage and counter logic (using angle_left for primary logic)
42
+ current_angle_for_logic = angle_left
43
+ if current_angle_for_logic > 170:
44
+ self.stage = "up"
45
+ elif 90 < current_angle_for_logic < 170 and self.stage == "up":
46
+ self.stage = "down"
47
+ elif current_angle_for_logic < 90 and self.stage == "down":
48
+ self.stage = "up"
49
+ self.counter += 1
50
+
51
+ feedback_message = self._get_squat_feedback(angle_left, angle_right, self.stage,
52
+ knee_left, hip_left, shoulder_left,
53
+ knee_right, hip_right, shoulder_right)
54
+
55
+ return {
56
+ "counter": self.counter,
57
+ "stage": self.stage,
58
+ "angle_left": angle_left,
59
+ "angle_right": angle_right,
60
+ "feedback": feedback_message
61
+ }
62
+
63
+ def _get_squat_feedback(self, angle_left, angle_right, stage,
64
+ knee_left, hip_left, shoulder_left,
65
+ knee_right, hip_right, shoulder_right): # Added points for future use
66
+ feedback = "Keep going." # Default feedback
67
+
68
+ if stage == "down":
69
+ if min(angle_left, angle_right) < 80:
70
+ feedback = "Good depth!"
71
+ elif min(angle_left, angle_right) > 100: # Knees should be more bent
72
+ feedback = "Go lower."
73
+
74
+ if abs(angle_left - angle_right) > 20: # Check for uneven squat
75
+ # Adding a check to see if there's significant movement, e.g., not in "up" stage fully extended
76
+ if not (stage == "up" and min(angle_left, angle_right) > 160): # Avoid this message if standing straight
77
+ feedback += " Try to keep your squat even." if feedback != "Keep going." else "Try to keep your squat even."
78
+
79
+
80
+ # Placeholder for more advanced feedback using the passed points:
81
+ # E.g., Knee valgus: check if knee_left.x < hip_left.x and knee_left.x > shoulder_left.x (simplified)
82
+ # E.g., Back posture: calculate angle shoulder-hip-ankle (requires ankle points)
83
+
84
+ return feedback.strip()
85
+
86
+
87
+ def get_drawing_annotations(self, landmarks_mp, frame_width, frame_height, exercise_data_dict):
88
+ annotations = []
89
+ lm = landmarks_mp # shortcut
90
+
91
+ # Re-calculate or retrieve necessary points (pixel coordinates)
92
+ # For simplicity, re-calculating here. Could be optimized by passing from track_squat.
93
+ shoulder_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].x * frame_width),
94
+ int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].y * frame_height)]
95
+ hip_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_HIP.value].x * frame_width),
96
+ int(lm[self.mp_pose.PoseLandmark.LEFT_HIP.value].y * frame_height)]
97
+ knee_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_KNEE.value].x * frame_width),
98
+ int(lm[self.mp_pose.PoseLandmark.LEFT_KNEE.value].y * frame_height)]
99
+
100
+ shoulder_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x * frame_width),
101
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y * frame_height)]
102
+ hip_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_HIP.value].x * frame_width),
103
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_HIP.value].y * frame_height)]
104
+ knee_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_KNEE.value].x * frame_width),
105
+ int(lm[self.mp_pose.PoseLandmark.RIGHT_KNEE.value].y * frame_height)]
106
+
107
+ # Lines for left side (original color: (178, 102, 255) -> BGR: [255, 102, 178])
108
+ annotations.append({"type": "line", "start_point": shoulder_left, "end_point": hip_left, "color_bgr": [255, 102, 178], "thickness": 2})
109
+ annotations.append({"type": "line", "start_point": hip_left, "end_point": knee_left, "color_bgr": [255, 102, 178], "thickness": 2})
110
+
111
+ # Lines for right side (original color: (51, 153, 255) -> BGR: [255, 153, 51])
112
+ annotations.append({"type": "line", "start_point": shoulder_right, "end_point": hip_right, "color_bgr": [255, 153, 51], "thickness": 2})
113
+ annotations.append({"type": "line", "start_point": hip_right, "end_point": knee_right, "color_bgr": [255, 153, 51], "thickness": 2})
114
+
115
+ # Circles for left side
116
+ annotations.append({"type": "circle", "center_point": shoulder_left, "radius": 8, "color_bgr": [255, 102, 178], "filled": True})
117
+ annotations.append({"type": "circle", "center_point": hip_left, "radius": 8, "color_bgr": [255, 102, 178], "filled": True})
118
+ annotations.append({"type": "circle", "center_point": knee_left, "radius": 8, "color_bgr": [255, 102, 178], "filled": True})
119
+
120
+ # Circles for right side
121
+ annotations.append({"type": "circle", "center_point": shoulder_right, "radius": 8, "color_bgr": [255, 153, 51], "filled": True})
122
+ annotations.append({"type": "circle", "center_point": hip_right, "radius": 8, "color_bgr": [255, 153, 51], "filled": True})
123
+ annotations.append({"type": "circle", "center_point": knee_right, "radius": 8, "color_bgr": [255, 153, 51], "filled": True})
124
+
125
+ # Text for angles
126
+ if 'angle_left' in exercise_data_dict:
127
+ annotations.append({"type": "text", "text_content": f"Angle L: {int(exercise_data_dict['angle_left'])}",
128
+ "position": [knee_left[0] + 10, knee_left[1] - 10],
129
+ "font_scale": 0.5, "color_bgr": [255, 255, 255], "thickness": 2})
130
+ if 'angle_right' in exercise_data_dict:
131
+ annotations.append({"type": "text", "text_content": f"Angle R: {int(exercise_data_dict['angle_right'])}",
132
+ "position": [knee_right[0] + 10, knee_right[1] - 10],
133
+ "font_scale": 0.5, "color_bgr": [255, 255, 255], "thickness": 2})
134
+
135
+ # Display main feedback from exercise_data_dict
136
+ if 'feedback' in exercise_data_dict:
137
+ annotations.append({"type": "text", "text_content": exercise_data_dict['feedback'],
138
+ "position": [frame_width // 2 - 100, frame_height - 40], # Centered at bottom
139
+ "font_scale": 0.7, "color_bgr": [0, 0, 255], "thickness": 2})
140
+
141
+
142
+ return annotations
143
+
144
+ # Inside the Squat class in squat.py
145
+ def reset_reps(self):
146
+ self.counter = 0
147
+ self.stage = "up" # Reset to the initial stage
148
+ print("Squat reps and stage reset for new set.")