Pitch registration for soccer broadcast video: for each frame, compute the homography mapping the real pitch (meters) to image pixels, then draw the pitch boundary and 18-yard boxes and expose zone geometry for analytics.
The pipeline is a health-gated hybrid: PnLCalib (SoccerNet-trained keypoint + line models) initializes the fit when available, a paint-anchored distance- transform optimizer refines it against the actual white lines, and a YOLO keypoint pipeline serves as fallback.
- Python 3.9+
- Packages:
ultralytics,opencv-python,numpy,scipy(installingultralyticspulls intorch/torchvision) - For the PnLCalib backend (optional but recommended):
lsq-ellipse,shapely
pip install ultralytics opencv-python numpy scipy lsq-ellipse shapely
Place the broadcast video at Video/usa_paraguay.mp4 (or edit VIDEO_PATH
in pitch_mapper.py). Set PITCH_LENGTH / PITCH_WIDTH for the venue
(defaults 105 x 68 m, the FIFA standard).
-
YOLO pitch keypoints —
Models/football-pitch-detection.pt(~134 MB), the 32-landmark pitch keypoint model from the Roboflow sports project. -
PnLCalib (optional, much better across broadcast styles):
git clone https://github.com/mguti97/PnLCalib.git curl -L -o PnLCalib/weights/SV_kp https://github.com/mguti97/PnLCalib/releases/download/v1.0.0/SV_kp curl -L -o PnLCalib/weights/SV_lines https://github.com/mguti97/PnLCalib/releases/download/v1.0.0/SV_linesIf the clone or weights are missing, everything still runs on the YOLO fallback alone.
Live viewer (overlays pitch boundary, 18-yard boxes, corner flags; q quits):
python3 pitch_mapper.py
Full calibration runs every ~2s of video with cheap tracking in between; the overlay hides itself when no trustworthy fit exists (replays, close-ups).
Test Images/Pitch Detection/ holds test frames, a graded baseline, and
hand-verified ground truth. The quiz grades verified frames absolutely (each
landmark within 12px of hand-placed truth) and unverified frames by
regression against the baseline.
python3 test_pitch_detection.py # take the quiz
python3 test_pitch_detection.py --report # render the worst fits
python3 test_pitch_detection.py --update # re-baseline after a verified improvement
python3 test_pitch_detection.py --annotate # build annotator.html to verify ground truth
python3 test_pitch_detection.py --sample-random N # add N random frames to the test set
Ground-truth workflow: --annotate, open
Test Images/Pitch Detection/annotator.html in a browser, correct/verify
frames, Export, and move the downloaded ground_truth.json into
Test Images/Pitch Detection/.
For personal use, everything below is fine as-is. Revisit before distributing this software or offering it as a service.
- Ultralytics / YOLO weights (
Models/football-pitch-detection.pt, the archived player models): theultralyticslibrary and models trained with it are AGPL-3.0. AGPL obligations (source disclosure) trigger on distribution or network service, not personal use. - PnLCalib (code and released weights): GPL-2.0. Same story — personal use is unrestricted; distribution requires GPL compliance.
- SoccerNet data: PnLCalib's weights were trained on the SoccerNet-Calibration dataset, which is released for research / non-commercial purposes. Factor that in before any commercial use of those weights.
Model weights and the PnLCalib clone are gitignored (files exceed GitHub's 100 MB limit); test images, baseline, and ground truth are small and are meant to be committed.