Skip to content

Commit 506dc15

Browse files
authored
PR #67: Bowling-Action-Tracking-App
Bowling-Action-Tracking-App Merge pull request #67 from musharrafhamraz/bowling-action-tracking-app
2 parents 7841987 + 4fe2b55 commit 506dc15

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

Bowling-Action-Tracking/main.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import cv2
2+
import mediapipe as mp
3+
import numpy as np
4+
from collections import deque
5+
6+
# Initialize MediaPipe Pose
7+
mp_pose = mp.solutions.pose
8+
pose = mp_pose.Pose()
9+
mp_drawing = mp.solutions.drawing_utils
10+
11+
# Initialize video capture
12+
cap = cv2.VideoCapture('bowling.mp4')
13+
14+
# Store wrist trajectory and arcs
15+
wrist_trajectory = deque(maxlen=100) # Main wrist trajectory
16+
wrist_positions = deque(maxlen=20) # For arcs
17+
elbow_positions = deque(maxlen=20)
18+
shoulder_positions = deque(maxlen=20)
19+
20+
# Function to convert normalized coordinates to pixel coordinates
21+
def to_pixel_coords(landmark, frame):
22+
return int(landmark.x * frame.shape[1]), int(landmark.y * frame.shape[0])
23+
24+
# Function to draw a gradient arc between two points
25+
def draw_gradient_arc(frame, p1, p2, thickness, start_color, end_color):
26+
num_segments = 50
27+
x_diff = (p2[0] - p1[0]) / num_segments
28+
y_diff = (p2[1] - p1[1]) / num_segments
29+
30+
for i in range(num_segments):
31+
# Compute start and end points of each segment
32+
start_point = (int(p1[0] + i * x_diff), int(p1[1] + i * y_diff))
33+
end_point = (int(p1[0] + (i + 1) * x_diff), int(p1[1] + (i + 1) * y_diff))
34+
35+
# Interpolate color between start and end
36+
alpha = i / num_segments
37+
color = (
38+
int(start_color[0] * (1 - alpha) + end_color[0] * alpha),
39+
int(start_color[1] * (1 - alpha) + end_color[1] * alpha),
40+
int(start_color[2] * (1 - alpha) + end_color[2] * alpha),
41+
)
42+
cv2.line(frame, start_point, end_point, color, thickness)
43+
44+
while cap.isOpened():
45+
ret, frame = cap.read()
46+
if not ret:
47+
break
48+
frame = cv2.resize(frame, (1000, 600))
49+
# Convert the frame to RGB
50+
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
51+
results = pose.process(rgb_frame)
52+
53+
if results.pose_landmarks:
54+
landmarks = results.pose_landmarks.landmark
55+
56+
# Extract right-hand keypoints
57+
right_shoulder = landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER]
58+
right_elbow = landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW]
59+
right_wrist = landmarks[mp_pose.PoseLandmark.RIGHT_WRIST]
60+
61+
# Convert normalized coordinates to pixel coordinates
62+
shoulder_coords = to_pixel_coords(right_shoulder, frame)
63+
elbow_coords = to_pixel_coords(right_elbow, frame)
64+
wrist_coords = to_pixel_coords(right_wrist, frame)
65+
66+
# Add wrist coordinates to the deque for trajectory
67+
wrist_trajectory.append(wrist_coords)
68+
69+
# Add coordinates for arcs
70+
shoulder_positions.append(shoulder_coords)
71+
elbow_positions.append(elbow_coords)
72+
wrist_positions.append(wrist_coords)
73+
74+
# Draw the wrist trajectory (main line)
75+
for i in range(1, len(wrist_trajectory)):
76+
cv2.line(frame, wrist_trajectory[i - 1], wrist_trajectory[i], (0, 255, 255), 3)
77+
78+
# Draw dynamic arcs for the last few positions
79+
for i in range(1, len(shoulder_positions)):
80+
# Fade effect using index
81+
thickness = max(2, 10 - (len(shoulder_positions) - i))
82+
83+
# Gradient arc for shoulder-to-elbow
84+
draw_gradient_arc(frame, shoulder_positions[i - 1], elbow_positions[i - 1], thickness, (0, 255, 0), (255, 0, 0))
85+
# Gradient arc for elbow-to-wrist
86+
draw_gradient_arc(frame, elbow_positions[i - 1], wrist_positions[i - 1], thickness, (255, 0, 0), (0, 0, 255))
87+
88+
# Draw keypoints
89+
cv2.circle(frame, shoulder_coords, 10, (0, 255, 0), -1) # Shoulder
90+
cv2.circle(frame, elbow_coords, 10, (255, 0, 0), -1) # Elbow
91+
cv2.circle(frame, wrist_coords, 10, (0, 0, 255), -1) # Wrist
92+
93+
# Display the frame
94+
cv2.imshow('Dynamic Bowling Trajectory', frame)
95+
96+
if cv2.waitKey(10) & 0xFF == ord('q'):
97+
break
98+
99+
cap.release()
100+
cv2.destroyAllWindows()
101+
102+
103+

0 commit comments

Comments
 (0)