| # Data Classes (Don't pass dicts everywhere!) | |
| from dataclasses import dataclass | |
| from typing import List, Optional, Tuple | |
| from enum import Enum | |
| class EventType(Enum): | |
| PASS = "pass" | |
| DRIBBLE = "dribble" | |
| MOVEMENT = "movement" | |
| RECOVERY = "recovery" | |
| SHOT = "shot" | |
| class Detection: | |
| """Single detection from RF-DETR""" | |
| class_id: int | |
| confidence: float | |
| bbox: Tuple[float, float, float, float] # x, y, width, height | |
| class_name: str = "" | |
| class TrackedObject: | |
| """Tracked object with ID""" | |
| object_id: int | |
| detection: Detection | |
| team_id: Optional[int] = None | |
| class Player: | |
| """Player with pitch coordinates""" | |
| object_id: int | |
| team_id: int | |
| x_pitch: float | |
| y_pitch: float | |
| bbox: Tuple[float, float, float, float] | |
| frame_id: int | |
| timestamp: float | |
| class Ball: | |
| """Ball position""" | |
| x_pitch: float | |
| y_pitch: float | |
| bbox: Tuple[float, float, float, float] | |
| frame_id: int | |
| timestamp: float | |
| object_id: Optional[int] = None | |
| class FrameData: | |
| """Data for a single frame""" | |
| frame_id: int | |
| timestamp: float | |
| players: List[Player] | |
| ball: Optional[Ball] = None | |
| detections: List[Detection] = None | |
| class Location: | |
| """Pitch location""" | |
| x: float | |
| y: float | |
| class Event: | |
| """Detected event""" | |
| id: str | |
| type: EventType | |
| start_frame: int | |
| end_frame: int | |
| start_location: Location | |
| end_location: Location | |
| involved_players: List[int] # object_ids | |
| confidence: float | |
| timestamp_start: float | |
| timestamp_end: float | |
| class MatchData: | |
| """Complete match data""" | |
| match_id: str | |
| events: List[Event] | |
| metadata: dict | |