pjxcharya commited on
Commit
6d537bf
·
verified ·
1 Parent(s): 3908140

Update exercises/push_up.py

Browse files
Files changed (1) hide show
  1. exercises/push_up.py +112 -59
exercises/push_up.py CHANGED
@@ -1,77 +1,130 @@
1
- import cv2
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 = "Initial" # 'up' or 'down'
9
- self.angle_threshold_up = 150 # Upper threshold for 'up' stage
10
- self.angle_threshold_down = 70 # Lower threshold for 'down' stage
11
- self.last_counter_update = time.time() # Track the time of the last counter update
 
12
 
13
  def calculate_shoulder_elbow_wrist_angle(self, shoulder, elbow, wrist):
14
  """Calculate the angle between shoulder, elbow, and wrist."""
15
  return calculate_angle(shoulder, elbow, wrist)
16
 
17
- def track_push_up(self, landmarks, frame):
18
- # Right side landmarks (shoulder, elbow, wrist)
19
- shoulder_left = [int(landmarks[11].x * frame.shape[1]), int(landmarks[11].y * frame.shape[0])]
20
- elbow_left = [int(landmarks[13].x * frame.shape[1]), int(landmarks[13].y * frame.shape[0])]
21
- wrist_left = [int(landmarks[15].x * frame.shape[1]), int(landmarks[15].y * frame.shape[0])]
22
-
23
- shoulder_right = [int(landmarks[12].x * frame.shape[1]), int(landmarks[12].y * frame.shape[0])]
24
- elbow_right = [int(landmarks[14].x * frame.shape[1]), int(landmarks[14].y * frame.shape[0])]
25
- wrist_right = [int(landmarks[16].x * frame.shape[1]), int(landmarks[16].y * frame.shape[0])]
26
-
27
- # Calculate angles for push-up tracking
 
 
 
 
 
 
 
 
 
28
  angle_left = self.calculate_shoulder_elbow_wrist_angle(shoulder_left, elbow_left, wrist_left)
29
  angle_right = self.calculate_shoulder_elbow_wrist_angle(shoulder_right, elbow_right, wrist_right)
30
 
31
- # Draw lines with improved style
32
- self.draw_line_with_style(frame, shoulder_left, elbow_left, (0, 0, 255), 2)
33
- self.draw_line_with_style(frame, elbow_left, wrist_left, (0, 0, 255), 2)
34
-
35
- self.draw_line_with_style(frame, shoulder_right, elbow_right, (102, 0, 0), 2)
36
- self.draw_line_with_style(frame, elbow_right, wrist_right, (102, 0, 0), 2)
37
-
38
- # Draw circles to highlight key points
39
- self.draw_circle(frame, shoulder_left, (0, 0, 255), 8)
40
- self.draw_circle(frame, elbow_left, (0, 0, 255), 8)
41
- self.draw_circle(frame, wrist_left, (0, 0, 255), 8)
42
-
43
- self.draw_circle(frame, shoulder_right, (102, 0, 0), 8)
44
- self.draw_circle(frame, elbow_right, (102, 0, 0), 8)
45
- self.draw_circle(frame, wrist_right, (102, 0, 0), 8)
46
-
47
- # Update angle text positions and display
48
- angle_text_position_left = (elbow_left[0] + 10, elbow_left[1] - 10)
49
- cv2.putText(frame, f'Angle: {int(angle_left)}', angle_text_position_left, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
50
-
51
- angle_text_position_right = (elbow_right[0] + 10, elbow_right[1] - 10)
52
- cv2.putText(frame, f'Angle: {int(angle_right)}', angle_text_position_right, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
53
-
54
- # Get current time
55
  current_time = time.time()
56
 
57
- # Update stage and counter
58
- if angle_left > self.angle_threshold_up:
59
- self.stage = "Starting position"
60
- elif self.angle_threshold_down < angle_left < self.angle_threshold_up and self.stage == "Starting position":
61
- self.stage = "Descent"
62
- elif angle_left < self.angle_threshold_down and self.stage == "Descent":
63
- self.stage = "Ascent"
64
- # Increment counter only if enough time has passed since last update
65
- if current_time - self.last_counter_update > 1: # 1 second threshold
66
  self.counter += 1
67
  self.last_counter_update = current_time
68
-
69
- return self.counter, angle_left, self.stage
70
-
71
- def draw_line_with_style(self, frame, start_point, end_point, color, thickness):
72
- """Draw a line with specified style."""
73
- cv2.line(frame, start_point, end_point, color, thickness, lineType=cv2.LINE_AA)
74
-
75
- def draw_circle(self, frame, center, color, radius):
76
- """Draw a circle with specified style."""
77
- cv2.circle(frame, center, radius, color, -1) # -1 to fill the circle
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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