live-train / exercises /hammer_curl.py
pjxcharya's picture
Upload 4 files
9cbbabb verified
import cv2
import numpy as np
from pose_estimation.angle_calculation import calculate_angle
from voice_feedback.feedback import provide_hammer_curl_feedback , speak
class HammerCurl:
def __init__(self):
self.counter_right = 0
self.counter_left = 0
self.stage_right = None # 'up' or 'down' for right arm
self.stage_left = None # 'up' or 'down' for left arm
self.angle_threshold = 40 # Angle threshold for misalignment
self.flexion_angle_up = 155 # Flexion angle for 'up' stage
self.flexion_angle_down = 35 # Flexion angle for 'down' stage
self.angle_threshold_up = 155 # Upper threshold for 'up' stage
self.angle_threshold_down = 47 # Lower threshold for 'down' stage
def calculate_shoulder_elbow_hip_angle(self, shoulder, elbow, hip):
"""Calculate the angle between shoulder, elbow, and hip."""
return calculate_angle(elbow, shoulder, hip)
def calculate_shoulder_elbow_wrist(self, shoulder, elbow, wrist):
"""Calculate the angle between shoulder, elbow, and wrist."""
return calculate_angle(shoulder, elbow, wrist)
def track_hammer_curl(self, landmarks, frame):
# Right arm landmarks (shoulder, elbow, hip, wrist)
shoulder_right = [int(landmarks[11].x * frame.shape[1]), int(landmarks[11].y * frame.shape[0])]
elbow_right = [int(landmarks[13].x * frame.shape[1]), int(landmarks[13].y * frame.shape[0])]
hip_right = [int(landmarks[23].x * frame.shape[1]), int(landmarks[23].y * frame.shape[0])]
wrist_right = [int(landmarks[15].x * frame.shape[1]), int(landmarks[15].y * frame.shape[0])]
# Left arm landmarks (shoulder, elbow, hip, wrist)
shoulder_left = [int(landmarks[12].x * frame.shape[1]), int(landmarks[12].y * frame.shape[0])]
elbow_left = [int(landmarks[14].x * frame.shape[1]), int(landmarks[14].y * frame.shape[0])]
hip_left = [int(landmarks[24].x * frame.shape[1]), int(landmarks[24].y * frame.shape[0])]
wrist_left = [int(landmarks[16].x * frame.shape[1]), int(landmarks[16].y * frame.shape[0])]
# Calculate the angle for counting (elbow flexion angle)
angle_right_counter = self.calculate_shoulder_elbow_wrist(shoulder_right, elbow_right, wrist_right)
angle_left_counter = self.calculate_shoulder_elbow_wrist(shoulder_left, elbow_left, wrist_left)
# Calculate the angle for the right arm (shoulder, elbow, hip)
angle_right = self.calculate_shoulder_elbow_hip_angle(shoulder_right, elbow_right, hip_right)
# Calculate the angle for the left arm (shoulder, elbow, hip)
angle_left = self.calculate_shoulder_elbow_hip_angle(shoulder_left, elbow_left, hip_left)
# Draw lines with improved style
self.draw_line_with_style(frame, shoulder_left, elbow_left, (0, 0, 255), 4)
self.draw_line_with_style(frame, elbow_left, wrist_left, (0, 0, 255), 4)
self.draw_line_with_style(frame, shoulder_right, elbow_right, (0, 0, 255), 4)
self.draw_line_with_style(frame, elbow_right, wrist_right, (0, 0, 255), 4)
# Add circles to highlight key points
self.draw_circle(frame, shoulder_left, (0, 0, 255), 8)
self.draw_circle(frame, elbow_left, (0, 0, 255), 8)
self.draw_circle(frame, wrist_left, (0, 0, 255), 8)
self.draw_circle(frame, shoulder_right, (0, 0, 255), 8)
self.draw_circle(frame, elbow_right, (0, 0, 255), 8)
self.draw_circle(frame, wrist_right, (0, 0, 255), 8)
# Convert the angles to integers and update the text positions
angle_text_position_left = (elbow_left[0] + 10, elbow_left[1] - 10)
cv2.putText(frame, f'Angle: {int(angle_left_counter)}', angle_text_position_left, cv2.FONT_HERSHEY_SIMPLEX, 0.5,
(255, 255, 255), 2)
angle_text_position_right = (elbow_right[0] + 10, elbow_right[1] - 10)
cv2.putText(frame, f'Angle: {int(angle_right_counter)}', angle_text_position_right, cv2.FONT_HERSHEY_SIMPLEX,
0.5,
(255, 255, 255), 2)
warning_message_right = None
warning_message_left = None
# Check for misalignment based on shoulder-elbow-hip angle
if abs(angle_right) > self.angle_threshold:
warning_message_right = f"Right Shoulder-Elbow-Hip Misalignment! Angle: {angle_right:.2f}°"
if abs(angle_left) > self.angle_threshold:
warning_message_left = f"Left Shoulder-Elbow-Hip Misalignment! Angle: {angle_left:.2f}°"
if angle_right_counter > self.angle_threshold_up:
self.stage_right = "Flex"
elif self.angle_threshold_down < angle_right_counter < self.angle_threshold_up and self.stage_right == "Flex":
self.stage_right = "Up"
elif angle_right_counter < self.angle_threshold_down and self.stage_right=="Up":
self.stage_right = "Down"
self.counter_right +=1
if angle_left_counter > self.angle_threshold_up:
self.stage_left = "Flex"
elif self.angle_threshold_down < angle_left_counter < self.angle_threshold_up and self.stage_left == "Flex":
self.stage_left = "Up"
elif angle_left_counter < self.angle_threshold_down and self.stage_left == "Up":
self.stage_left = "Down"
self.counter_left +=1
# Progress percentages: 1 for "up", 0 for "down"
progress_right = 1 if self.stage_right == "up" else 0 # Note: your stage names are 'Flex', 'Up', 'Down'
progress_left = 1 if self.stage_left == "up" else 0 # This logic might need adjusting based on stage names
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
def draw_line_with_style(self, frame, start_point, end_point, color, thickness):
cv2.line(frame, start_point, end_point, color, thickness, lineType=cv2.LINE_AA)
def draw_circle(self, frame, center, color, radius):
"""Draw a circle with specified style."""
cv2.circle(frame, center, radius, color, -1) # -1 to fill the circle
# Inside the HammerCurl class in hammer_curl.py
def reset_reps(self):
self.counter_right = 0
self.counter_left = 0
self.stage_right = None # Or your desired initial stage, e.g., "Down" or "Flex"
self.stage_left = None # Or your desired initial stage
print("HammerCurl reps and stages reset for new set.")