pjxcharya's picture
Upload 4 files
9cbbabb verified
import mediapipe as mp
from pose_estimation.angle_calculation import calculate_angle
class Squat:
def __init__(self):
self.counter = 0
self.stage = "up" # Initial stage
self.mp_pose = mp.solutions.pose # Added for convenience
def calculate_angle(self, point1, point2, point3): # Assuming these are pixel coordinates
return calculate_angle(point1, point2, point3)
def track_squat(self, landmarks_mp, frame_width, frame_height):
lm = landmarks_mp # shortcut
# Left side landmarks
shoulder_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].y * frame_height)]
hip_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_HIP.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.LEFT_HIP.value].y * frame_height)]
knee_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_KNEE.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.LEFT_KNEE.value].y * frame_height)]
# ankle_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_ANKLE.value].x * frame_width),
# int(lm[self.mp_pose.PoseLandmark.LEFT_ANKLE.value].y * frame_height)]
# Right side landmarks
shoulder_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y * frame_height)]
hip_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_HIP.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.RIGHT_HIP.value].y * frame_height)]
knee_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_KNEE.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.RIGHT_KNEE.value].y * frame_height)]
# ankle_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_ANKLE.value].x * frame_width),
# int(lm[self.mp_pose.PoseLandmark.RIGHT_ANKLE.value].y * frame_height)]
# Calculate angles
angle_left = self.calculate_angle(shoulder_left, hip_left, knee_left)
angle_right = self.calculate_angle(shoulder_right, hip_right, knee_right)
# Stage and counter logic (using angle_left for primary logic)
current_angle_for_logic = angle_left
if current_angle_for_logic > 170:
self.stage = "up"
elif 90 < current_angle_for_logic < 170 and self.stage == "up":
self.stage = "down"
elif current_angle_for_logic < 90 and self.stage == "down":
self.stage = "up"
self.counter += 1
feedback_message = self._get_squat_feedback(angle_left, angle_right, self.stage,
knee_left, hip_left, shoulder_left,
knee_right, hip_right, shoulder_right)
return {
"counter": self.counter,
"stage": self.stage,
"angle_left": angle_left,
"angle_right": angle_right,
"feedback": feedback_message
}
def _get_squat_feedback(self, angle_left, angle_right, stage,
knee_left, hip_left, shoulder_left,
knee_right, hip_right, shoulder_right): # Added points for future use
feedback = "Keep going." # Default feedback
if stage == "down":
if min(angle_left, angle_right) < 80:
feedback = "Good depth!"
elif min(angle_left, angle_right) > 100: # Knees should be more bent
feedback = "Go lower."
if abs(angle_left - angle_right) > 20: # Check for uneven squat
# Adding a check to see if there's significant movement, e.g., not in "up" stage fully extended
if not (stage == "up" and min(angle_left, angle_right) > 160): # Avoid this message if standing straight
feedback += " Try to keep your squat even." if feedback != "Keep going." else "Try to keep your squat even."
# Placeholder for more advanced feedback using the passed points:
# E.g., Knee valgus: check if knee_left.x < hip_left.x and knee_left.x > shoulder_left.x (simplified)
# E.g., Back posture: calculate angle shoulder-hip-ankle (requires ankle points)
return feedback.strip()
def get_drawing_annotations(self, landmarks_mp, frame_width, frame_height, exercise_data_dict):
annotations = []
lm = landmarks_mp # shortcut
# Re-calculate or retrieve necessary points (pixel coordinates)
# For simplicity, re-calculating here. Could be optimized by passing from track_squat.
shoulder_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.LEFT_SHOULDER.value].y * frame_height)]
hip_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_HIP.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.LEFT_HIP.value].y * frame_height)]
knee_left = [int(lm[self.mp_pose.PoseLandmark.LEFT_KNEE.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.LEFT_KNEE.value].y * frame_height)]
shoulder_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y * frame_height)]
hip_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_HIP.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.RIGHT_HIP.value].y * frame_height)]
knee_right = [int(lm[self.mp_pose.PoseLandmark.RIGHT_KNEE.value].x * frame_width),
int(lm[self.mp_pose.PoseLandmark.RIGHT_KNEE.value].y * frame_height)]
# Lines for left side (original color: (178, 102, 255) -> BGR: [255, 102, 178])
annotations.append({"type": "line", "start_point": shoulder_left, "end_point": hip_left, "color_bgr": [255, 102, 178], "thickness": 2})
annotations.append({"type": "line", "start_point": hip_left, "end_point": knee_left, "color_bgr": [255, 102, 178], "thickness": 2})
# Lines for right side (original color: (51, 153, 255) -> BGR: [255, 153, 51])
annotations.append({"type": "line", "start_point": shoulder_right, "end_point": hip_right, "color_bgr": [255, 153, 51], "thickness": 2})
annotations.append({"type": "line", "start_point": hip_right, "end_point": knee_right, "color_bgr": [255, 153, 51], "thickness": 2})
# Circles for left side
annotations.append({"type": "circle", "center_point": shoulder_left, "radius": 8, "color_bgr": [255, 102, 178], "filled": True})
annotations.append({"type": "circle", "center_point": hip_left, "radius": 8, "color_bgr": [255, 102, 178], "filled": True})
annotations.append({"type": "circle", "center_point": knee_left, "radius": 8, "color_bgr": [255, 102, 178], "filled": True})
# Circles for right side
annotations.append({"type": "circle", "center_point": shoulder_right, "radius": 8, "color_bgr": [255, 153, 51], "filled": True})
annotations.append({"type": "circle", "center_point": hip_right, "radius": 8, "color_bgr": [255, 153, 51], "filled": True})
annotations.append({"type": "circle", "center_point": knee_right, "radius": 8, "color_bgr": [255, 153, 51], "filled": True})
# Text for angles
if 'angle_left' in exercise_data_dict:
annotations.append({"type": "text", "text_content": f"Angle L: {int(exercise_data_dict['angle_left'])}",
"position": [knee_left[0] + 10, knee_left[1] - 10],
"font_scale": 0.5, "color_bgr": [255, 255, 255], "thickness": 2})
if 'angle_right' in exercise_data_dict:
annotations.append({"type": "text", "text_content": f"Angle R: {int(exercise_data_dict['angle_right'])}",
"position": [knee_right[0] + 10, knee_right[1] - 10],
"font_scale": 0.5, "color_bgr": [255, 255, 255], "thickness": 2})
# Display main feedback from exercise_data_dict
if 'feedback' in exercise_data_dict:
annotations.append({"type": "text", "text_content": exercise_data_dict['feedback'],
"position": [frame_width // 2 - 100, frame_height - 40], # Centered at bottom
"font_scale": 0.7, "color_bgr": [0, 0, 255], "thickness": 2})
return annotations
# Inside the Squat class in squat.py
def reset_reps(self):
self.counter = 0
self.stage = "up" # Reset to the initial stage
print("Squat reps and stage reset for new set.")