opensportslib 0.3.1.dev14__tar.gz → 0.3.1.dev15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opensportslib-0.3.1.dev14/opensportslib.egg-info → opensportslib-0.3.1.dev15}/PKG-INFO +1 -1
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/adaptation/spotta.py +4 -38
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/e2e_spotta.yaml +1 -10
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/datasets/localization_dataset.py +42 -4
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15/opensportslib.egg-info}/PKG-INFO +1 -1
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib.egg-info/SOURCES.txt +0 -1
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/pyproject.toml +1 -1
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_localization_intervals.py +20 -0
- opensportslib-0.3.1.dev14/tests/test_spotta_e2e.py +0 -285
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/LICENSE +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/LICENSE-COMMERCIAL +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/MANIFEST.in +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/README.md +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/examples/quickstart/basic_classification.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/examples/quickstart/basic_localization.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/examples/quickstart/basic_vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/adaptation/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/base_task_model.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/classification.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/config.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/configuration.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/localization.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/cli.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/classification/default.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/classification/sngar_frames.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/classification/sngar_tracking.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/classification/video.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/default.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/calf_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/default.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/h5_header_distance.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/h5_header_skeleton.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/netvladpp_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/tracking_action_spotting.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/video_dali.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/localization/video_ocv.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/vqa/default.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/vqa/qwen.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/vqa/qwen3_vl_native.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/vqa/qwen_lora.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/vqa/qwen_sngar_frames.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/vqa/xvars.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/accessors.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/conflicts.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/editable.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/loader.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/migrate.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/migrations/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/migrations/legacy_to_canonical.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/rule_variants.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/runtime_adapter.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/schema.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/schemas/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/schemas/schema_canonical.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/schemas/schema_legacy.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/config/validate.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/loss/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/loss/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/loss/calf.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/loss/ce.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/loss/combine.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/loss/nll.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/optimizer/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/optimizer/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/sampler/weighted_sampler.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/scheduler/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/scheduler/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/trainer/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/trainer/classification_trainer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/trainer/localization_trainer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/trainer/vqa_trainer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/checkpoint.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/config.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/config_normalize.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/data.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/ddp.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/default_args.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/direct_video.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/hf_runtime.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/lightning.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/load_annotations.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/seed.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/video_processing.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/core/utils/wandb.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/datasets/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/datasets/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/datasets/classification_dataset.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/datasets/utils/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/datasets/utils/h5_tracking.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/datasets/utils/tracking.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/datasets/vqa_dataset.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/legacy_config/classification.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/legacy_config/localization-e2e-ocv.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/legacy_config/localization-json_calf_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/legacy_config/localization-json_netvlad++_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/legacy_config/localization.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/legacy_config/sngar-frames.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/legacy_config/sngar-tracking.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/metrics/classification_metric.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/metrics/localization_metric.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/metrics/vqa_metric.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/backbones/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/contextaware.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/e2e.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/learnablepooling.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/qwen_vl_native.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/qwen_xvars.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/rule_based.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/tracking.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/vars.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/video.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/video_chatgpt_compat.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/video_mae.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/base/xvars_videochatgpt.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/heads/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/neck/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/common.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/impl/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/impl/asformer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/impl/calf.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/impl/gsm.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/impl/gtad.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/impl/tsm.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/litebase.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/modules.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/shift.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/utils.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/vqa_prediction_priors.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/vqa_prompting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/models/utils/xvars_clip_index.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/remote_registry.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/setup/setup.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/tools/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/tools/_common.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/tools/hf_transfer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/tools/osl_json_to_parquet.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/tools/parquet_to_osl_json.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib.egg-info/dependency_links.txt +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib.egg-info/entry_points.txt +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib.egg-info/requires.txt +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib.egg-info/top_level.txt +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/scripts/release_versions.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/scripts/run_h5_header_rule_inference.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/setup.cfg +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/conftest.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/release/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/release/_release_common.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/release/test_classification_release.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/release/test_localization_release.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/release/test_vqa_release.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_classification_dataset_paths.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_classification_trainer_dataloader.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_config_architecture.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_config_split_override_sync.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_config_utils_smoke.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_conversion_tools.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_editable_config.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_extract_xvars_features.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_h5_header_rule_spotter.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_h5_header_skeleton_spotter.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_h5_tracking_dataset.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_hf_transfer_tools.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_localization_dali_filenames.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_localization_hf_backend_override.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_optional_hf_config.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_package_smoke.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_pretrained_config_merge_policy.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_public_apis_smoke.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_release_versions.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_remote_model_registry.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_server_model_registry.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_setup_cli.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_subset_train_infer_integration.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_task_model_api_contract.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_vqa_api.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_vqa_metrics_semantic.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_vqa_qwen_xvars.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_vqa_training_lora.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_vqa_xvars_videochatgpt.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/build_sn_vqa_2026_vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/build_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/build_soccernet_gar.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/build_soccernet_gar_action_spotting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/build_soccernet_gar_vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/build_xvars_indexes.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/extract_xvars_clip_features.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/osl_json_to_parquet_webdataset.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/parquet_webdataset_to_osl_json.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/sngar_dataset_card.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/sngar_events.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/convert/verify_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/download/download_hf_repo.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/download/download_osl_hf.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/download/push_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/download/upload_osl_hf.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/training/classification.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/training/localization.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/training/vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tools/upload/upload_model_hf.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensportslib
|
|
3
|
-
Version: 0.3.1.
|
|
3
|
+
Version: 0.3.1.dev15
|
|
4
4
|
Summary: OpenSportsLib is the professional library, designed for advanced video understanding in sports. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with sports video data.
|
|
5
5
|
Author: Jeet Vora
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -59,7 +59,6 @@ class SpoTTAConfig:
|
|
|
59
59
|
drift_scale: float = 10.0
|
|
60
60
|
drift_threshold: float = 1.0
|
|
61
61
|
drift_gamma: float = 0.2
|
|
62
|
-
augmentation: bool = True
|
|
63
62
|
|
|
64
63
|
@classmethod
|
|
65
64
|
def from_mapping(cls, value: Any) -> "SpoTTAConfig":
|
|
@@ -70,7 +69,6 @@ class SpoTTAConfig:
|
|
|
70
69
|
memory = _mapping(root.get("memory"))
|
|
71
70
|
optimizer = _mapping(root.get("optimizer"))
|
|
72
71
|
teacher = _mapping(root.get("teacher"))
|
|
73
|
-
augmentation = _mapping(root.get("augmentation"))
|
|
74
72
|
|
|
75
73
|
_require_supported_value(
|
|
76
74
|
root,
|
|
@@ -78,34 +76,6 @@ class SpoTTAConfig:
|
|
|
78
76
|
"adapt_then_predict",
|
|
79
77
|
"adaptation",
|
|
80
78
|
)
|
|
81
|
-
_require_supported_value(tether, "mode", "bayesian", "robust_bn.tether")
|
|
82
|
-
_require_supported_value(
|
|
83
|
-
gate,
|
|
84
|
-
"uncertainty",
|
|
85
|
-
"one_minus_max_probability",
|
|
86
|
-
"confidence_gate",
|
|
87
|
-
)
|
|
88
|
-
_require_supported_value(
|
|
89
|
-
gate,
|
|
90
|
-
"aggregation",
|
|
91
|
-
"min_over_predicted_action_frames",
|
|
92
|
-
"confidence_gate",
|
|
93
|
-
)
|
|
94
|
-
_require_supported_value(optimizer, "type", "Adam", "optimizer")
|
|
95
|
-
_require_supported_value(
|
|
96
|
-
optimizer,
|
|
97
|
-
"trainable_parameters",
|
|
98
|
-
"batch_norm_affine_only",
|
|
99
|
-
"optimizer",
|
|
100
|
-
)
|
|
101
|
-
_require_supported_value(teacher, "type", "ema", "teacher")
|
|
102
|
-
_require_supported_value(
|
|
103
|
-
teacher, "adaptive_from_bn_drift", True, "teacher"
|
|
104
|
-
)
|
|
105
|
-
_require_supported_value(
|
|
106
|
-
augmentation, "mode", "framewise_rotta_strong", "augmentation"
|
|
107
|
-
)
|
|
108
|
-
|
|
109
79
|
config = cls(
|
|
110
80
|
alpha=float(robust_bn.get("alpha", cls.alpha)),
|
|
111
81
|
tether_cap=float(tether.get("cap", cls.tether_cap)),
|
|
@@ -133,7 +103,6 @@ class SpoTTAConfig:
|
|
|
133
103
|
teacher.get("drift_threshold", cls.drift_threshold)
|
|
134
104
|
),
|
|
135
105
|
drift_gamma=float(teacher.get("drift_gamma", cls.drift_gamma)),
|
|
136
|
-
augmentation=bool(augmentation.get("enabled", cls.augmentation)),
|
|
137
106
|
)
|
|
138
107
|
config.validate()
|
|
139
108
|
return config
|
|
@@ -577,13 +546,10 @@ class SpoTTA:
|
|
|
577
546
|
with torch.no_grad():
|
|
578
547
|
teacher_logits = _logits(self.teacher(clips))
|
|
579
548
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
).reshape(batch, time, channels, height, width)
|
|
585
|
-
else:
|
|
586
|
-
augmented = clips
|
|
549
|
+
batch, time, channels, height, width = clips.shape
|
|
550
|
+
augmented = self.augmentation(
|
|
551
|
+
clips.reshape(batch * time, channels, height, width)
|
|
552
|
+
).reshape(batch, time, channels, height, width)
|
|
587
553
|
|
|
588
554
|
self.student.train()
|
|
589
555
|
student_logits = _logits(self.student(augmented))
|
|
@@ -39,6 +39,7 @@ DATA:
|
|
|
39
39
|
resize:
|
|
40
40
|
height: 224
|
|
41
41
|
width: 398
|
|
42
|
+
preserve_aspect_ratio: true
|
|
42
43
|
params:
|
|
43
44
|
crop_dim: 224
|
|
44
45
|
dilate_len: 0
|
|
@@ -69,13 +70,10 @@ MODEL:
|
|
|
69
70
|
robust_bn:
|
|
70
71
|
alpha: 0.05
|
|
71
72
|
tether:
|
|
72
|
-
mode: bayesian
|
|
73
73
|
cap: 0.5
|
|
74
74
|
confidence_gate:
|
|
75
75
|
action_class_index: 1
|
|
76
76
|
min_action_frames: 1
|
|
77
|
-
uncertainty: one_minus_max_probability
|
|
78
|
-
aggregation: min_over_predicted_action_frames
|
|
79
77
|
threshold: 0.3
|
|
80
78
|
memory:
|
|
81
79
|
capacity: 8
|
|
@@ -83,21 +81,14 @@ MODEL:
|
|
|
83
81
|
lambda_t: 1.0
|
|
84
82
|
lambda_u: 1.0
|
|
85
83
|
optimizer:
|
|
86
|
-
type: Adam
|
|
87
84
|
learning_rate: 0.001
|
|
88
85
|
beta: 0.9
|
|
89
|
-
trainable_parameters: batch_norm_affine_only
|
|
90
86
|
teacher:
|
|
91
|
-
type: ema
|
|
92
87
|
base_nu: 0.001
|
|
93
|
-
adaptive_from_bn_drift: true
|
|
94
88
|
max_nu: 0.02
|
|
95
89
|
drift_scale: 10.0
|
|
96
90
|
drift_threshold: 1.0
|
|
97
91
|
drift_gamma: 0.2
|
|
98
|
-
augmentation:
|
|
99
|
-
enabled: true
|
|
100
|
-
mode: framewise_rotta_strong
|
|
101
92
|
|
|
102
93
|
TRAIN:
|
|
103
94
|
execution:
|
|
@@ -161,6 +161,7 @@ class LocalizationDataset(Dataset):
|
|
|
161
161
|
imagenet_std=normalization.get("std"),
|
|
162
162
|
target_height=resize.get("height"),
|
|
163
163
|
target_width=resize.get("width"),
|
|
164
|
+
preserve_aspect_ratio=resize.get("preserve_aspect_ratio", False),
|
|
164
165
|
)
|
|
165
166
|
annotation_path = annotations_path or getattr(
|
|
166
167
|
split_cfg, "annotation_path", getattr(split_cfg, "path", None)
|
|
@@ -346,6 +347,7 @@ class LocalizationDataset(Dataset):
|
|
|
346
347
|
IMAGENET_STD=self.data_cfg.imagenet_std,
|
|
347
348
|
TARGET_HEIGHT=self.data_cfg.target_height,
|
|
348
349
|
TARGET_WIDTH=self.data_cfg.target_width,
|
|
350
|
+
preserve_aspect_ratio=self.data_cfg.preserve_aspect_ratio,
|
|
349
351
|
)
|
|
350
352
|
elif dataset_type == "VideoGameWithOpencvVideo":
|
|
351
353
|
dataset = ActionSpotVideoDataset(
|
|
@@ -362,6 +364,7 @@ class LocalizationDataset(Dataset):
|
|
|
362
364
|
IMAGENET_STD=self.data_cfg.imagenet_std,
|
|
363
365
|
TARGET_HEIGHT=self.data_cfg.target_height,
|
|
364
366
|
TARGET_WIDTH=self.data_cfg.target_width,
|
|
367
|
+
preserve_aspect_ratio=self.data_cfg.preserve_aspect_ratio,
|
|
365
368
|
)
|
|
366
369
|
elif dataset_type == "VideoGameWithDali":
|
|
367
370
|
if not DALI_AVAILABLE:
|
|
@@ -543,6 +546,7 @@ class FrameReader:
|
|
|
543
546
|
sample_fps=2,
|
|
544
547
|
TARGET_HEIGHT=224,
|
|
545
548
|
TARGET_WIDTH=398,
|
|
549
|
+
preserve_aspect_ratio=False,
|
|
546
550
|
):
|
|
547
551
|
self._is_flow = modality == "flow"
|
|
548
552
|
self._crop_transform = crop_transform
|
|
@@ -551,6 +555,37 @@ class FrameReader:
|
|
|
551
555
|
self._sample_fps = sample_fps
|
|
552
556
|
self.TARGET_HEIGHT = TARGET_HEIGHT
|
|
553
557
|
self.TARGET_WIDTH = TARGET_WIDTH
|
|
558
|
+
self.preserve_aspect_ratio = preserve_aspect_ratio
|
|
559
|
+
|
|
560
|
+
def _resize_frame_ocv(self, frame):
|
|
561
|
+
"""Resize an OpenCV frame using the configured spatial policy.
|
|
562
|
+
|
|
563
|
+
With aspect preservation enabled, ``TARGET_HEIGHT`` fixes the output
|
|
564
|
+
height and the width is derived from the source aspect ratio. If no
|
|
565
|
+
target height is configured, ``TARGET_WIDTH`` fixes the output width.
|
|
566
|
+
"""
|
|
567
|
+
import cv2
|
|
568
|
+
|
|
569
|
+
height, width = frame.shape[:2]
|
|
570
|
+
if self.preserve_aspect_ratio:
|
|
571
|
+
if self.TARGET_HEIGHT is not None and self.TARGET_HEIGHT > 0:
|
|
572
|
+
scale = self.TARGET_HEIGHT / height
|
|
573
|
+
elif self.TARGET_WIDTH is not None and self.TARGET_WIDTH > 0:
|
|
574
|
+
scale = self.TARGET_WIDTH / width
|
|
575
|
+
else:
|
|
576
|
+
return frame
|
|
577
|
+
|
|
578
|
+
output_height = max(1, round(height * scale))
|
|
579
|
+
output_width = max(1, round(width * scale))
|
|
580
|
+
else:
|
|
581
|
+
output_height = self.TARGET_HEIGHT
|
|
582
|
+
output_width = self.TARGET_WIDTH
|
|
583
|
+
|
|
584
|
+
if output_height is None or output_width is None:
|
|
585
|
+
return frame
|
|
586
|
+
if (height, width) == (output_height, output_width):
|
|
587
|
+
return frame
|
|
588
|
+
return cv2.resize(frame, (output_width, output_height))
|
|
554
589
|
|
|
555
590
|
def adapt_frame_ocv(self, frame):
|
|
556
591
|
"""Apply some modifications to the frame to have the expected shape and format.
|
|
@@ -675,8 +710,7 @@ class FrameReader:
|
|
|
675
710
|
ret, frame = vc.read()
|
|
676
711
|
if ret:
|
|
677
712
|
if i % stride_extract == 0:
|
|
678
|
-
|
|
679
|
-
frame = cv2.resize(frame, (ow, oh))
|
|
713
|
+
frame = self._resize_frame_ocv(frame)
|
|
680
714
|
img = self.adapt_frame_ocv(frame)
|
|
681
715
|
if self._crop_transform:
|
|
682
716
|
if self._same_transform:
|
|
@@ -781,6 +815,7 @@ class ActionSpotDataset(Dataset):
|
|
|
781
815
|
IMAGENET_STD=[0.229, 0.224, 0.225],
|
|
782
816
|
TARGET_HEIGHT=224,
|
|
783
817
|
TARGET_WIDTH=398,
|
|
818
|
+
preserve_aspect_ratio=False,
|
|
784
819
|
):
|
|
785
820
|
import random
|
|
786
821
|
from opensportslib.core.utils.load_annotations import annotationstoe2eformat
|
|
@@ -850,7 +885,8 @@ class ActionSpotDataset(Dataset):
|
|
|
850
885
|
same_transform,
|
|
851
886
|
extract_fps,
|
|
852
887
|
self.TARGET_HEIGHT,
|
|
853
|
-
self.TARGET_WIDTH
|
|
888
|
+
self.TARGET_WIDTH,
|
|
889
|
+
preserve_aspect_ratio,
|
|
854
890
|
)
|
|
855
891
|
|
|
856
892
|
def load_frame_gpu(self, batch, device):
|
|
@@ -1097,6 +1133,7 @@ class ActionSpotVideoDataset(Dataset, DatasetVideoSharedMethods):
|
|
|
1097
1133
|
IMAGENET_STD=[0.229, 0.224, 0.225],
|
|
1098
1134
|
TARGET_HEIGHT=224,
|
|
1099
1135
|
TARGET_WIDTH=398,
|
|
1136
|
+
preserve_aspect_ratio=False,
|
|
1100
1137
|
):
|
|
1101
1138
|
from opensportslib.core.utils.load_annotations import annotationstoe2eformat, construct_labels
|
|
1102
1139
|
from opensportslib.core.utils.video_processing import _get_img_transforms
|
|
@@ -1138,7 +1175,8 @@ class ActionSpotVideoDataset(Dataset, DatasetVideoSharedMethods):
|
|
|
1138
1175
|
False,
|
|
1139
1176
|
extract_fps,
|
|
1140
1177
|
self.TARGET_HEIGHT,
|
|
1141
|
-
self.TARGET_WIDTH
|
|
1178
|
+
self.TARGET_WIDTH,
|
|
1179
|
+
preserve_aspect_ratio,
|
|
1142
1180
|
)
|
|
1143
1181
|
|
|
1144
1182
|
self._flip = flip
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensportslib
|
|
3
|
-
Version: 0.3.1.
|
|
3
|
+
Version: 0.3.1.dev15
|
|
4
4
|
Summary: OpenSportsLib is the professional library, designed for advanced video understanding in sports. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with sports video data.
|
|
5
5
|
Author: Jeet Vora
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -169,7 +169,6 @@ tests/test_release_versions.py
|
|
|
169
169
|
tests/test_remote_model_registry.py
|
|
170
170
|
tests/test_server_model_registry.py
|
|
171
171
|
tests/test_setup_cli.py
|
|
172
|
-
tests/test_spotta_e2e.py
|
|
173
172
|
tests/test_subset_train_infer_integration.py
|
|
174
173
|
tests/test_task_model_api_contract.py
|
|
175
174
|
tests/test_vqa_api.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "opensportslib"
|
|
7
|
-
version = "0.3.1.
|
|
7
|
+
version = "0.3.1.dev15"
|
|
8
8
|
description = "OpenSportsLib is the professional library, designed for advanced video understanding in sports. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with sports video data."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/tests/test_localization_intervals.py
RENAMED
|
@@ -209,6 +209,26 @@ def test_frame_reader_seeks_and_stops_inside_interval(monkeypatch):
|
|
|
209
209
|
assert max(capture.read_positions) < 50
|
|
210
210
|
|
|
211
211
|
|
|
212
|
+
def test_frame_reader_can_preserve_aspect_ratio_before_crop():
|
|
213
|
+
reader = FrameReader(
|
|
214
|
+
"rgb",
|
|
215
|
+
crop_transform=None,
|
|
216
|
+
img_transform=lambda image: image,
|
|
217
|
+
same_transform=False,
|
|
218
|
+
TARGET_HEIGHT=224,
|
|
219
|
+
TARGET_WIDTH=398,
|
|
220
|
+
preserve_aspect_ratio=True,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
four_by_three = np.zeros((224, 298, 3), dtype=np.uint8)
|
|
224
|
+
sixteen_by_nine = np.zeros((224, 398, 3), dtype=np.uint8)
|
|
225
|
+
scaled_four_by_three = np.zeros((448, 596, 3), dtype=np.uint8)
|
|
226
|
+
|
|
227
|
+
assert reader._resize_frame_ocv(four_by_three).shape == (224, 298, 3)
|
|
228
|
+
assert reader._resize_frame_ocv(sixteen_by_nine).shape == (224, 398, 3)
|
|
229
|
+
assert reader._resize_frame_ocv(scaled_four_by_three).shape == (224, 298, 3)
|
|
230
|
+
|
|
231
|
+
|
|
212
232
|
def test_v2_evaluator_scores_only_verified_logical_intervals(tmp_path):
|
|
213
233
|
verified = _record()
|
|
214
234
|
unlabeled = _record(status="unlabeled")
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from types import SimpleNamespace
|
|
4
|
-
from unittest.mock import patch
|
|
5
|
-
|
|
6
|
-
import torch
|
|
7
|
-
import pytest
|
|
8
|
-
from torch import nn
|
|
9
|
-
|
|
10
|
-
from opensportslib.core.config.accessors import get_loader_backend
|
|
11
|
-
from opensportslib.models.base.e2e import E2EModel
|
|
12
|
-
from opensportslib.adaptation.spotta import (
|
|
13
|
-
FramewiseStrongAugmentation,
|
|
14
|
-
RobustBatchNorm,
|
|
15
|
-
SpoTTA,
|
|
16
|
-
SpoTTAConfig,
|
|
17
|
-
replace_batch_norm,
|
|
18
|
-
)
|
|
19
|
-
from opensportslib.core.config import load_config
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class _TinyE2ESpot(nn.Module):
|
|
23
|
-
def __init__(self, num_classes=2, predicted_class=1):
|
|
24
|
-
super().__init__()
|
|
25
|
-
self.bn = nn.BatchNorm2d(3)
|
|
26
|
-
self.classifier = nn.Linear(3, num_classes)
|
|
27
|
-
with torch.no_grad():
|
|
28
|
-
self.classifier.weight.zero_()
|
|
29
|
-
self.classifier.bias.fill_(-2.0)
|
|
30
|
-
self.classifier.bias[predicted_class] = 2.0
|
|
31
|
-
|
|
32
|
-
def forward(self, clips):
|
|
33
|
-
batch, time, channels, height, width = clips.shape
|
|
34
|
-
frames = self.bn(clips.reshape(batch * time, channels, height, width))
|
|
35
|
-
features = frames.mean(dim=(-1, -2))
|
|
36
|
-
return self.classifier(features).reshape(batch, time, -1)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def _spotta_config(**overrides):
|
|
40
|
-
config = {
|
|
41
|
-
"enabled": True,
|
|
42
|
-
"name": "spotta",
|
|
43
|
-
"prediction_timing": "adapt_then_predict",
|
|
44
|
-
"robust_bn": {"alpha": 0.05, "tether": {"cap": 0.5}},
|
|
45
|
-
"confidence_gate": {
|
|
46
|
-
"action_class_index": 1,
|
|
47
|
-
"min_action_frames": 1,
|
|
48
|
-
"threshold": 0.3,
|
|
49
|
-
},
|
|
50
|
-
"memory": {
|
|
51
|
-
"capacity": 8,
|
|
52
|
-
"update_frequency": 2,
|
|
53
|
-
"lambda_t": 1.0,
|
|
54
|
-
"lambda_u": 1.0,
|
|
55
|
-
},
|
|
56
|
-
"optimizer": {"learning_rate": 0.001, "beta": 0.9},
|
|
57
|
-
"teacher": {
|
|
58
|
-
"base_nu": 0.001,
|
|
59
|
-
"max_nu": 0.02,
|
|
60
|
-
"drift_scale": 10.0,
|
|
61
|
-
"drift_threshold": 1.0,
|
|
62
|
-
"drift_gamma": 0.2,
|
|
63
|
-
},
|
|
64
|
-
"augmentation": {"enabled": False},
|
|
65
|
-
}
|
|
66
|
-
config.update(overrides)
|
|
67
|
-
return config
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def test_robust_batch_norm_preserves_eval_output_and_frozen_anchor():
|
|
71
|
-
torch.manual_seed(7)
|
|
72
|
-
source = nn.Sequential(nn.BatchNorm2d(3)).eval()
|
|
73
|
-
with torch.no_grad():
|
|
74
|
-
source[0].running_mean.copy_(torch.tensor([0.2, -0.1, 0.4]))
|
|
75
|
-
source[0].running_var.copy_(torch.tensor([0.7, 1.3, 2.0]))
|
|
76
|
-
source[0].weight.copy_(torch.tensor([0.8, 1.1, 0.9]))
|
|
77
|
-
source[0].bias.copy_(torch.tensor([-0.2, 0.3, 0.1]))
|
|
78
|
-
inputs = torch.randn(4, 3, 5, 5)
|
|
79
|
-
expected = source(inputs)
|
|
80
|
-
|
|
81
|
-
layers = replace_batch_norm(source, alpha=0.05)
|
|
82
|
-
source.eval()
|
|
83
|
-
actual = source(inputs)
|
|
84
|
-
|
|
85
|
-
assert len(layers) == 1
|
|
86
|
-
assert isinstance(layers[0], RobustBatchNorm)
|
|
87
|
-
assert torch.allclose(actual, expected, atol=1e-6, rtol=1e-5)
|
|
88
|
-
|
|
89
|
-
anchor_mean = layers[0].anchor_mean.clone()
|
|
90
|
-
source.train()
|
|
91
|
-
source(inputs + 2)
|
|
92
|
-
assert torch.equal(layers[0].anchor_mean, anchor_mean)
|
|
93
|
-
assert not torch.equal(layers[0].source_mean, anchor_mean)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def test_spotta_gates_actions_and_updates_every_second_gated_clip():
|
|
97
|
-
spotta = SpoTTA(_TinyE2ESpot(), _spotta_config())
|
|
98
|
-
clips = torch.randn(2, 4, 3, 5, 5)
|
|
99
|
-
|
|
100
|
-
predicted, probabilities = spotta.predict(clips, use_amp=False)
|
|
101
|
-
|
|
102
|
-
assert predicted.shape == (2, 4)
|
|
103
|
-
assert probabilities.shape == (2, 4, 2)
|
|
104
|
-
assert spotta.stats["clips_seen"] == 2
|
|
105
|
-
assert spotta.stats["clips_gated"] == 2
|
|
106
|
-
assert spotta.stats["memory_insertions"] == 2
|
|
107
|
-
assert spotta.stats["memory_occupancy"] == 2
|
|
108
|
-
assert spotta.stats["update_attempts"] == 1
|
|
109
|
-
assert spotta.stats["updates_completed"] == 1
|
|
110
|
-
assert {layer.tether_rho for layer in spotta.tether_layers} == {0.25}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def test_framewise_strong_augmentation_preserves_clip_frame_shape_and_range():
|
|
114
|
-
torch.manual_seed(11)
|
|
115
|
-
frames = torch.randn(3, 3, 16, 20)
|
|
116
|
-
|
|
117
|
-
augmented = FramewiseStrongAugmentation(image_size=16)(frames)
|
|
118
|
-
|
|
119
|
-
assert augmented.shape == frames.shape
|
|
120
|
-
assert float(augmented.min()) >= 0.0
|
|
121
|
-
assert float(augmented.max()) <= 1.0
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def test_e2e_wrapper_starts_fresh_spotta_without_mutating_source_model():
|
|
125
|
-
wrapper = E2EModel.__new__(E2EModel)
|
|
126
|
-
wrapper._model = _TinyE2ESpot()
|
|
127
|
-
wrapper._num_classes = 2
|
|
128
|
-
wrapper._multi_gpu = False
|
|
129
|
-
wrapper._test_time_adapter = None
|
|
130
|
-
source_state = {
|
|
131
|
-
name: tensor.clone() for name, tensor in wrapper._model.state_dict().items()
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
wrapper.configure_test_time_adaptation(_spotta_config())
|
|
135
|
-
wrapper.predict(torch.randn(2, 4, 3, 5, 5), use_amp=False)
|
|
136
|
-
first_adapter = wrapper._test_time_adapter
|
|
137
|
-
wrapper.configure_test_time_adaptation(_spotta_config())
|
|
138
|
-
|
|
139
|
-
assert wrapper._test_time_adapter is not first_adapter
|
|
140
|
-
for name, tensor in wrapper._model.state_dict().items():
|
|
141
|
-
assert torch.equal(tensor, source_state[name])
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def test_e2e_wrapper_keeps_one_spotta_instance_across_session_batches():
|
|
145
|
-
wrapper = E2EModel.__new__(E2EModel)
|
|
146
|
-
wrapper._model = _TinyE2ESpot()
|
|
147
|
-
wrapper._num_classes = 2
|
|
148
|
-
wrapper._multi_gpu = False
|
|
149
|
-
wrapper._test_time_adapter = None
|
|
150
|
-
wrapper.configure_test_time_adaptation(_spotta_config())
|
|
151
|
-
session_adapter = wrapper._test_time_adapter
|
|
152
|
-
|
|
153
|
-
wrapper.predict(torch.randn(1, 4, 3, 5, 5), use_amp=False)
|
|
154
|
-
wrapper.predict(torch.randn(1, 4, 3, 5, 5), use_amp=False)
|
|
155
|
-
|
|
156
|
-
assert wrapper._test_time_adapter is session_adapter
|
|
157
|
-
assert wrapper.test_time_adaptation_stats["clips_seen"] == 2
|
|
158
|
-
assert wrapper.test_time_adaptation_stats["memory_occupancy"] == 2
|
|
159
|
-
assert wrapper.test_time_adaptation_stats["updates_completed"] == 1
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
def test_disabled_spotta_uses_ordinary_e2e_prediction_path():
|
|
163
|
-
wrapper = E2EModel.__new__(E2EModel)
|
|
164
|
-
wrapper._model = _TinyE2ESpot()
|
|
165
|
-
wrapper._num_classes = 2
|
|
166
|
-
wrapper._multi_gpu = False
|
|
167
|
-
wrapper._test_time_adapter = None
|
|
168
|
-
wrapper.device = torch.device("cpu")
|
|
169
|
-
clips = torch.randn(2, 4, 3, 5, 5)
|
|
170
|
-
wrapper._model.eval()
|
|
171
|
-
with torch.no_grad():
|
|
172
|
-
expected_probabilities = wrapper._model(clips).softmax(dim=2)
|
|
173
|
-
expected_classes = expected_probabilities.argmax(dim=2)
|
|
174
|
-
|
|
175
|
-
wrapper.configure_test_time_adaptation({"enabled": False, "name": "spotta"})
|
|
176
|
-
predicted_classes, probabilities = wrapper.predict(clips, use_amp=False)
|
|
177
|
-
|
|
178
|
-
assert wrapper._test_time_adapter is None
|
|
179
|
-
assert torch.equal(torch.from_numpy(predicted_classes), expected_classes)
|
|
180
|
-
assert torch.allclose(
|
|
181
|
-
torch.from_numpy(probabilities), expected_probabilities, atol=1e-7
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
def test_spotta_supports_configured_action_class_in_multiclass_output():
|
|
186
|
-
config = _spotta_config()
|
|
187
|
-
config["confidence_gate"]["action_class_index"] = 2
|
|
188
|
-
spotta = SpoTTA(
|
|
189
|
-
_TinyE2ESpot(num_classes=4, predicted_class=2), config
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
predicted, probabilities = spotta.predict(
|
|
193
|
-
torch.randn(2, 4, 3, 5, 5), use_amp=False
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
assert predicted.shape == (2, 4)
|
|
197
|
-
assert probabilities.shape == (2, 4, 4)
|
|
198
|
-
assert torch.from_numpy(predicted).eq(2).all()
|
|
199
|
-
assert spotta.stats["clips_gated"] == 2
|
|
200
|
-
assert spotta.stats["updates_completed"] == 1
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
def test_spotta_config_rejects_negative_action_class_index():
|
|
204
|
-
config = _spotta_config()
|
|
205
|
-
config["confidence_gate"]["action_class_index"] = -1
|
|
206
|
-
|
|
207
|
-
with pytest.raises(ValueError, match="must be non-negative"):
|
|
208
|
-
SpoTTAConfig.from_mapping(config)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
def test_spotta_rejects_action_class_outside_model_outputs():
|
|
212
|
-
config = _spotta_config()
|
|
213
|
-
config["confidence_gate"]["action_class_index"] = 4
|
|
214
|
-
spotta = SpoTTA(_TinyE2ESpot(num_classes=4), config)
|
|
215
|
-
|
|
216
|
-
with pytest.raises(ValueError, match="outside the model's 4 output classes"):
|
|
217
|
-
spotta.predict(torch.randn(1, 4, 3, 5, 5), use_amp=False)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
def test_spotta_config_rejects_unsupported_semantic_changes():
|
|
221
|
-
config = _spotta_config()
|
|
222
|
-
config["confidence_gate"]["aggregation"] = "mean"
|
|
223
|
-
|
|
224
|
-
try:
|
|
225
|
-
SpoTTAConfig.from_mapping(config)
|
|
226
|
-
except ValueError as exc:
|
|
227
|
-
assert "min_over_predicted_action_frames" in str(exc)
|
|
228
|
-
else:
|
|
229
|
-
raise AssertionError("Expected a changed confidence aggregation to fail.")
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
def test_spotta_config_contains_only_supported_options():
|
|
233
|
-
with patch(
|
|
234
|
-
"opensportslib.core.config.loader._dali_available", return_value=False
|
|
235
|
-
):
|
|
236
|
-
config = load_config(
|
|
237
|
-
"opensportslib/configs/localization/e2e_spotta.yaml",
|
|
238
|
-
as_namespace=False,
|
|
239
|
-
)
|
|
240
|
-
spotta_config = config["MODEL"]["policies"]["test_time_adaptation"]
|
|
241
|
-
|
|
242
|
-
assert spotta_config["enabled"] is True
|
|
243
|
-
assert spotta_config["prediction_timing"] == "adapt_then_predict"
|
|
244
|
-
assert spotta_config["confidence_gate"]["threshold"] == 0.3
|
|
245
|
-
assert spotta_config["memory"]["capacity"] == 8
|
|
246
|
-
assert spotta_config["memory"]["update_frequency"] == 2
|
|
247
|
-
assert spotta_config["robust_bn"]["tether"]["mode"] == "bayesian"
|
|
248
|
-
assert "class_policy" not in spotta_config["memory"]
|
|
249
|
-
assert "frame_filter" not in spotta_config
|
|
250
|
-
assert "steps" not in spotta_config
|
|
251
|
-
assert "reset_frequency" not in spotta_config
|
|
252
|
-
assert "action_frame_weight" not in spotta_config
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
def test_localization_starts_fresh_spotta_session_and_forces_opencv_runtime():
|
|
256
|
-
from opensportslib.apis.localization import LocalizationModel
|
|
257
|
-
|
|
258
|
-
configured = []
|
|
259
|
-
|
|
260
|
-
class _Model:
|
|
261
|
-
def configure_test_time_adaptation(self, adaptation):
|
|
262
|
-
configured.append(adaptation)
|
|
263
|
-
|
|
264
|
-
adaptation = SimpleNamespace(enabled=True, name="spotta")
|
|
265
|
-
api = LocalizationModel.__new__(LocalizationModel)
|
|
266
|
-
api.model = _Model()
|
|
267
|
-
api.config = SimpleNamespace(
|
|
268
|
-
MODEL=SimpleNamespace(
|
|
269
|
-
metadata=SimpleNamespace(family="E2E"),
|
|
270
|
-
policies=SimpleNamespace(test_time_adaptation=adaptation),
|
|
271
|
-
),
|
|
272
|
-
DATA=SimpleNamespace(
|
|
273
|
-
common=SimpleNamespace(
|
|
274
|
-
runtime=SimpleNamespace(loader_backend="dali"),
|
|
275
|
-
splits=SimpleNamespace(
|
|
276
|
-
test=SimpleNamespace(type="VideoGameWithOpencvVideo")
|
|
277
|
-
),
|
|
278
|
-
)
|
|
279
|
-
),
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
api._configure_test_time_adaptation()
|
|
283
|
-
|
|
284
|
-
assert configured == [adaptation]
|
|
285
|
-
assert get_loader_backend(api.config) == "opencv"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/examples/quickstart/basic_classification.py
RENAMED
|
File without changes
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/examples/quickstart/basic_localization.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/adaptation/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/base_task_model.py
RENAMED
|
File without changes
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/apis/classification.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/vqa/default.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev15}/opensportslib/configs/vqa/qwen_lora.yaml
RENAMED
|
File without changes
|