An end-to-end computer-vision pipeline that turns broadcast soccer footage into tactical analytics — detecting and tracking players, referees, and the ball, assigning teams by jersey color, compensating for camera motion, and computing real-world player speed, distance covered, and per-team ball possession.
Live output: per-player IDs and speed/distance, team-colored markers, ball-possession tracking, and camera-motion compensation.
Custom YOLO detector evaluated on a held-out test split (Apple M2 / MPS). Full report: EVALUATION.md.
| Metric | Test split | Val split |
|---|---|---|
| mAP@0.5 | 78.2% | 74.7% |
| mAP@0.5:0.95 | 52.4% | 52.7% |
| Precision | 83.2% | 83.6% |
| Recall | 77.5% | 72.3% |
Per-class mAP@0.5 (test): player 96.9% · goalkeeper 98.0% · referee 92.5% · ball 25.2% (small-object, the hard case)
- ~75 FPS detection-only throughput (batch 20, Apple M2 MPS) — real-time on the 750-frame sample clip.
- Baseline contrast: stock COCO
yolov8nhas no football roles — it collapses referees, goalkeepers, and players into a single genericpersonclass. The custom detector recovers those roles, which the entire downstream pipeline depends on.
- Object detection using a custom-trained YOLO model
- Object tracking across video frames using interpolation
- Team assignment using KMeans clustering on jersey colors
- Camera motion estimation using optical flow
- Perspective transformation to map pixel movement to real-world distance
- Player metrics: Ball control, speed and total distance covered
Object Detection -> Object Tracking -> Team Classification -> Camera Motion Compensation -> Perspective Transformation -> Player Metrics Calculation
Install dependencies (Python 3.11+ recommended) and run the pipeline:
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Analyze the bundled sample clip
python main.py
# Or run on your own video with custom settings
python main.py --input path/to/match.mp4 --output annotated.mp4 --device mpsThe output frame rate and speed metrics are auto-detected from the source video.
Run python main.py --help for all options:
| Flag | Default | Description |
|---|---|---|
-i, --input |
sample clip | Input match video |
-o, --output |
output_videos/output_video.mp4 |
Annotated output |
-m, --model |
models/best.pt |
YOLO detector weights |
--conf |
0.1 |
Detection confidence threshold |
--batch-size |
20 |
Frames per inference batch |
--device |
auto |
cpu / mps / cuda / auto |
--no-cache |
off | Recompute instead of using cached stubs |
--fps |
auto | Override the auto-detected frame rate |
For object detection, the out-of-the-box YOLOv8 model is not good enough for analysis, as it often labels people and objects on the sideline which are not involved in the match. Furthermore, it cannot distinguish between referees and players.
That is why I trained a custom YOLO model using a labeled soccer image dataset from Roboflow: https://universe.roboflow.com/roboflow-jvuqo/football-players-detection-3zvbc/dataset/1
Training was done on Google Colaboratory, with 100 epochs.
The following libraries were used in the project:
- ultralytics
- supervision
- OpenCV
- NumPy
- Matplotlib
- Pandas
