SoccerNetPro is the professional extension of the popular SoccerNet library, designed for advanced video understanding in soccer. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with soccer video data.
Project description
SoccerNetPro
SoccerNetPro is the professional extension of the popular SoccerNet library, designed for advanced video understanding in soccer. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with soccer video data.
Development
### Clone the github repo
git clone https://github.com/OpenSportsLab/soccernetpro.git
### Requirements and installation ###
conda create -n SoccerNet python=3.12 pip
conda activate SoccerNet
pip install -e .
or
pip install -e .[localization]
or
pip install -e .[tracking]
### git branch and merge rules ###
1. Check and verify current branch is "dev" - git status
2. Create new branch from source "dev" -
git pull
git checkout -b <new_feature/fix/bug>
3. Raise PR request to merge your branch <new_feature/fix/bug> to "dev" branch
Installation
conda create -n SoccerNet python=3.12 pip
conda activate SoccerNet
pip install --pre soccernetpro
🤝 Contributing & Developer Guide
We welcome contributions to SoccerNetPro.
- 📘 Contributor Guide: CONTRIBUTING.md
- 🛠 Developer Guide: DEVELOPERS.md
These documents explain:
- How to add models and datasets
- Coding standards
- Training pipeline structure
- How to run and test the framework
Configuration Sample (.yaml) file
- Classification
TASK: classification
DATA:
dataset_name: mvfouls
data_dir: /home/vorajv/soccernetpro/SoccerNet/mvfouls
view_type: multi # multi or single
num_classes: 8 # mvfoul
train:
type: annotations_train.json
video_path: ${DATA.data_dir}/train
path: ${DATA.train.video_path}/annotations-train.json
dataloader:
batch_size: 8
shuffle: true
num_workers: 4
pin_memory: true
valid:
type: annotations_valid.json
video_path: ${DATA.data_dir}/valid
path: ${DATA.valid.video_path}/annotations-valid.json
dataloader:
batch_size: 1
num_workers: 1
shuffle: false
test:
type: annotations_test.json
video_path: ${DATA.data_dir}/test
path: ${DATA.test.video_path}/annotations-test.json
dataloader:
batch_size: 1
num_workers: 1
shuffle: false
num_frames: 16 # 8 before + 8 after the foul
input_fps: 25 # Original FPS of video
target_fps: 17 # Temporal downsampling to 1s clip (approx)
start_frame: 63 # Start frame of clip relative to foul frame
end_frame: 87 # End frame of clip relative to foul frame
frame_size: [224, 224] # Spatial resolution (HxW)
augmentations:
random_affine: true
translate: [0.1, 0.1]
affine_scale: [0.9, 1.0]
random_perspective: true
distortion_scale: 0.3
perspective_prob: 0.5
random_rotation: true
rotation_degrees: 5
color_jitter: true
jitter_params: [0.2, 0.2, 0.2, 0.1] # brightness, contrast, saturation, hue
random_horizontal_flip: true
flip_prob: 0.5
random_crop: false
MODEL:
type: custom # huggingface, custom
backbone:
type: mvit_v2_s # video_mae, r3d_18, mc3_18, r2plus1d_18, s3d, mvit_v2_s
neck:
type: MV_Aggregate
agr_type: max # max, mean, attention
head:
type: MV_LinearLayer
pretrained_model: mvit_v2_s # MCG-NJU/videomae-base, OpenGVLab/VideoMAEv2-Base, r3d_18, mc3_18, r2plus1d_18, s3d, mvit_v2_s
unfreeze_head: true # for videomae backbone
unfreeze_last_n_layers: 3 # for videomae backbone
TRAIN:
enabled: true
use_weighted_sampler: false
use_weighted_loss: true
epochs: 20 #20
save_dir: ./checkpoints
log_interval: 10
save_every: 2 #5
criterion:
type: CrossEntropyLoss
optimizer:
type: AdamW
lr: 0.0001 #0.001
backbone_lr: 0.00005
head_lr: 0.001
betas: [0.9, 0.999]
eps: 0.0000001
weight_decay: 0.001 #0.01 - videomae, 0.001 - others
amsgrad: false
scheduler:
type: StepLR
step_size: 3
gamma: 0.1
SYSTEM:
log_dir: ./logs
seed: 42
GPU: 4
device: cuda # auto | cuda | cpu
gpu_id: 0
- Localization
TASK: localization
dali: True
DATA:
dataset_name: SoccerNet
data_dir: /home/vorajv/soccernetpro/SoccerNet/annotations/
classes:
- PASS
- DRIVE
epoch_num_frames: 500000
mixup: true
modality: rgb
crop_dim: -1
dilate_len: 0 # Dilate ground truth labels
clip_len: 100
input_fps: 25
extract_fps: 2
imagenet_mean: [0.485, 0.456, 0.406]
imagenet_std: [0.229, 0.224, 0.225]
target_height: 224
target_width: 398
train:
type: VideoGameWithDali
classes: ${DATA.classes}
output_map: [data, label]
video_path: ${DATA.data_dir}/train/
path: ${DATA.train.video_path}/annotations-train.json
dataloader:
batch_size: 8
shuffle: true
num_workers: 4
pin_memory: true
valid:
type: VideoGameWithDali
classes: ${DATA.classes}
output_map: [data, label]
video_path: ${DATA.data_dir}/valid/
path: ${DATA.valid.video_path}/annotations-valid.json
dataloader:
batch_size: 8
shuffle: true
valid_data_frames:
type: VideoGameWithDaliVideo
classes: ${DATA.classes}
output_map: [data, label]
video_path: ${DATA.valid.video_path}
path: ${DATA.valid.path}
overlap_len: 0
dataloader:
batch_size: 4
shuffle: false
test:
type: VideoGameWithDaliVideo
classes: ${DATA.classes}
output_map: [data, label]
video_path: ${DATA.data_dir}/test/
path: ${DATA.test.video_path}/annotations-test.json
results: results_spotting_test
nms_window: 2
metric: loose
overlap_len: 50
dataloader:
batch_size: 4
shuffle: false
challenge:
type: VideoGameWithDaliVideo
overlap_len: 50
output_map: [data, label]
path: ${DATA.data_dir}/challenge/annotations.json
dataloader:
batch_size: 4
shuffle: false
MODEL:
type: E2E
runner:
type: runner_e2e
backbone:
type: rny008_gsm
head:
type: gru
multi_gpu: true
load_weights: null
save_dir: ./checkpoints
work_dir: ${MODEL.save_dir}
TRAIN:
type: trainer_e2e
num_epochs: 10
acc_grad_iter: 1
base_num_valid_epochs: 30
start_valid_epoch: 1
valid_map_every: 1
criterion_valid: map
criterion:
type: CrossEntropyLoss
optimizer:
type: AdamWithScaler
lr: 0.001
scheduler:
type: ChainedSchedulerE2E
acc_grad_iter: 1
num_epochs: ${TRAIN.num_epochs}
warm_up_epochs: 3
SYSTEM:
log_dir: ./logs
seed: 42
GPU: 4 # number of gpus to use
device: cuda # auto | cuda | cpu
gpu_id: 0 # device id for single gpu training
Annotations (train/valid/test) (.json) format
Download annotations file from below links
-
Classification mvfouls = https://huggingface.co/datasets/OpenSportsLab/soccernetpro-classification-vars/tree/mvfouls svfouls = https://huggingface.co/datasets/OpenSportsLab/soccernetpro-classification-vars/tree/svfouls
-
Localization ball-action-spotting = https://huggingface.co/datasets/OpenSportsLab/soccernetpro-localization-snbas/tree/main
Download weights from HF
- classification (mvit) https://huggingface.co/jeetv/snpro-classification-mvit/tree/main
Usage:
### Load weights from HF ###
myModel.infer(
test_set="/path/to/annotations.json",
pretrained="jeetv/snpro-classification-mvit", # Important
)
Train on SINGLE GPU
from soccernetpro import model
import wandb
# Initialize model with config
myModel = model.classification(
config="/path/to/classification.yaml"
)
# Train on your dataset
myModel.train(
train_set="/path/to/train_annotations.json",
valid_set="/path/to/valid_annotations.json",
pretrained=/path/to/ # or path to pretrained checkpoint
)
Train on Multiple GPU (DDP)
from soccernetpro import model
def main():
myModel = model.classification(
config="/path/to/classification.yaml",
data_dir="/path/to/dataset_root"
)
myModel.train(
train_set="/path/to/train_annotations.json",
valid_set="/path/to/valid_annotations.json",
pretrained="/path/to/pretrained.pt", # optional
use_ddp=True, # IMPORTANT
)
if __name__ == "__main__":
main()
Test / Inference on SINGLE GPU
from soccernetpro import model
# Load trained model
myModel = model.classification(
config="/path/to/classification.yaml"
)
# Run inference on test set
metrics = myModel.infer(
test_set="/path/to/test_annotations.json",
pretrained="/path/to/checkpoints/final_model",
predictions="/path/to/predictions.json"
)
Test / Inference on Multiple GPU (DDP)
from soccernetpro import model
def main():
myModel = model.classification(
config="/path/to/classification.yaml",
data_dir="/path/to/dataset_root"
)
metrics = myModel.infer(
test_set="/path/to/test_annotations.json",
pretrained="/path/to/checkpoints/best.pt",
predictions="/path/to/predictions.json",
use_ddp=True, # optional (usually not needed)
)
print(metrics)
if __name__ == "__main__":
main()
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file soccernetpro-0.0.1.dev7.tar.gz.
File metadata
- Download URL: soccernetpro-0.0.1.dev7.tar.gz
- Upload date:
- Size: 110.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f31d5a014d52ef15f21d686ecd1ecb55c3ec0bdfff902093fe54e1f1e54cfdb3
|
|
| MD5 |
ea88163d67482ce7ff2b936fcb55c1cb
|
|
| BLAKE2b-256 |
3e6bd5013adc944d746ef33c894dad777fe9169fd0953934d201f69060a98b51
|
File details
Details for the file soccernetpro-0.0.1.dev7-py3-none-any.whl.
File metadata
- Download URL: soccernetpro-0.0.1.dev7-py3-none-any.whl
- Upload date:
- Size: 137.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f1c0d4255c925f9777eada1b286a612900ae347b84fe42c6b95d8dade4721d3
|
|
| MD5 |
ef09e3c4e2b2d3fe3d303adfa9d8d076
|
|
| BLAKE2b-256 |
19603cf923e93ef857a91b5e685c8ba6aff7d0d8181553551c467f8ad95e99c7
|