Handball Tracking makes broadcast match footage easier to inspect. It detects people and the ball, follows their movement, places reliable floor positions on a 40 × 20 metre tactical map, and exports timelines for further analysis. The annotated video and court view stay synchronized frame by frame.
Quick start · Measured results · Technical methods · Datasets · Models
| Stage | Result |
|---|---|
| Detect | Players, goalkeepers, referees, the ball, and 37 court landmarks |
| Track | Scene-aware person tracklets with ByteTrack and bounded ball predictions |
| Calibrate | Bidirectional homography between video pixels and court metres |
| Visualize | Court lines on video, player/ball trails, and camera field of view |
| Analyze | Possession states and evidence-based goal, shot, save, foul, and transition candidates |
| Export | Annotated MP4 plus trajectories, calibration, possession, events, and run metadata |
The pipeline processes frames as a stream. Separate models handle people, the ball, and court landmarks; timestamps always refer to the source video.
The included 32-second sample contains 803 frames and three broadcast-camera scenes. The final run recognizes both camera cuts and produces valid metric court coordinates on 738 frames.
| Measurement | Result |
|---|---|
| Processed video | 803 / 803 frames |
| Valid court calibration | 738 frames — 91.9% |
| Camera cuts / scenes | 2 / 3 |
| Observed ball frames | 167 |
| Short predicted ball frames | 302 |
| Person observations | 11,085 |
| Distinct scene-aware tracklets | 76 |
When calibration cannot pass the geometric checks, the tactical map displays
Calibration unavailable and omits metric positions. This prevents image pixels
from being presented as physically meaningful court coordinates.
Use Python 3.12 and the sample assets described in Models.
git clone https://github.com/elymeraj/Handball_Tracking.git
cd Handball_Tracking
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel
python -m pip install -r requirements-dev.txt
python -m pip checkRun a short 90-frame check:
python main.py \
--input input_videos/video2.mp4 \
--output output_videos/demo.mp4 \
--output-dir outputs/demo \
--max-frames 90 \
--calibration configs/demo_video2_calibration.yaml \
--cache outputs/inference_cacheRun the complete sample by removing --max-frames:
python main.py \
--input input_videos/video2.mp4 \
--output output_videos/handball_tracking_demo.mp4 \
--output-dir outputs/handball_tracking_demo \
--calibration configs/demo_video2_calibration.yaml \
--cache outputs/inference_cacheThe first CPU run performs inference with all three models and can take more than one hour. The optional cache makes later renders much faster while still recomputing tracking, calibration, analytics, exports, and visualization. Cache keys include the source video, model hashes, inference settings, preprocessing, device, and Ultralytics version.
For another video, omit --calibration to use pose-only initialization or
provide a seed file with known video/court point correspondences. Run
python main.py --help for clipping, device, cache, and configuration options.
| File | Contents |
|---|---|
| Annotated MP4 | Detections, projected lines, tactical map, trails, and camera footprint |
trajectories.csv |
Frame, time, scene, track, object type, pixels, metres, confidence, and state |
possession.csv |
possessed, free, or uncertain with nullable player/team IDs |
events.csv, events.jsonl |
Timestamped event candidates, actors, evidence, and confidence |
calibration.csv, calibration.jsonl |
Status, fitting quality, homographies, and camera footprint |
summary.json |
Input/output metadata, configuration, counts, availability, and processing speed |
| Review images | Preview, sampled frames, detected-ball example, and trajectory plot |
Track ID 0 is reserved for the ball. Person IDs are tracklets within a camera
scene and are not athlete identities. Observed, predicted, and missing ball
states remain separate throughout the exports.
The people detector reaches 0.969 mAP50 on its complete test split. The ball detector reaches 0.581 mAP50 and 0.50 recall, making missed ball observations the main constraint on possession and event cues. The court model is evaluated for both its object box and landmark pose; a good court box alone does not establish an accurate metric map. The chart, per-class values, and full-video measurements are in Results.
The runtime uses three custom checkpoints:
| Checkpoint | Purpose | Input size |
|---|---|---|
models/best.pt |
Goalkeeper, player, and referee detection | 640 |
models/best_ball_fin_53.pt |
Ball detection | 800 |
models/best_keypoints.pt |
Court box and 37-point pose | 640 |
See Models for the checkpoint files, hashes, and sample-video setup.
Training and evaluation data come from these versioned Roboflow exports:
| Dataset | Version | Train / validation / test |
|---|---|---|
| Handball Player Detection | 2 | 852 / 112 / 102 |
| handball-ballon | 13 | 972 / 121 / 120 |
| handball-pitch-points | 6 | 462 / 58 / 58 |
See Datasets for labels, preprocessing, attribution, and the local layout needed for training or evaluation.
YOLOv8 provides frame measurements; ByteTrack maintains person tracklets; RANSAC homography maps floor points into metres; optical flow carries valid calibration through camera motion. Technical Methods explains these stages with sourced illustrations, simple formulas, and their effect on this video. Notebook 05 contains executable examples for readers who want to inspect the calculations.
Download the datasets into the documented folders before running evaluation or training:
python scripts/evaluate_models.py --audit-only
python scripts/evaluate_models.py --model all --split test
python scripts/train_model.py --helpThe five notebooks can be viewed directly on GitHub or executed with the project interpreter:
01_dataset_and_model_audit.ipynb— schemas, counts, and labeled examples.02_detection_evaluation.ipynb— test metrics and failure inspection.03_court_keypoints_and_homography.ipynb— calibration and camera footprint.04_end_to_end_analysis.ipynb— trajectories, possession, and event outputs.05_technical_methods.ipynb— equations and executable method examples.
python -m jupyterlab notebooks
python scripts/execute_notebooks.pypython -m pytest -q
python -m compileall -q handball_tracking scripts tests main.py
python -m pip checkThe regression suite covers coordinate conventions, person and ball tracking, bounded predictions, homographies, horizon rejection, camera footprints, pose/flow fallback, scene cuts, possession, events, cache invalidation, timestamps, exports, and video I/O. GitHub Actions runs the same checks without downloading the large runtime assets.
- Fast ball motion, blur, and occlusion reduce detection continuity.
- Homography describes the floor plane; an airborne ball does not lie on it.
- Invalid or unavailable calibration deliberately produces no metric position.
- Appearance-based person re-identification across camera cuts is not included.
- Team colors require configured references and are disabled by default.
- Possession and event outputs are review cues without a labeled event benchmark.
- Source audio is not copied, and timing uses the video container's nominal FPS.
handball_tracking/ detection, tracking, geometry, analytics, rendering, export
configs/ runtime settings, landmark map, sample calibration seed
scripts/ pipeline, evaluation, training, plotting, documentation tools
notebooks/ explanatory and executable analyses
tests/ regression tests
models/ three runtime checkpoints
training/ dataset manifests and attribution
reports/ compact inventories and measured metrics
docs/ methods, calibration, datasets, models, and results
input_videos/ reproducible sample
outputs/ ignored structured run outputs and caches
output_videos/ ignored generated videos
The animated preview plays directly on GitHub. The full annotated MP4 can be attached to a GitHub Release as a download without cloning the code or weights.