import cv2 import mediapipe as mp import numpy as np mp_pose = mp.solutions.pose mp_draw = mp.solutions.drawing_utils def calculate_angle(a, b, c): a, b, c = np.array(a), np.array(b), np.array(c) radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - \ np.arctan2(a[1]-b[1], a[0]-b[0]) angle = np.abs(radians * 180.0 / np.pi) if angle > 180: angle = 360 - angle return angle cap = cv2.VideoCapture(0) count = 0 stage = None # "up" or "down" with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose: while cap.isOpened(): ret, frame = cap.read() image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = pose.process(image) image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) try: landmarks = results.pose_landmarks.landmark # Get elbow angle (left side) shoulder = [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x, landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y] elbow = [landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].x, landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].y] wrist = [landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].x, landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].y] angle = calculate_angle(shoulder, elbow, wrist) # Push up logic if angle > 160: stage = "up" if angle < 90 and stage == "up": stage = "down" count += 1 except: pass # Display cv2.rectangle(image, (0,0), (220,60), (0,0,0), -1) cv2.putText(image, f'Reps: {count}', (10,40), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0,255,0), 2) mp_draw.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS) cv2.imshow('Push Up Counter', image) if cv2.waitKey(10) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()