Repository navigation
Expand file tree
/
Copy pathplayer_tracker.py
More file actions
76 lines (64 loc) · 2.41 KB
/
Copy pathplayer_tracker.py
File metadata and controls
76 lines (64 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
"""
Player detection & projection module
Purpose
-------
Runs YOLO to detect players each frame, then projects each player’s bottom-center
point into bird’s-eye space for analytics and overlays.
What it does
------------
- detect_players(frame): YOLO inference → list of [x1, y1, x2, y2] boxes
- project_player_positions(boxes, H): bottom-center of each box → perspectiveTransform
- detect_and_project(frame, H): convenience returning (boxes, projected_points)
Inputs
------
- BGR frame (OpenCV), homography H (3×3)
Outputs
-------
- Image-space bounding boxes and bird’s-eye (x, y) points
Assumptions
-----------
- Bottom-center of bbox reasonably approximates foot location for court placement
- Homography H is valid when projection is requested
"""
import cv2
import numpy as np
from ultralytics import YOLO
class PlayerTracker:
def __init__(self, model_path, conf_threshold=0.5):
self.model = YOLO(model_path)
self.conf_threshold = conf_threshold
def detect_players(self, frame):
"""
Run YOLO player detection on frame.
Returns list of bounding boxes in format [x1, y1, x2, y2].
"""
results = self.model.predict(frame, conf=self.conf_threshold)[0]
boxes = []
for box in results.boxes:
bbox = box.xyxy.cpu().numpy()[0]
boxes.append(bbox.tolist())
return boxes
def project_player_positions(self, boxes, H):
"""
Given bounding boxes and homography H, project player bottom-center points.
Returns list of projected (x, y) tuples in bird's eye space.
"""
projected_pts = []
if H is None:
return projected_pts
for box in boxes:
x1, y1, x2, y2 = box
cx = (x1 + x2) / 2
cy = y2 # bottom center of bbox
pt = np.array([[[cx, cy]]], dtype=np.float32)
proj = cv2.perspectiveTransform(pt, H)[0][0]
projected_pts.append(tuple(proj))
return projected_pts
def detect_and_project(self, frame, H):
"""
Convenience method: detect players and get projected points.
Returns tuple: (list of bounding boxes, list of projected points)
"""
boxes = self.detect_players(frame)
projected_pts = self.project_player_positions(boxes, H)
return boxes, projected_pts