Instructions to use acatorcini/yolov9-soccer-ball with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- ultralytics
How to use acatorcini/yolov9-soccer-ball with ultralytics:
from ultralytics import YOLOvv9 model = YOLOvv9.from_pretrained("acatorcini/yolov9-soccer-ball") source = 'http://images.cocodataset.org/val2017/000000039769.jpg' model.predict(source=source, save=True) - Notebooks
- Google Colab
- Kaggle
yolov9-soccer-ball
Custom YOLOv9 ball detector for amateur-level soccer footage. ~22 MB.
Standard YOLO weights (COCO etc.) struggle to detect a soccer ball at the small pixel scales typical of sideline-camera amateur footage (~3-5 px ball at 50 m distance, 1080p). This checkpoint was fine-tuned specifically on that regime and is the ball detector used by the soccer-video-pipeline project for per-frame ball grounding.
Two inference paths
Both v9b_best.pt (Ultralytics format) and v9b_best.onnx are in this repo.
Use the ONNX path if you want to avoid the AGPL Ultralytics runtime
dependency.
Option A β ONNX + onnxruntime (Apache 2.0 dependency chain)
pip install onnxruntime opencv-python numpy
import cv2, numpy as np, onnxruntime as ort
sess = ort.InferenceSession("v9b_best.onnx",
providers=["CPUExecutionProvider"]) # or CUDAExecutionProvider
img = cv2.imread("path/to/frame.jpg")
# preprocess: BGR->RGB, resize to 1280, normalize 0-1, NCHW
resized = cv2.resize(img, (1280, 1280))
x = resized[..., ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0
x = x[None] # (1, 3, 1280, 1280)
outputs = sess.run(None, {sess.get_inputs()[0].name: x})
# outputs[0] shape: (1, 5, N) for single-class YOLOv9 β x,y,w,h,conf per anchor
# Apply NMS + confidence threshold; see ultralytics/utils/ops.py for reference
Option B β Ultralytics (AGPL-3.0)
from ultralytics import YOLO
model = YOLO("v9b_best.pt")
results = model("path/to/frame.jpg")
for r in results:
for box in r.boxes:
x1, y1, x2, y2 = box.xyxy[0].tolist()
conf = box.conf[0].item()
print(f"ball at ({x1:.0f},{y1:.0f})-({x2:.0f},{y2:.0f}) conf={conf:.2f}")
The model outputs a single class (ball). The pipeline default threshold is
conf > 0.2 β at amateur-distance footage ball-class confidence typically
sits in 0.15-0.35.
Training data
Custom labeled set of amateur soccer match frames, sideline camera, 1080p, varied venues + lighting. Training data not redistributed.
Performance characteristics
- Ball detection coverage: ~63% of frames in production (vs <5% for stock YOLO weights at this camera distance)
- Useful confidence band: 0.15-0.35 β well below the typical "useful" threshold for object detection but the right band for tiny objects
- Frame sampling rate in production: 5 seconds (so ~63% of those sparse samples have a detected ball)
Intended use
Per-frame ball grounding in the soccer-video-pipeline kickoff-pattern detector. Also useful as a standalone amateur-soccer ball detector.
Limitations
- Trained for sideline-camera framings at amateur match distances. Performs worse on close-up footage or drone shots.
- Single-class output (just ball) β no player detection.
License
The weights themselves carry AGPL-3.0 (inherited from the Ultralytics training framework that produced them). The ONNX runtime path lets you use the WEIGHTS without bundling the AGPL CODE β which is the relevant distinction for many downstream projects (your code and the AGPL training tool stay separable).
Related
- Player detector used by the pipeline: uisikdag/weed_soccer_models (yolov8_soccer)
- Pipeline source: github.com/acato/soccer-video-pipeline
- Downloads last month
- 56
from ultralytics import YOLOvv9 model = YOLOvv9.from_pretrained("acatorcini/yolov9-soccer-ball") source = 'http://images.cocodataset.org/val2017/000000039769.jpg' model.predict(source=source, save=True)