Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub (part 24)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +3 -0
- .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/INSTALLER +1 -0
- .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/METADATA +398 -0
- .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/RECORD +604 -0
- .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/REQUESTED +0 -0
- .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/WHEEL +5 -0
- .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/entry_points.txt +3 -0
- .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/licenses/LICENSE +661 -0
- .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/top_level.txt +1 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/files.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/git.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/instance.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/logger.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/loss.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/metrics.cpython-314.pyc +3 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/nms.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/ops.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/patches.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/plotting.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tal.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/torch_utils.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tqdm.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/triton.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tuner.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/uploads.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/autobatch.py +131 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/autodevice.py +207 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/benchmarks.py +618 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__init__.py +5 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/__init__.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/base.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/clearml.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/comet.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/dvc.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/hub.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/mlflow.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/neptune.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/platform.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/raytune.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/tensorboard.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/wb.cpython-314.pyc +0 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/base.py +235 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/clearml.py +146 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/comet.py +622 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/dvc.py +197 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/hub.py +111 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/mlflow.py +162 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/neptune.py +126 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/platform.py +553 -0
- .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/raytune.py +42 -0
.gitattributes
CHANGED
|
@@ -821,3 +821,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 821 |
.venv/lib/python3.14/site-packages/ultralytics/nn/__pycache__/tasks.cpython-314.pyc filter=lfs diff=lfs merge=lfs -text
|
| 822 |
.venv/lib/python3.14/site-packages/ultralytics/nn/modules/__pycache__/block.cpython-314.pyc filter=lfs diff=lfs merge=lfs -text
|
| 823 |
.venv/lib/python3.14/site-packages/ultralytics/nn/modules/__pycache__/head.cpython-314.pyc filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
| 821 |
.venv/lib/python3.14/site-packages/ultralytics/nn/__pycache__/tasks.cpython-314.pyc filter=lfs diff=lfs merge=lfs -text
|
| 822 |
.venv/lib/python3.14/site-packages/ultralytics/nn/modules/__pycache__/block.cpython-314.pyc filter=lfs diff=lfs merge=lfs -text
|
| 823 |
.venv/lib/python3.14/site-packages/ultralytics/nn/modules/__pycache__/head.cpython-314.pyc filter=lfs diff=lfs merge=lfs -text
|
| 824 |
+
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/metrics.cpython-314.pyc filter=lfs diff=lfs merge=lfs -text
|
| 825 |
+
.venv/lib/python3.14/site-packages/yaml/_yaml.cpython-314-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 826 |
+
.venv/share/jupyter/nbextensions/pydeck/index.js.map filter=lfs diff=lfs merge=lfs -text
|
.venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pip
|
.venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/METADATA
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.4
|
| 2 |
+
Name: ultralytics
|
| 3 |
+
Version: 8.4.83
|
| 4 |
+
Summary: Ultralytics YOLO 🚀 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation, classification, and oriented object detection.
|
| 5 |
+
Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>, Jing Qiu <jing.qiu@ultralytics.com>
|
| 6 |
+
Maintainer-email: Ultralytics <hello@ultralytics.com>
|
| 7 |
+
License: AGPL-3.0
|
| 8 |
+
Project-URL: Homepage, https://ultralytics.com
|
| 9 |
+
Project-URL: Source, https://github.com/ultralytics/ultralytics
|
| 10 |
+
Project-URL: Documentation, https://docs.ultralytics.com
|
| 11 |
+
Project-URL: Bug Reports, https://github.com/ultralytics/ultralytics/issues
|
| 12 |
+
Project-URL: Changelog, https://github.com/ultralytics/ultralytics/releases
|
| 13 |
+
Keywords: machine-learning,deep-learning,computer-vision,ML,DL,AI,RT-DETR,SAM3,YOLO,YOLOv3,YOLOv5,YOLOv8,YOLO11,YOLO26,Platform,Ultralytics
|
| 14 |
+
Classifier: Development Status :: 5 - Production/Stable
|
| 15 |
+
Classifier: Intended Audience :: Developers
|
| 16 |
+
Classifier: Intended Audience :: Education
|
| 17 |
+
Classifier: Intended Audience :: Science/Research
|
| 18 |
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
| 19 |
+
Classifier: Programming Language :: Python :: 3
|
| 20 |
+
Classifier: Programming Language :: Python :: 3.8
|
| 21 |
+
Classifier: Programming Language :: Python :: 3.9
|
| 22 |
+
Classifier: Programming Language :: Python :: 3.10
|
| 23 |
+
Classifier: Programming Language :: Python :: 3.11
|
| 24 |
+
Classifier: Programming Language :: Python :: 3.12
|
| 25 |
+
Classifier: Programming Language :: Python :: 3.13
|
| 26 |
+
Classifier: Topic :: Software Development
|
| 27 |
+
Classifier: Topic :: Scientific/Engineering
|
| 28 |
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
| 29 |
+
Classifier: Topic :: Scientific/Engineering :: Image Recognition
|
| 30 |
+
Classifier: Operating System :: POSIX :: Linux
|
| 31 |
+
Classifier: Operating System :: MacOS
|
| 32 |
+
Classifier: Operating System :: Microsoft :: Windows
|
| 33 |
+
Requires-Python: >=3.8
|
| 34 |
+
Description-Content-Type: text/markdown
|
| 35 |
+
License-File: LICENSE
|
| 36 |
+
Requires-Dist: numpy>=1.23.0
|
| 37 |
+
Requires-Dist: matplotlib>=3.3.0
|
| 38 |
+
Requires-Dist: opencv-python>=4.6.0
|
| 39 |
+
Requires-Dist: pillow>=7.1.2
|
| 40 |
+
Requires-Dist: pyyaml>=5.3.1
|
| 41 |
+
Requires-Dist: requests>=2.23.0
|
| 42 |
+
Requires-Dist: torch>=1.8.0
|
| 43 |
+
Requires-Dist: torch!=2.4.0,>=1.8.0; sys_platform == "win32"
|
| 44 |
+
Requires-Dist: torchvision>=0.9.0
|
| 45 |
+
Requires-Dist: psutil>=5.8.0
|
| 46 |
+
Requires-Dist: polars>=0.20.0
|
| 47 |
+
Requires-Dist: nvidia-ml-py>=12.0.0
|
| 48 |
+
Requires-Dist: ultralytics-thop>=2.0.18
|
| 49 |
+
Provides-Extra: dev
|
| 50 |
+
Requires-Dist: ipython; extra == "dev"
|
| 51 |
+
Requires-Dist: pytest; extra == "dev"
|
| 52 |
+
Requires-Dist: pytest-cov; extra == "dev"
|
| 53 |
+
Requires-Dist: pytest-xdist>=3.0.0; extra == "dev"
|
| 54 |
+
Requires-Dist: coverage[toml]; extra == "dev"
|
| 55 |
+
Requires-Dist: zensical>=0.0.15; python_version >= "3.10" and extra == "dev"
|
| 56 |
+
Requires-Dist: mkdocs-ultralytics-plugin>=0.2.4; extra == "dev"
|
| 57 |
+
Requires-Dist: minijinja>=2.0.0; extra == "dev"
|
| 58 |
+
Provides-Extra: export-base
|
| 59 |
+
Requires-Dist: onnx>=1.12.0; platform_system != "Darwin" and extra == "export-base"
|
| 60 |
+
Requires-Dist: onnx<1.18.0,>=1.12.0; (platform_system == "Darwin" and python_version < "3.13") and extra == "export-base"
|
| 61 |
+
Requires-Dist: onnx>=1.20.0; (platform_system == "Darwin" and python_version >= "3.13") and extra == "export-base"
|
| 62 |
+
Requires-Dist: onnxslim>=0.1.82; extra == "export-base"
|
| 63 |
+
Requires-Dist: onnxruntime<1.20.0; (python_version < "3.11" and (platform_machine != "aarch64" or platform_system != "Linux")) and extra == "export-base"
|
| 64 |
+
Requires-Dist: onnxruntime>=1.20.0; python_version >= "3.11" and extra == "export-base"
|
| 65 |
+
Requires-Dist: nncf<3.0.0,>=2.14.0; python_version >= "3.9" and extra == "export-base"
|
| 66 |
+
Requires-Dist: openvino>=2024.0.0; extra == "export-base"
|
| 67 |
+
Requires-Dist: packaging>=26.0; (platform_machine == "aarch64" and platform_system == "Linux" and python_version >= "3.9") and extra == "export-base"
|
| 68 |
+
Provides-Extra: export-legacy-torch
|
| 69 |
+
Requires-Dist: numpy<2; extra == "export-legacy-torch"
|
| 70 |
+
Requires-Dist: setuptools<81.0.0; python_version >= "3.9" and extra == "export-legacy-torch"
|
| 71 |
+
Provides-Extra: export-tensorflow
|
| 72 |
+
Requires-Dist: numpy<2.0.0; python_version < "3.13" and extra == "export-tensorflow"
|
| 73 |
+
Requires-Dist: tensorflow<=2.19.0,>=2.0.0; python_version < "3.13" and extra == "export-tensorflow"
|
| 74 |
+
Requires-Dist: tensorflow>2.19.0; python_version >= "3.13" and extra == "export-tensorflow"
|
| 75 |
+
Requires-Dist: ydf<0.13.0; (platform_machine != "aarch64" and python_version <= "3.12") and extra == "export-tensorflow"
|
| 76 |
+
Requires-Dist: googleapis-common-protos<1.74.0; python_version <= "3.12" and extra == "export-tensorflow"
|
| 77 |
+
Requires-Dist: tensorstore>=0.1.63; (platform_machine == "aarch64" and python_version >= "3.9") and extra == "export-tensorflow"
|
| 78 |
+
Requires-Dist: h5py!=3.11.0; platform_machine == "aarch64" and extra == "export-tensorflow"
|
| 79 |
+
Provides-Extra: export-coreml
|
| 80 |
+
Requires-Dist: numpy<=2.3.5; python_version >= "3.13" and extra == "export-coreml"
|
| 81 |
+
Requires-Dist: coremltools>=9.0; (platform_system != "Windows" and python_version <= "3.13") and extra == "export-coreml"
|
| 82 |
+
Requires-Dist: scikit-learn>=1.3.2; (platform_system != "Windows" and python_version <= "3.13") and extra == "export-coreml"
|
| 83 |
+
Provides-Extra: export-executorch
|
| 84 |
+
Requires-Dist: executorch; extra == "export-executorch"
|
| 85 |
+
Requires-Dist: numpy<=2.3.5; extra == "export-executorch"
|
| 86 |
+
Provides-Extra: export-deepx
|
| 87 |
+
Requires-Dist: dx_com; extra == "export-deepx"
|
| 88 |
+
Requires-Dist: numpy<2; extra == "export-deepx"
|
| 89 |
+
Provides-Extra: export-litert
|
| 90 |
+
Requires-Dist: litert-torch>=0.9.0; ((platform_system == "Linux" and platform_machine == "x86_64") or platform_system == "Darwin") and extra == "export-litert"
|
| 91 |
+
Requires-Dist: ai-edge-litert>=2.1.4; ((platform_system == "Linux" and platform_machine == "x86_64") or platform_system == "Darwin") and extra == "export-litert"
|
| 92 |
+
Requires-Dist: ai-edge-quantizer>=0.6.0; ((platform_system == "Linux" and platform_machine == "x86_64") or platform_system == "Darwin") and extra == "export-litert"
|
| 93 |
+
Provides-Extra: export
|
| 94 |
+
Requires-Dist: ultralytics[export-base]; extra == "export"
|
| 95 |
+
Requires-Dist: ultralytics[export-tensorflow]; extra == "export"
|
| 96 |
+
Requires-Dist: ultralytics[export-coreml]; extra == "export"
|
| 97 |
+
Requires-Dist: ultralytics[export-litert]; extra == "export"
|
| 98 |
+
Provides-Extra: solutions
|
| 99 |
+
Requires-Dist: shapely>=2.0.0; extra == "solutions"
|
| 100 |
+
Requires-Dist: lap>=0.5.12; extra == "solutions"
|
| 101 |
+
Requires-Dist: streamlit>=1.51.0; python_version >= "3.10" and extra == "solutions"
|
| 102 |
+
Requires-Dist: streamlit<1.51.0,>=1.29.0; (python_version < "3.10" and (platform_machine != "aarch64" or platform_system != "Linux")) and extra == "solutions"
|
| 103 |
+
Requires-Dist: flask>=3.0.1; extra == "solutions"
|
| 104 |
+
Provides-Extra: logging
|
| 105 |
+
Requires-Dist: wandb; extra == "logging"
|
| 106 |
+
Requires-Dist: tensorboard; extra == "logging"
|
| 107 |
+
Requires-Dist: mlflow; extra == "logging"
|
| 108 |
+
Provides-Extra: extra
|
| 109 |
+
Requires-Dist: ipython; extra == "extra"
|
| 110 |
+
Requires-Dist: albumentations>=1.4.6; extra == "extra"
|
| 111 |
+
Requires-Dist: faster-coco-eval>=1.6.7; extra == "extra"
|
| 112 |
+
Provides-Extra: typing
|
| 113 |
+
Requires-Dist: types-pillow; extra == "typing"
|
| 114 |
+
Requires-Dist: types-psutil; extra == "typing"
|
| 115 |
+
Requires-Dist: types-pyyaml; extra == "typing"
|
| 116 |
+
Requires-Dist: types-requests; extra == "typing"
|
| 117 |
+
Requires-Dist: types-shapely; extra == "typing"
|
| 118 |
+
Dynamic: license-file
|
| 119 |
+
|
| 120 |
+
<div align="center">
|
| 121 |
+
<p>
|
| 122 |
+
<a href="https://platform.ultralytics.com/?utm_source=github&utm_medium=referral&utm_campaign=platform_launch&utm_content=banner&utm_term=ultralytics_github" target="_blank">
|
| 123 |
+
<img width="100%" src="https://raw.githubusercontent.com/ultralytics/assets/main/yolov8/banner-yolov8.png" alt="Ultralytics YOLO banner"></a>
|
| 124 |
+
</p>
|
| 125 |
+
|
| 126 |
+
[中文](https://docs.ultralytics.com/zh) | [한국어](https://docs.ultralytics.com/ko) | [日本語](https://docs.ultralytics.com/ja) | [Русский](https://docs.ultralytics.com/ru) | [Deutsch](https://docs.ultralytics.com/de) | [Français](https://docs.ultralytics.com/fr) | [Español](https://docs.ultralytics.com/es) | [Português](https://docs.ultralytics.com/pt) | [Türkçe](https://docs.ultralytics.com/tr) | [Tiếng Việt](https://docs.ultralytics.com/vi) | [العربية](https://docs.ultralytics.com/ar) <br>
|
| 127 |
+
|
| 128 |
+
<div>
|
| 129 |
+
<a href="https://github.com/ultralytics/ultralytics/actions/workflows/ci.yml"><img src="https://github.com/ultralytics/ultralytics/actions/workflows/ci.yml/badge.svg" alt="Ultralytics CI"></a>
|
| 130 |
+
<a href="https://clickpy.clickhouse.com/dashboard/ultralytics"><img src="https://static.pepy.tech/badge/ultralytics" alt="Ultralytics Downloads"></a>
|
| 131 |
+
<a href="https://discord.com/invite/ultralytics"><img alt="Ultralytics Discord" src="https://img.shields.io/discord/1089800235347353640?logo=discord&logoColor=white&label=Discord&color=blue"></a>
|
| 132 |
+
<a href="https://community.ultralytics.com/"><img alt="Ultralytics Forums" src="https://img.shields.io/discourse/users?server=https%3A%2F%2Fcommunity.ultralytics.com&logo=discourse&label=Forums&color=blue"></a>
|
| 133 |
+
<a href="https://www.reddit.com/r/ultralytics/"><img alt="Ultralytics Reddit" src="https://img.shields.io/reddit/subreddit-subscribers/ultralytics?style=flat&logo=reddit&logoColor=white&label=Reddit&color=blue"></a>
|
| 134 |
+
<br>
|
| 135 |
+
<a href="https://console.paperspace.com/github/ultralytics/ultralytics"><img src="https://assets.paperspace.io/img/gradient-badge.svg" alt="Run Ultralytics on Gradient"></a>
|
| 136 |
+
<a href="https://colab.research.google.com/github/ultralytics/ultralytics/blob/main/examples/tutorial.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open Ultralytics In Colab"></a>
|
| 137 |
+
<a href="https://www.kaggle.com/models/ultralytics/yolo26"><img src="https://kaggle.com/static/images/open-in-kaggle.svg" alt="Open Ultralytics In Kaggle"></a>
|
| 138 |
+
<a href="https://mybinder.org/v2/gh/ultralytics/ultralytics/HEAD?labpath=examples%2Ftutorial.ipynb"><img src="https://mybinder.org/badge_logo.svg" alt="Open Ultralytics In Binder"></a>
|
| 139 |
+
</div>
|
| 140 |
+
</div>
|
| 141 |
+
<br>
|
| 142 |
+
|
| 143 |
+
<div align="center">
|
| 144 |
+
<a href="https://trendshift.io/repositories/1556?utm_source=repository-badge&utm_medium=badge&utm_campaign=badge-repository-1556" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/1556" alt="ultralytics%2Fultralytics | Trendshift" width="250" height="55"/></a>
|
| 145 |
+
</div>
|
| 146 |
+
<br>
|
| 147 |
+
|
| 148 |
+
[Ultralytics](https://www.ultralytics.com/) creates cutting-edge, state-of-the-art (SOTA) [YOLO models](https://www.ultralytics.com/yolo) built on years of foundational research in computer vision and AI. Constantly updated for performance and flexibility, our models are **fast**, **accurate**, and **easy to use**. They excel at [object detection](https://docs.ultralytics.com/tasks/detect), [tracking](https://docs.ultralytics.com/modes/track), [instance segmentation](https://docs.ultralytics.com/tasks/segment), [semantic segmentation](https://docs.ultralytics.com/tasks/semantic), [image classification](https://docs.ultralytics.com/tasks/classify), and [pose estimation](https://docs.ultralytics.com/tasks/pose) tasks.
|
| 149 |
+
|
| 150 |
+
Find detailed documentation in the [Ultralytics Docs](https://docs.ultralytics.com/). Get support via [GitHub Issues](https://github.com/ultralytics/ultralytics/issues/new/choose). Join discussions on [Discord](https://discord.com/invite/ultralytics), [Reddit](https://www.reddit.com/r/ultralytics/), and the [Ultralytics Community Forums](https://community.ultralytics.com/)!
|
| 151 |
+
|
| 152 |
+
Request an Enterprise License for commercial use at [Ultralytics Licensing](https://www.ultralytics.com/license).
|
| 153 |
+
|
| 154 |
+
<a href="https://platform.ultralytics.com/ultralytics/yolo26" target="_blank">
|
| 155 |
+
<img width="100%" src="https://raw.githubusercontent.com/ultralytics/assets/refs/heads/main/yolo/performance-comparison.png" alt="YOLO26 performance plots">
|
| 156 |
+
</a>
|
| 157 |
+
|
| 158 |
+
<div align="center">
|
| 159 |
+
<a href="https://github.com/ultralytics"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-github.png" width="2%" alt="Ultralytics GitHub"></a>
|
| 160 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="2%" alt="space">
|
| 161 |
+
<a href="https://www.linkedin.com/company/ultralytics/"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-linkedin.png" width="2%" alt="Ultralytics LinkedIn"></a>
|
| 162 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="2%" alt="space">
|
| 163 |
+
<a href="https://twitter.com/ultralytics"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-twitter.png" width="2%" alt="Ultralytics Twitter"></a>
|
| 164 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="2%" alt="space">
|
| 165 |
+
<a href="https://www.youtube.com/ultralytics?sub_confirmation=1"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-youtube.png" width="2%" alt="Ultralytics YouTube"></a>
|
| 166 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="2%" alt="space">
|
| 167 |
+
<a href="https://www.tiktok.com/@ultralytics"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-tiktok.png" width="2%" alt="Ultralytics TikTok"></a>
|
| 168 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="2%" alt="space">
|
| 169 |
+
<a href="https://ultralytics.com/bilibili"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-bilibili.png" width="2%" alt="Ultralytics BiliBili"></a>
|
| 170 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="2%" alt="space">
|
| 171 |
+
<a href="https://discord.com/invite/ultralytics"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-discord.png" width="2%" alt="Ultralytics Discord"></a>
|
| 172 |
+
</div>
|
| 173 |
+
|
| 174 |
+
## 📄 Documentation
|
| 175 |
+
|
| 176 |
+
See below for quickstart installation and usage examples. For comprehensive guidance on training, validation, prediction, and deployment, refer to our full [Ultralytics Docs](https://docs.ultralytics.com/).
|
| 177 |
+
|
| 178 |
+
<details open>
|
| 179 |
+
<summary>Install</summary>
|
| 180 |
+
|
| 181 |
+
Install the `ultralytics` package, including all [requirements](https://github.com/ultralytics/ultralytics/blob/main/pyproject.toml), in a [**Python>=3.8**](https://www.python.org/) environment with [**PyTorch>=1.8**](https://pytorch.org/get-started/locally/).
|
| 182 |
+
|
| 183 |
+
[](https://pypi.org/project/ultralytics/) [](https://clickpy.clickhouse.com/dashboard/ultralytics) [](https://pypi.org/project/ultralytics/)
|
| 184 |
+
|
| 185 |
+
```bash
|
| 186 |
+
pip install ultralytics
|
| 187 |
+
```
|
| 188 |
+
|
| 189 |
+
For alternative installation methods, including [Conda](https://anaconda.org/conda-forge/ultralytics), [Docker](https://hub.docker.com/r/ultralytics/ultralytics), and building from source via Git, please consult the [Quickstart Guide](https://docs.ultralytics.com/quickstart).
|
| 190 |
+
|
| 191 |
+
[](https://anaconda.org/conda-forge/ultralytics) [](https://hub.docker.com/r/ultralytics/ultralytics) [](https://hub.docker.com/r/ultralytics/ultralytics)
|
| 192 |
+
|
| 193 |
+
</details>
|
| 194 |
+
|
| 195 |
+
<details open>
|
| 196 |
+
<summary>Usage</summary>
|
| 197 |
+
|
| 198 |
+
### CLI
|
| 199 |
+
|
| 200 |
+
You can use Ultralytics YOLO directly from the Command Line Interface (CLI) with the `yolo` command:
|
| 201 |
+
|
| 202 |
+
```bash
|
| 203 |
+
# Predict using a pretrained YOLO model (e.g., YOLO26n) on an image
|
| 204 |
+
yolo predict model=yolo26n.pt source='https://ultralytics.com/images/bus.jpg'
|
| 205 |
+
```
|
| 206 |
+
|
| 207 |
+
The `yolo` command supports various tasks and modes, accepting additional arguments like `imgsz=640`. Explore the YOLO [CLI Docs](https://docs.ultralytics.com/usage/cli) for more examples.
|
| 208 |
+
|
| 209 |
+
### Python
|
| 210 |
+
|
| 211 |
+
Ultralytics YOLO can also be integrated directly into your Python projects. It accepts the same [configuration arguments](https://docs.ultralytics.com/usage/cfg) as the CLI:
|
| 212 |
+
|
| 213 |
+
```python
|
| 214 |
+
from ultralytics import YOLO
|
| 215 |
+
|
| 216 |
+
# Load a pretrained YOLO26n model
|
| 217 |
+
model = YOLO("yolo26n.pt")
|
| 218 |
+
|
| 219 |
+
# Train the model on the COCO8 dataset for 100 epochs
|
| 220 |
+
train_results = model.train(
|
| 221 |
+
data="coco8.yaml", # Path to dataset configuration file
|
| 222 |
+
epochs=100, # Number of training epochs
|
| 223 |
+
imgsz=640, # Image size for training
|
| 224 |
+
device="cpu", # Device to run on (e.g., 'cpu', 0, [0,1,2,3])
|
| 225 |
+
)
|
| 226 |
+
|
| 227 |
+
# Evaluate the model's performance on the validation set
|
| 228 |
+
metrics = model.val()
|
| 229 |
+
|
| 230 |
+
# Perform object detection on an image
|
| 231 |
+
results = model("path/to/image.jpg") # Predict on an image
|
| 232 |
+
results[0].show() # Display results
|
| 233 |
+
|
| 234 |
+
# Export the model to ONNX format for deployment
|
| 235 |
+
path = model.export(format="onnx") # Returns the path to the exported model
|
| 236 |
+
```
|
| 237 |
+
|
| 238 |
+
Discover more examples in the YOLO [Python Docs](https://docs.ultralytics.com/usage/python).
|
| 239 |
+
|
| 240 |
+
</details>
|
| 241 |
+
|
| 242 |
+
## ✨ Models
|
| 243 |
+
|
| 244 |
+
Ultralytics supports a wide range of YOLO models, from early versions like [YOLOv3](https://docs.ultralytics.com/models/yolov3) to the latest [YOLO26](https://docs.ultralytics.com/models/yolo26). The tables below showcase YOLO26 models pretrained on [COCO](https://docs.ultralytics.com/datasets/detect/coco) for [Detection](https://docs.ultralytics.com/tasks/detect), [Segmentation](https://docs.ultralytics.com/tasks/segment), and [Pose Estimation](https://docs.ultralytics.com/tasks/pose). [Semantic Segmentation](https://docs.ultralytics.com/tasks/semantic) models are pretrained on [Cityscapes](https://docs.ultralytics.com/datasets/semantic/cityscapes), and [Classification](https://docs.ultralytics.com/tasks/classify) models are pretrained on [ImageNet](https://docs.ultralytics.com/datasets/classify/imagenet). [Tracking](https://docs.ultralytics.com/modes/track) mode is compatible with Detection, Segmentation, and Pose models. All [Models](https://docs.ultralytics.com/models) download automatically from the latest Ultralytics [release](https://github.com/ultralytics/assets/releases) on first use.
|
| 245 |
+
|
| 246 |
+
<a href="https://docs.ultralytics.com/tasks" target="_blank">
|
| 247 |
+
<img width="100%" src="https://raw.githubusercontent.com/ultralytics/assets/main/docs/ultralytics-yolov8-tasks-banner.avif" alt="Ultralytics YOLO supported tasks">
|
| 248 |
+
</a>
|
| 249 |
+
<br>
|
| 250 |
+
<br>
|
| 251 |
+
|
| 252 |
+
<details open><summary>Detection (COCO)</summary>
|
| 253 |
+
|
| 254 |
+
Explore the [Detection Docs](https://docs.ultralytics.com/tasks/detect) for usage examples. These models are trained on the [COCO dataset](https://cocodataset.org/), featuring 80 object classes.
|
| 255 |
+
|
| 256 |
+
| Model | size<br><sup>(pixels)</sup> | mAP<sup>val<br>50-95</sup> | mAP<sup>val<br>50-95(e2e)</sup> | Speed<br><sup>CPU ONNX<br>(ms)</sup> | Speed<br><sup>T4 TensorRT10<br>(ms)</sup> | params<br><sup>(M)</sup> | FLOPs<br><sup>(B)</sup> |
|
| 257 |
+
| ------------------------------------------------------------------------------------ | --------------------------- | -------------------------- | ------------------------------- | ------------------------------------ | ----------------------------------------- | ------------------------ | ----------------------- |
|
| 258 |
+
| [YOLO26n](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26n.pt) | 640 | 40.9 | 40.1 | 38.9 ± 0.7 | 1.7 ± 0.0 | 2.4 | 5.4 |
|
| 259 |
+
| [YOLO26s](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26s.pt) | 640 | 48.6 | 47.8 | 87.2 ± 0.9 | 2.5 ± 0.0 | 9.5 | 20.7 |
|
| 260 |
+
| [YOLO26m](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26m.pt) | 640 | 53.1 | 52.5 | 220.0 ± 1.4 | 4.7 ± 0.1 | 20.4 | 68.2 |
|
| 261 |
+
| [YOLO26l](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26l.pt) | 640 | 55.0 | 54.4 | 286.2 ± 2.0 | 6.2 ± 0.2 | 24.8 | 86.4 |
|
| 262 |
+
| [YOLO26x](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26x.pt) | 640 | 57.5 | 56.9 | 525.8 ± 4.0 | 11.8 ± 0.2 | 55.7 | 193.9 |
|
| 263 |
+
|
| 264 |
+
- **mAP<sup>val</sup>** values refer to single-model single-scale performance on the [COCO val2017](https://cocodataset.org/) dataset. See [YOLO Performance Metrics](https://docs.ultralytics.com/guides/yolo-performance-metrics) for details. <br>Reproduce with `yolo val detect data=coco.yaml device=0`
|
| 265 |
+
- **Speed** metrics are averaged over COCO val images using an [Amazon EC2 P4d](https://aws.amazon.com/ec2/instance-types/p4/) instance. CPU speeds measured with [ONNX](https://onnx.ai/) export. GPU speeds measured with [TensorRT](https://developer.nvidia.com/tensorrt) export. <br>Reproduce with `yolo val detect data=coco.yaml batch=1 device=0|cpu`
|
| 266 |
+
|
| 267 |
+
</details>
|
| 268 |
+
|
| 269 |
+
<details><summary>Segmentation (COCO)</summary>
|
| 270 |
+
|
| 271 |
+
Refer to the [Segmentation Docs](https://docs.ultralytics.com/tasks/segment) for usage examples. These models are trained on [COCO-Seg](https://docs.ultralytics.com/datasets/segment/coco), including 80 classes.
|
| 272 |
+
|
| 273 |
+
| Model | size<br><sup>(pixels)</sup> | mAP<sup>box<br>50-95(e2e)</sup> | mAP<sup>mask<br>50-95(e2e)</sup> | Speed<br><sup>CPU ONNX<br>(ms)</sup> | Speed<br><sup>T4 TensorRT10<br>(ms)</sup> | params<br><sup>(M)</sup> | FLOPs<br><sup>(B)</sup> |
|
| 274 |
+
| -------------------------------------------------------------------------------------------- | --------------------------- | ------------------------------- | -------------------------------- | ------------------------------------ | ----------------------------------------- | ------------------------ | ----------------------- |
|
| 275 |
+
| [YOLO26n-seg](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26n-seg.pt) | 640 | 39.6 | 33.9 | 53.3 ± 0.5 | 2.1 ± 0.0 | 2.7 | 9.1 |
|
| 276 |
+
| [YOLO26s-seg](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26s-seg.pt) | 640 | 47.3 | 40.0 | 118.4 ± 0.9 | 3.3 ± 0.0 | 10.4 | 34.2 |
|
| 277 |
+
| [YOLO26m-seg](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26m-seg.pt) | 640 | 52.5 | 44.1 | 328.2 ± 2.4 | 6.7 ± 0.1 | 23.6 | 121.5 |
|
| 278 |
+
| [YOLO26l-seg](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26l-seg.pt) | 640 | 54.4 | 45.5 | 387.0 ± 3.7 | 8.0 ± 0.1 | 28.0 | 139.8 |
|
| 279 |
+
| [YOLO26x-seg](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26x-seg.pt) | 640 | 56.5 | 47.0 | 787.0 ± 6.8 | 16.4 ± 0.1 | 62.8 | 313.5 |
|
| 280 |
+
|
| 281 |
+
- **mAP<sup>val</sup>** values are for single-model single-scale on the [COCO val2017](https://cocodataset.org/) dataset. See [YOLO Performance Metrics](https://docs.ultralytics.com/guides/yolo-performance-metrics) for details. <br>Reproduce with `yolo val segment data=coco.yaml device=0`
|
| 282 |
+
- **Speed** metrics are averaged over COCO val images using an [Amazon EC2 P4d](https://aws.amazon.com/ec2/instance-types/p4/) instance. CPU speeds measured with [ONNX](https://onnx.ai/) export. GPU speeds measured with [TensorRT](https://developer.nvidia.com/tensorrt) export. <br>Reproduce with `yolo val segment data=coco.yaml batch=1 device=0|cpu`
|
| 283 |
+
|
| 284 |
+
</details>
|
| 285 |
+
|
| 286 |
+
<details><summary>Semantic Segmentation (Cityscapes)</summary>
|
| 287 |
+
|
| 288 |
+
See the [Semantic Segmentation Docs](https://docs.ultralytics.com/tasks/semantic) for usage examples. These models are trained on [Cityscapes](https://docs.ultralytics.com/datasets/semantic/cityscapes), including 19 classes.
|
| 289 |
+
|
| 290 |
+
| Model | size<br><sup>(pixels)</sup> | mIoU<sup>val</sup> | Speed<br><sup>RTX3090 PyTorch<br>(ms)</sup> | params<br><sup>(M)</sup> | FLOPs<br><sup>(B)</sup> |
|
| 291 |
+
| -------------------------------------------------------------------------------------------- | --------------------------- | ------------------ | ------------------------------------------- | ------------------------ | ----------------------- |
|
| 292 |
+
| [YOLO26n-sem](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26n-sem.pt) | 1024 × 2048 | 78.3 | 4.4 ± 0.0 | 1.6 | 22.7 |
|
| 293 |
+
| [YOLO26s-sem](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26s-sem.pt) | 1024 × 2048 | 80.8 | 8.4 ± 0.0 | 6.5 | 88.8 |
|
| 294 |
+
| [YOLO26m-sem](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26m-sem.pt) | 1024 × 2048 | 82.0 | 19.9 ± 0.1 | 14.3 | 304.5 |
|
| 295 |
+
| [YOLO26l-sem](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26l-sem.pt) | 1024 × 2048 | 82.9 | 26.5 ± 0.1 | 17.9 | 384.7 |
|
| 296 |
+
| [YOLO26x-sem](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26x-sem.pt) | 1024 × 2048 | 83.6 | 48.9 ± 0.2 | 40.2 | 861.7 |
|
| 297 |
+
|
| 298 |
+
- **mIoU<sup>val</sup>** values are for single-model single-scale on the [Cityscapes](https://www.cityscapes-dataset.com/) validation set. <br>Reproduce with `yolo semantic val data=cityscapes.yaml device=0 imgsz=2048`
|
| 299 |
+
- **Speed** metrics are averaged over Cityscapes validation images using an RTX3090 instance. <br>Reproduce with `yolo semantic val data=cityscapes.yaml batch=1 device=0|cpu imgsz=2048`
|
| 300 |
+
|
| 301 |
+
</details>
|
| 302 |
+
|
| 303 |
+
<details><summary>Classification (ImageNet)</summary>
|
| 304 |
+
|
| 305 |
+
Consult the [Classification Docs](https://docs.ultralytics.com/tasks/classify) for usage examples. These models are trained on [ImageNet](https://docs.ultralytics.com/datasets/classify/imagenet), covering 1000 classes.
|
| 306 |
+
|
| 307 |
+
| Model | size<br><sup>(pixels)</sup> | acc<br><sup>top1</sup> | acc<br><sup>top5</sup> | Speed<br><sup>CPU ONNX<br>(ms)</sup> | Speed<br><sup>T4 TensorRT10<br>(ms)</sup> | params<br><sup>(M)</sup> | FLOPs<br><sup>(B) at 224</sup> |
|
| 308 |
+
| -------------------------------------------------------------------------------------------- | --------------------------- | ---------------------- | ---------------------- | ------------------------------------ | ----------------------------------------- | ------------------------ | ------------------------------ |
|
| 309 |
+
| [YOLO26n-cls](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26n-cls.pt) | 224 | 71.4 | 90.1 | 5.0 ± 0.3 | 1.1 ± 0.0 | 2.8 | 0.5 |
|
| 310 |
+
| [YOLO26s-cls](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26s-cls.pt) | 224 | 76.0 | 92.9 | 7.9 ± 0.2 | 1.3 ± 0.0 | 6.7 | 1.6 |
|
| 311 |
+
| [YOLO26m-cls](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26m-cls.pt) | 224 | 78.1 | 94.2 | 17.2 ± 0.4 | 2.0 ± 0.0 | 11.6 | 4.9 |
|
| 312 |
+
| [YOLO26l-cls](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26l-cls.pt) | 224 | 79.0 | 94.6 | 23.2 ± 0.3 | 2.8 ± 0.0 | 14.1 | 6.2 |
|
| 313 |
+
| [YOLO26x-cls](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26x-cls.pt) | 224 | 79.9 | 95.0 | 41.4 ± 0.9 | 3.8 ± 0.0 | 29.6 | 13.6 |
|
| 314 |
+
|
| 315 |
+
- **acc** values represent model accuracy on the [ImageNet](https://www.image-net.org/) dataset validation set. <br>Reproduce with `yolo val classify data=path/to/ImageNet device=0`
|
| 316 |
+
- **Speed** metrics are averaged over ImageNet val images using an [Amazon EC2 P4d](https://aws.amazon.com/ec2/instance-types/p4/) instance. CPU speeds measured with [ONNX](https://onnx.ai/) export. GPU speeds measured with [TensorRT](https://developer.nvidia.com/tensorrt) export. <br>Reproduce with `yolo val classify data=path/to/ImageNet batch=1 device=0|cpu`
|
| 317 |
+
|
| 318 |
+
</details>
|
| 319 |
+
|
| 320 |
+
<details><summary>Pose (COCO)</summary>
|
| 321 |
+
|
| 322 |
+
See the [Pose Estimation Docs](https://docs.ultralytics.com/tasks/pose) for usage examples. These models are trained on [COCO-Pose](https://docs.ultralytics.com/datasets/pose/coco), focusing on the 'person' class.
|
| 323 |
+
|
| 324 |
+
| Model | size<br><sup>(pixels)</sup> | mAP<sup>pose<br>50-95(e2e)</sup> | mAP<sup>pose<br>50(e2e)</sup> | Speed<br><sup>CPU ONNX<br>(ms)</sup> | Speed<br><sup>T4 TensorRT10<br>(ms)</sup> | params<br><sup>(M)</sup> | FLOPs<br><sup>(B)</sup> |
|
| 325 |
+
| ---------------------------------------------------------------------------------------------- | --------------------------- | -------------------------------- | ----------------------------- | ------------------------------------ | ----------------------------------------- | ------------------------ | ----------------------- |
|
| 326 |
+
| [YOLO26n-pose](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26n-pose.pt) | 640 | 57.2 | 83.3 | 40.3 ± 0.5 | 1.8 ± 0.0 | 2.9 | 7.5 |
|
| 327 |
+
| [YOLO26s-pose](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26s-pose.pt) | 640 | 63.0 | 86.6 | 85.3 ± 0.9 | 2.7 ± 0.0 | 10.4 | 23.9 |
|
| 328 |
+
| [YOLO26m-pose](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26m-pose.pt) | 640 | 68.8 | 89.6 | 218.0 ± 1.5 | 5.0 ± 0.1 | 21.5 | 73.1 |
|
| 329 |
+
| [YOLO26l-pose](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26l-pose.pt) | 640 | 70.4 | 90.5 | 275.4 ± 2.4 | 6.5 ± 0.1 | 25.9 | 91.3 |
|
| 330 |
+
| [YOLO26x-pose](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26x-pose.pt) | 640 | 71.6 | 91.6 | 565.4 ± 3.0 | 12.2 ± 0.2 | 57.6 | 201.7 |
|
| 331 |
+
|
| 332 |
+
- **mAP<sup>val</sup>** values are for single-model single-scale on the [COCO Keypoints val2017](https://docs.ultralytics.com/datasets/pose/coco) dataset. See [YOLO Performance Metrics](https://docs.ultralytics.com/guides/yolo-performance-metrics) for details. <br>Reproduce with `yolo val pose data=coco-pose.yaml device=0`
|
| 333 |
+
- **Speed** metrics are averaged over COCO val images using an [Amazon EC2 P4d](https://aws.amazon.com/ec2/instance-types/p4/) instance. CPU speeds measured with [ONNX](https://onnx.ai/) export. GPU speeds measured with [TensorRT](https://developer.nvidia.com/tensorrt) export. <br>Reproduce with `yolo val pose data=coco-pose.yaml batch=1 device=0|cpu`
|
| 334 |
+
|
| 335 |
+
</details>
|
| 336 |
+
|
| 337 |
+
<details><summary>Oriented Bounding Boxes (DOTAv1)</summary>
|
| 338 |
+
|
| 339 |
+
Check the [OBB Docs](https://docs.ultralytics.com/tasks/obb) for usage examples. These models are trained on [DOTAv1](https://docs.ultralytics.com/datasets/obb/dota-v2#dota-v10), including 15 classes.
|
| 340 |
+
|
| 341 |
+
| Model | size<br><sup>(pixels)</sup> | mAP<sup>test<br>50-95(e2e)</sup> | mAP<sup>test<br>50(e2e)</sup> | Speed<br><sup>CPU ONNX<br>(ms)</sup> | Speed<br><sup>T4 TensorRT10<br>(ms)</sup> | params<br><sup>(M)</sup> | FLOPs<br><sup>(B)</sup> |
|
| 342 |
+
| -------------------------------------------------------------------------------------------- | --------------------------- | -------------------------------- | ----------------------------- | ------------------------------------ | ----------------------------------------- | ------------------------ | ----------------------- |
|
| 343 |
+
| [YOLO26n-obb](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26n-obb.pt) | 1024 | 52.4 | 78.9 | 97.7 ± 0.9 | 2.8 ± 0.0 | 2.5 | 14.0 |
|
| 344 |
+
| [YOLO26s-obb](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26s-obb.pt) | 1024 | 54.8 | 80.9 | 218.0 ± 1.4 | 4.9 ± 0.1 | 9.8 | 55.1 |
|
| 345 |
+
| [YOLO26m-obb](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26m-obb.pt) | 1024 | 55.3 | 81.0 | 579.2 ± 3.8 | 10.2 ± 0.3 | 21.2 | 183.3 |
|
| 346 |
+
| [YOLO26l-obb](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26l-obb.pt) | 1024 | 56.2 | 81.6 | 735.6 ± 3.1 | 13.0 ± 0.2 | 25.6 | 230.0 |
|
| 347 |
+
| [YOLO26x-obb](https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo26x-obb.pt) | 1024 | 56.7 | 81.7 | 1485.7 ± 11.5 | 30.5 ± 0.9 | 57.6 | 516.5 |
|
| 348 |
+
|
| 349 |
+
- **mAP<sup>test</sup>** values are for single-model multiscale performance on the [DOTAv1 test set](https://captain-whu.github.io/DOTA/dataset.html). <br>Reproduce by `yolo val obb data=DOTAv1.yaml device=0 split=test` and submit merged results to the [DOTA evaluation server](https://captain-whu.github.io/DOTA/evaluation.html).
|
| 350 |
+
- **Speed** metrics are averaged over [DOTAv1 val images](https://docs.ultralytics.com/datasets/obb/dota-v2#dota-v10) using an [Amazon EC2 P4d](https://aws.amazon.com/ec2/instance-types/p4/) instance. CPU speeds measured with [ONNX](https://onnx.ai/) export. GPU speeds measured with [TensorRT](https://developer.nvidia.com/tensorrt) export. <br>Reproduce by `yolo val obb data=DOTAv1.yaml batch=1 device=0|cpu`
|
| 351 |
+
|
| 352 |
+
</details>
|
| 353 |
+
|
| 354 |
+
## 🧩 Integrations
|
| 355 |
+
|
| 356 |
+
Our key integrations with leading AI platforms extend the functionality of Ultralytics' offerings, enhancing tasks like dataset labeling, training, visualization, and model management. Discover how Ultralytics, in collaboration with partners like [Weights & Biases](https://docs.ultralytics.com/integrations/weights-biases), [Comet ML](https://docs.ultralytics.com/integrations/comet), [Roboflow](https://docs.ultralytics.com/integrations/roboflow), and [Intel OpenVINO](https://docs.ultralytics.com/integrations/openvino), can optimize your AI workflow. Explore more at [Ultralytics Integrations](https://docs.ultralytics.com/integrations).
|
| 357 |
+
|
| 358 |
+
<a href="https://platform.ultralytics.com" target="_blank">
|
| 359 |
+
<img width="100%" src="https://github.com/ultralytics/assets/raw/main/yolov8/banner-integrations.png" alt="Ultralytics active learning integrations">
|
| 360 |
+
</a>
|
| 361 |
+
|
| 362 |
+
## 🤝 Contribute
|
| 363 |
+
|
| 364 |
+
We thrive on community collaboration! Ultralytics YOLO wouldn't be the SOTA framework it is without contributions from developers like you. Please see our [Contributing Guide](https://docs.ultralytics.com/help/contributing) to get started. We also welcome your feedback—share your experience by completing our [Survey](https://www.ultralytics.com/survey?utm_source=github&utm_medium=social&utm_campaign=Survey). A huge **Thank You** 🙏 to everyone who contributes!
|
| 365 |
+
|
| 366 |
+
<!-- SVG image from https://opencollective.com/ultralytics/contributors.svg?width=1280 -->
|
| 367 |
+
|
| 368 |
+
[](https://github.com/ultralytics/ultralytics/graphs/contributors)
|
| 369 |
+
|
| 370 |
+
We look forward to your contributions to help make the Ultralytics ecosystem even better!
|
| 371 |
+
|
| 372 |
+
## 📜 License
|
| 373 |
+
|
| 374 |
+
Ultralytics offers two licensing options to suit different needs:
|
| 375 |
+
|
| 376 |
+
- **AGPL-3.0 License**: This [OSI-approved](https://opensource.org/license/agpl-3.0) open-source license is perfect for students, researchers, and enthusiasts. It encourages open collaboration and knowledge sharing. See the [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) file for full details.
|
| 377 |
+
- **Ultralytics Enterprise License**: For development and production use, this license enables seamless integration of Ultralytics software and AI models into business products and services, including internal tools, automated workflows, and production deployments, bypassing the open-source requirements of AGPL-3.0. To get started, please contact us via [Ultralytics Licensing](https://www.ultralytics.com/license).
|
| 378 |
+
|
| 379 |
+
## 📞 Contact
|
| 380 |
+
|
| 381 |
+
For bug reports and feature requests related to Ultralytics software, please visit [GitHub Issues](https://github.com/ultralytics/ultralytics/issues). For questions, discussions, and community support, join our active communities on [Discord](https://discord.com/invite/ultralytics), [Reddit](https://www.reddit.com/r/ultralytics/), and the [Ultralytics Community Forums](https://community.ultralytics.com/). We're here to help with all things Ultralytics!
|
| 382 |
+
|
| 383 |
+
<br>
|
| 384 |
+
<div align="center">
|
| 385 |
+
<a href="https://github.com/ultralytics"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-github.png" width="3%" alt="Ultralytics GitHub"></a>
|
| 386 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="3%" alt="space">
|
| 387 |
+
<a href="https://www.linkedin.com/company/ultralytics/"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-linkedin.png" width="3%" alt="Ultralytics LinkedIn"></a>
|
| 388 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="3%" alt="space">
|
| 389 |
+
<a href="https://twitter.com/ultralytics"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-twitter.png" width="3%" alt="Ultralytics Twitter"></a>
|
| 390 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="3%" alt="space">
|
| 391 |
+
<a href="https://www.youtube.com/ultralytics?sub_confirmation=1"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-youtube.png" width="3%" alt="Ultralytics YouTube"></a>
|
| 392 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="3%" alt="space">
|
| 393 |
+
<a href="https://www.tiktok.com/@ultralytics"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-tiktok.png" width="3%" alt="Ultralytics TikTok"></a>
|
| 394 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="3%" alt="space">
|
| 395 |
+
<a href="https://ultralytics.com/bilibili"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-bilibili.png" width="3%" alt="Ultralytics BiliBili"></a>
|
| 396 |
+
<img src="https://github.com/ultralytics/assets/raw/main/social/logo-transparent.png" width="3%" alt="space">
|
| 397 |
+
<a href="https://discord.com/invite/ultralytics"><img src="https://github.com/ultralytics/assets/raw/main/social/logo-social-discord.png" width="3%" alt="Ultralytics Discord"></a>
|
| 398 |
+
</div>
|
.venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/RECORD
ADDED
|
@@ -0,0 +1,604 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
../../../bin/ultralytics,sha256=lvXJu3IMtOnv6tRwpHYHFJ0EXUyLBlj3sqdCStE-Q64,225
|
| 2 |
+
../../../bin/yolo,sha256=lvXJu3IMtOnv6tRwpHYHFJ0EXUyLBlj3sqdCStE-Q64,225
|
| 3 |
+
tests/__init__.py,sha256=aBOT1alCmdyNRPWC4VLK7yvNozZFYLB7BhLhEIkN2Vc,1382
|
| 4 |
+
tests/__pycache__/__init__.cpython-314.pyc,,
|
| 5 |
+
tests/__pycache__/cache_test_assets.cpython-314.pyc,,
|
| 6 |
+
tests/__pycache__/conftest.cpython-314.pyc,,
|
| 7 |
+
tests/__pycache__/test_cli.cpython-314.pyc,,
|
| 8 |
+
tests/__pycache__/test_cuda.cpython-314.pyc,,
|
| 9 |
+
tests/__pycache__/test_engine.cpython-314.pyc,,
|
| 10 |
+
tests/__pycache__/test_exports.cpython-314.pyc,,
|
| 11 |
+
tests/__pycache__/test_integrations.cpython-314.pyc,,
|
| 12 |
+
tests/__pycache__/test_python.cpython-314.pyc,,
|
| 13 |
+
tests/__pycache__/test_solutions.cpython-314.pyc,,
|
| 14 |
+
tests/cache_test_assets.py,sha256=v0EU7gS3AXoCwUmlCszJUlEwZ6FNF20RVnCgtowwySc,3937
|
| 15 |
+
tests/conftest.py,sha256=1jSGGXfYmE4zVBkB1w2vjaQepPf2AWUA0qcm93jtvVA,5263
|
| 16 |
+
tests/test_cli.py,sha256=_KVuji9NvnJlNDPLmkBo7PgJBYMyDyt3ax6YovRqZ84,7196
|
| 17 |
+
tests/test_cuda.py,sha256=5YdMbv2iFup23CbwPMMinwu_FNDapq7bgPxlIiNoUDo,8844
|
| 18 |
+
tests/test_engine.py,sha256=NMPaSJdY7JHhIPyHMgiEdiRzH6oNzlL4jYaWPS42xgU,15276
|
| 19 |
+
tests/test_exports.py,sha256=7LpOpkjTJ0rp4qk_KXYjOWG1ow4ncOozb88QKwQheiY,23502
|
| 20 |
+
tests/test_integrations.py,sha256=H3ND6namUB8Ajwvb_ul12aRFeemslwwa1f7aMmZdAlg,6481
|
| 21 |
+
tests/test_python.py,sha256=KbIr7qjsU0Q7TPAWFhmtZRd8AhufEpjr1m5mzgBdcSc,40607
|
| 22 |
+
tests/test_solutions.py,sha256=nvTP6MtuwU742pdlzqexdEo8lCkybHURmwALZzwBxHo,14158
|
| 23 |
+
ultralytics-8.4.83.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
| 24 |
+
ultralytics-8.4.83.dist-info/METADATA,sha256=FVTZQev05uLqMTu5_c3nOAenvByDHl4ld8fcOJHfjPs,41801
|
| 25 |
+
ultralytics-8.4.83.dist-info/RECORD,,
|
| 26 |
+
ultralytics-8.4.83.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 27 |
+
ultralytics-8.4.83.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
| 28 |
+
ultralytics-8.4.83.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
|
| 29 |
+
ultralytics-8.4.83.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
| 30 |
+
ultralytics-8.4.83.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
|
| 31 |
+
ultralytics/__init__.py,sha256=EvUELO5v2GlZOoi7JxmL0HR1evkt3TPDlWh9knVhtFs,1301
|
| 32 |
+
ultralytics/__pycache__/__init__.cpython-314.pyc,,
|
| 33 |
+
ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
|
| 34 |
+
ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
|
| 35 |
+
ultralytics/cfg/__init__.py,sha256=d_Aj9m6tCjQy9SKnJvn4LFf9yS8t5QsU9yrvfqEL_bg,45019
|
| 36 |
+
ultralytics/cfg/__pycache__/__init__.cpython-314.pyc,,
|
| 37 |
+
ultralytics/cfg/datasets/Argoverse.yaml,sha256=VLuhz_gPQZTAaBFHEzSC9PxMOY3z8TUyUBZVBAm_HFE,3353
|
| 38 |
+
ultralytics/cfg/datasets/DOTAv1.5.yaml,sha256=X-u1bHSwFqf5-vgPIWiJfYev3KK9LHhXZz1ShQNkcc0,1212
|
| 39 |
+
ultralytics/cfg/datasets/DOTAv1.yaml,sha256=GOPKL5JUbdFU_B7jWtOPdz27OnX_DJMCm7WIWrZABr8,1182
|
| 40 |
+
ultralytics/cfg/datasets/GlobalWheat2020.yaml,sha256=_GjE5sxGcpLov7r-M06XsjWlolMiy3xLxs4ksw2lZRc,2143
|
| 41 |
+
ultralytics/cfg/datasets/HomeObjects-3K.yaml,sha256=uQ-wWTT9W-Hr7hiuqa4rMS5ATnkQeMuGReaJsqxeP7U,933
|
| 42 |
+
ultralytics/cfg/datasets/ImageNet.yaml,sha256=06smoReuJ9Q0XmzKlK0Y48z----SeaqgC6zdORy3b28,42528
|
| 43 |
+
ultralytics/cfg/datasets/Objects365.yaml,sha256=fKgiwvntM-RpbfJmAgPmfL3k1lyXl0JZZb6e_RE8v14,9648
|
| 44 |
+
ultralytics/cfg/datasets/SKU-110K.yaml,sha256=cVXoMAOHbik-MAOKqtke6TU2QCaEyn9cBlytqQeKh20,2608
|
| 45 |
+
ultralytics/cfg/datasets/TT100K.yaml,sha256=CMb94ZxiADjg1oKZThY2DrSt7VsqxrxIK3zlCotfQHw,6895
|
| 46 |
+
ultralytics/cfg/datasets/VOC.yaml,sha256=p-ZqQf5aP26FDqCfHZjfYOrDtzHB9VE5gpKlGlU9X2g,3802
|
| 47 |
+
ultralytics/cfg/datasets/VisDrone.yaml,sha256=z0lG4KNLohaNKbVBHoMh4avjpbKCv90CyLs__roJu58,3396
|
| 48 |
+
ultralytics/cfg/datasets/ade20k.yaml,sha256=DLj7DKcOa0rZHuJp72GgcU2XnBlypwp9ub-9tKdlid4,4322
|
| 49 |
+
ultralytics/cfg/datasets/african-wildlife.yaml,sha256=GH81S5fG5dAibTw_p1c0ivaLnnvXlGF3kzWtbyU3ejo,914
|
| 50 |
+
ultralytics/cfg/datasets/brain-tumor.yaml,sha256=y5Skd-Yy9wmAfF3E40LYvHQkYsgbDlWU5aKg0EhOwJY,799
|
| 51 |
+
ultralytics/cfg/datasets/carparts-seg.yaml,sha256=6Xy2UDEzsdUk-s3qgOSrrCFFByiunaJ7qHpL-JrsXb8,1252
|
| 52 |
+
ultralytics/cfg/datasets/cityscapes.yaml,sha256=hvqK65DEjCM0Xjl9xTqlQxUkYyBQjfRQ2zn561GCnEA,2998
|
| 53 |
+
ultralytics/cfg/datasets/cityscapes8.yaml,sha256=MM7KLZW1Jh2duhIaNM5v6PkUtlFgIypzXDrdnhL5kII,1623
|
| 54 |
+
ultralytics/cfg/datasets/coco-pose.yaml,sha256=fgiCiMjacLl9g-npcl19AqFJd9kkitUZEOHFakAmQc4,1927
|
| 55 |
+
ultralytics/cfg/datasets/coco.yaml,sha256=fgUmbfvfIGlPWgkm0GBb1xJKzkSc8tzow4nOAJ2jctA,2572
|
| 56 |
+
ultralytics/cfg/datasets/coco12-formats.yaml,sha256=ZzXepkW2h3u9xJpYYZCPNS9E7htGLKfzxGLTq-aioQo,1952
|
| 57 |
+
ultralytics/cfg/datasets/coco128-seg.yaml,sha256=lr8lrEnrsIM4bqG1YI9hYBrAfygf5CMu9opG8FXJf5Y,1992
|
| 58 |
+
ultralytics/cfg/datasets/coco128.yaml,sha256=B6CDxu3TCY1Mm3x-iRXEbM2N1IyOuXC_sU2ViVg5KEQ,1967
|
| 59 |
+
ultralytics/cfg/datasets/coco8-grayscale.yaml,sha256=ZbTr4lQpqVWCHw9d4Pghi9e3fJagrMLqXqX0wtU06G8,1960
|
| 60 |
+
ultralytics/cfg/datasets/coco8-multispectral.yaml,sha256=mDcNFGmSKT-bBk88EDDnIvuy18utSjAXlso1S581Aok,2062
|
| 61 |
+
ultralytics/cfg/datasets/coco8-pose.yaml,sha256=oaFyz668gJUfiL83UleJSch6UNV-biiL2rLTM6RrZPs,1335
|
| 62 |
+
ultralytics/cfg/datasets/coco8-seg.yaml,sha256=iXAMV5GP2xIO2PHl1JDHXvyIob2neo8RlKHkOVDac7Q,1912
|
| 63 |
+
ultralytics/cfg/datasets/coco8.yaml,sha256=Awqv-gj4oWHcNYfSFqqVbAyJR-WUstnYUVo2uaxE-fo,1887
|
| 64 |
+
ultralytics/cfg/datasets/construction-ppe.yaml,sha256=iSa27Cwowv1vycVK_o3hK8UXwHE8EdNTI6NvDVBynck,1007
|
| 65 |
+
ultralytics/cfg/datasets/crack-seg.yaml,sha256=jY7IZUxOamioCdcBdNO5eXt8fVeS40gCmbebouQpzkM,836
|
| 66 |
+
ultralytics/cfg/datasets/dog-pose.yaml,sha256=OboPj_y8QlEGH9ECqLNuT32RY_YapEo3IUn8Walvym0,1407
|
| 67 |
+
ultralytics/cfg/datasets/dota128.yaml,sha256=Kzktc64z93wTZdg3hvHrZyszlhNTZ4oPVsbXkkmtVGg,1079
|
| 68 |
+
ultralytics/cfg/datasets/dota8-multispectral.yaml,sha256=sZzrP1SUMryEJe8syMb6BsAghIbyfMQuqHI0BxiMRS4,1216
|
| 69 |
+
ultralytics/cfg/datasets/dota8.yaml,sha256=W_3Bcp8dRHeOL0VFWsaaNEXq8Kj2PzgYwVEQqeOtNqQ,1058
|
| 70 |
+
ultralytics/cfg/datasets/hand-keypoints.yaml,sha256=wPLYeZmGQ8lWI89oLwRVMDGnBka6H7yPZCtxeg8P878,1362
|
| 71 |
+
ultralytics/cfg/datasets/kitti.yaml,sha256=PRyDF6bkfG3X4aYv6PTUTSGHiCUsVAA2i9i8KO9OElI,894
|
| 72 |
+
ultralytics/cfg/datasets/lvis.yaml,sha256=0XwKkQW5d7VVkIHJP8KmLq2oxaUYPcR2L-mlp1hA870,29595
|
| 73 |
+
ultralytics/cfg/datasets/medical-pills.yaml,sha256=5GLYrB0rwkOrDSe1KswZAuly1LWdNyW1GsASRGHaKEM,791
|
| 74 |
+
ultralytics/cfg/datasets/open-images-v7.yaml,sha256=SXRor53GRNFJEB78CQcn08b9ZEWR9MwujFresA9K2Eg,12115
|
| 75 |
+
ultralytics/cfg/datasets/package-seg.yaml,sha256=uBzKJHCJtyfV-Omza8Fww6h_NDpNGIQco2wN513vj5w,848
|
| 76 |
+
ultralytics/cfg/datasets/signature.yaml,sha256=134eo-EpaK9XxISzTZnUP2bNtn3Hb-5j_-nO4Pt-JJM,773
|
| 77 |
+
ultralytics/cfg/datasets/tiger-pose.yaml,sha256=DQk5S7uH5JbP3pD6Q7I12AAagNRA3AKiZTeubsjhYR4,1195
|
| 78 |
+
ultralytics/cfg/datasets/xView.yaml,sha256=m2pWXw_SheDPwkPdNEVLIlx9uLhTEOTgOxePe7MG2Jo,5405
|
| 79 |
+
ultralytics/cfg/default.yaml,sha256=9uGatyKIJjQcxjcLzIx40QR40r1gTiWhPZl1te_JtBA,9690
|
| 80 |
+
ultralytics/cfg/models/11/yolo11-cls-resnet18.yaml,sha256=1Ycp9qMrwpb8rq7cqht3Q-1gMN0R87U35nm2j_isdro,524
|
| 81 |
+
ultralytics/cfg/models/11/yolo11-cls.yaml,sha256=17l5GdN-Vst4LvafsK2-q6Li9VX9UlUcT5ClCtikweE,1412
|
| 82 |
+
ultralytics/cfg/models/11/yolo11-obb.yaml,sha256=FHo7xWrhKdN2BBn2xdZ099T2NcqcUJiuyQ0a6zdvrqY,2031
|
| 83 |
+
ultralytics/cfg/models/11/yolo11-pose.yaml,sha256=dWOT9VBRxD8h-jmQC0qWEOvFvyx1CUa0tekt1kOdvmk,2131
|
| 84 |
+
ultralytics/cfg/models/11/yolo11-seg.yaml,sha256=xyTWVhFoSszF1LhNEIznIW8QGKU1z0EAIvkp4OwYtls,2046
|
| 85 |
+
ultralytics/cfg/models/11/yolo11.yaml,sha256=Q9inyGrMdygt30lm1lJuCR5bBkwUDtSm5MC2jsvDeEw,2012
|
| 86 |
+
ultralytics/cfg/models/11/yoloe-11-seg.yaml,sha256=j053cYgHMCRFUxJ7MumNkHz7eq6hxvcMMuNOzNsdV1w,2072
|
| 87 |
+
ultralytics/cfg/models/11/yoloe-11.yaml,sha256=qxKDa8Xt-embNVOLOthfQlt1N0kFFHnGFO74R_CQzUw,2038
|
| 88 |
+
ultralytics/cfg/models/12/yolo12-cls.yaml,sha256=yJBuDOXRYLa-LQipGkLBT97ujKSyXx755zts612JVWc,1407
|
| 89 |
+
ultralytics/cfg/models/12/yolo12-obb.yaml,sha256=2cPJKV7kU1thYxnnNsCJPfWNoTk0l29ZD22U4XTX3wQ,1972
|
| 90 |
+
ultralytics/cfg/models/12/yolo12-pose.yaml,sha256=eBo-9b3o_qv3-jftgCaX0FedeJWOfKHDLJPPfCMwu7M,2072
|
| 91 |
+
ultralytics/cfg/models/12/yolo12-seg.yaml,sha256=0JTqSjyhOTLNTIrIFAOuu6F7yQqMkq1soscAkSZtsz8,1985
|
| 92 |
+
ultralytics/cfg/models/12/yolo12.yaml,sha256=ZeA8LuymJXPNjZ5xkxkZHkcktDaKDzUBb2Kc3gCLC1w,1953
|
| 93 |
+
ultralytics/cfg/models/26/yolo26-cls.yaml,sha256=GmaLvnB62X6r9_mZwpx0b2LTRYIXzVYqSqR3Mcy336g,1432
|
| 94 |
+
ultralytics/cfg/models/26/yolo26-obb.yaml,sha256=A9Ng5nZOow74tYkejxoVyGB2wztIi_cuNqxYrqB5T38,2146
|
| 95 |
+
ultralytics/cfg/models/26/yolo26-p2.yaml,sha256=Dbwvo9_t5e3NolZquMfqFQrQZuop155o1sTaK6tHYnk,2405
|
| 96 |
+
ultralytics/cfg/models/26/yolo26-p6.yaml,sha256=YFWaH6NAOHoLYmH4Te3edcj5-c7QJ-glzri-xPFk4U0,2457
|
| 97 |
+
ultralytics/cfg/models/26/yolo26-pose.yaml,sha256=B7qC2WNwI_Jh5SbDj6muuKsF2RF2b_2M9PSM0z8nGI0,2245
|
| 98 |
+
ultralytics/cfg/models/26/yolo26-seg.yaml,sha256=U8A0ijaj4Zu8O9T2lfUMu_yXowWfYumyUfJ4rXT918s,2156
|
| 99 |
+
ultralytics/cfg/models/26/yolo26-sem.yaml,sha256=rX3g2vBk7U9T7ejtCjLWqjOaXaPNMEeR2BWq2oe5nYI,1850
|
| 100 |
+
ultralytics/cfg/models/26/yolo26.yaml,sha256=sdH6DGns7WT5k5U2A4vY1pfDLnIgCzQYenZ95DGvfvA,2120
|
| 101 |
+
ultralytics/cfg/models/26/yoloe-26-seg.yaml,sha256=QlyK3awjLOjs9q0raj0we5QCG1tDy-NvQ2uQzKDoBYk,2223
|
| 102 |
+
ultralytics/cfg/models/26/yoloe-26.yaml,sha256=YWsBS4D3f7QhqLQzYT-LVdCOISo0VaTILIaLKmujDdo,2191
|
| 103 |
+
ultralytics/cfg/models/rt-detr/rtdetr-l.yaml,sha256=hXFvYmdpy13fANWfz2yvtYFKrRljKBAL3HyTMG9lDoM,2043
|
| 104 |
+
ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml,sha256=5vCPfihyzXMKCR7kYYIDSHbSHvAzYlWbOZ5Wp9m84Ms,1696
|
| 105 |
+
ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml,sha256=Xm-U_m-_okdspiW7qxb5mgN_NPZPvyjXrS1A1KcoaFo,1692
|
| 106 |
+
ultralytics/cfg/models/rt-detr/rtdetr-x.yaml,sha256=QHa3B5Pwd9TA9B3W5lEwrUl-_bAvwGXVqSlvnLSbKNs,2250
|
| 107 |
+
ultralytics/cfg/models/v10/yolov10b.yaml,sha256=W9K-lqgUEKOCpV0Ae7dk8iBUFpSTTFzDPDL3AHnMKfs,1488
|
| 108 |
+
ultralytics/cfg/models/v10/yolov10l.yaml,sha256=YtdL74ivxWxY2jUsYkkUX_WraWsLJtcOKhRNioCwvJg,1488
|
| 109 |
+
ultralytics/cfg/models/v10/yolov10m.yaml,sha256=YQuxn4KjiGqxwK-3BuRSprt86aWxcxn2VngIlHQKxy4,1479
|
| 110 |
+
ultralytics/cfg/models/v10/yolov10n.yaml,sha256=iL9T4XUrTnf001i6e9qF9wEBCUoral_fF5bjIFxJdMU,1474
|
| 111 |
+
ultralytics/cfg/models/v10/yolov10s.yaml,sha256=dG_z0fSweIzCi7Km9OY-Q9IztEOjX67wFsdP4Eam_to,1483
|
| 112 |
+
ultralytics/cfg/models/v10/yolov10x.yaml,sha256=IFIYR5p46OECsHK3yz5UO5CMxR1JNDWeXKzUQQvxM_M,1491
|
| 113 |
+
ultralytics/cfg/models/v3/yolov3-spp.yaml,sha256=hsM-yhdWv-8XlWuaSOVqFJcHUVZ-FmjH4QjkA9CHJZU,1625
|
| 114 |
+
ultralytics/cfg/models/v3/yolov3-tiny.yaml,sha256=SYrSg0m1A6ErUapdrJDI5E-edLaH0oF-NRb558DZgmQ,1330
|
| 115 |
+
ultralytics/cfg/models/v3/yolov3.yaml,sha256=Fvt4_PTwLBpRw3R4v4VQ-1PIiojpoFZD1uuTZySUYSw,1612
|
| 116 |
+
ultralytics/cfg/models/v5/yolov5-p6.yaml,sha256=VKEWykksykSlzvuy7if4yFo9WlblC3hdqcNxJ9bwHek,1994
|
| 117 |
+
ultralytics/cfg/models/v5/yolov5.yaml,sha256=QD8dRe5e5ys52wXPKvNJn622H_3iX0jPzE_2--2dZx0,1626
|
| 118 |
+
ultralytics/cfg/models/v6/yolov6.yaml,sha256=tl04iHe4dVg_78jgupVul5gbqOn5hBhtLKfP3xYxcWA,1813
|
| 119 |
+
ultralytics/cfg/models/v8/yoloe-v8-seg.yaml,sha256=5cjZ2xCMUF2pV7gv1ZoRFEV6Lo6v4slMQt1lU7_Jqtc,2064
|
| 120 |
+
ultralytics/cfg/models/v8/yoloe-v8.yaml,sha256=dujtgHql2RzqqEEpB4UzsEpAXMRarkltnt8vb1usILc,2015
|
| 121 |
+
ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml,sha256=TAiAkZwUckzjWdY6yn_ulGzM-lnHaY7Yx9v8rI-2WoA,1014
|
| 122 |
+
ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml,sha256=gbIttNMvj02Rk3eKjq45qgjdmdCo5n_mV9R5xt65OdU,1010
|
| 123 |
+
ultralytics/cfg/models/v8/yolov8-cls.yaml,sha256=G50mnw-C0SWrZpZl5wzov1dugdjZMM6zT30t5cQrcJQ,1019
|
| 124 |
+
ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml,sha256=5MX8D3_8lkj9aKVwpAIC1PZAaMoTFs_Wq-XZUTVn9PU,2505
|
| 125 |
+
ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml,sha256=c7YYnEPx2vrwHjbgr4o_Q9f_NI2X1dx2MrLo9xeOvXc,2575
|
| 126 |
+
ultralytics/cfg/models/v8/yolov8-ghost.yaml,sha256=nxzIlvntFajHbu4DN8ujEx65PREgn7o0Dd6cHp8pHSM,2198
|
| 127 |
+
ultralytics/cfg/models/v8/yolov8-obb.yaml,sha256=Owlncx5peKBTNo3xhkbVxz_1qlzVJR4Z2zNeoR_NDxg,2016
|
| 128 |
+
ultralytics/cfg/models/v8/yolov8-p2.yaml,sha256=ulQ2Pp8oPo9gsPoIQ-s3EVCTM41vknPM1PdPYGOXVPQ,1831
|
| 129 |
+
ultralytics/cfg/models/v8/yolov8-p6.yaml,sha256=TqIsa8gNEW04KmdLxxC9rqhd7PCHlUqkzoiDxnMTio0,2363
|
| 130 |
+
ultralytics/cfg/models/v8/yolov8-pose-p6.yaml,sha256=tfgfYrbVu5biWCWmdTZRr7ZRC-zlAzycsRyaJbDtI1g,2047
|
| 131 |
+
ultralytics/cfg/models/v8/yolov8-pose.yaml,sha256=LdzbiIVknZQMLYB2wzCHqul3NilfKp4nx5SdaGQsF6s,1676
|
| 132 |
+
ultralytics/cfg/models/v8/yolov8-rtdetr.yaml,sha256=5cupHKPHD43cuvd3H3zvNijiqpW9-bFLKg-KMeRzOPE,2055
|
| 133 |
+
ultralytics/cfg/models/v8/yolov8-seg-p6.yaml,sha256=7FlNlY-sB8bCcVty2Hf_nYD8fxZpsqaTgGxTfac8DRI,1958
|
| 134 |
+
ultralytics/cfg/models/v8/yolov8-seg.yaml,sha256=hFeiOFVwTV4zv08IrmTIuzJcUZmYkY7SIi2oV322e6U,1587
|
| 135 |
+
ultralytics/cfg/models/v8/yolov8-world.yaml,sha256=2hNQoybITO5FBNnKKz05Pk9ygeAf4qW7XvkMEfBd90A,2174
|
| 136 |
+
ultralytics/cfg/models/v8/yolov8-worldv2.yaml,sha256=UkdRhk7pauLIZto7QdOrWpW8Mb-3J61RdRuxS5lZC24,2124
|
| 137 |
+
ultralytics/cfg/models/v8/yolov8.yaml,sha256=QFo8MC62CWEDqZr02CwdLYsrv_RpoijFWqyUSywZZyo,1977
|
| 138 |
+
ultralytics/cfg/models/v9/yolov9c-seg.yaml,sha256=UBHoQ_cJV2yp6rMzHXRp46uBAUmKIrbgd3jiEBPRvqI,1447
|
| 139 |
+
ultralytics/cfg/models/v9/yolov9c.yaml,sha256=x1kus_2mQdU9V3ZGg0XdE5WTUU3j8fwGe1Ou3x2aX5I,1426
|
| 140 |
+
ultralytics/cfg/models/v9/yolov9e-seg.yaml,sha256=WVpU5jHgoUuCMVirvmn_ScOmH9d1MyVVIX8XAY8787c,2377
|
| 141 |
+
ultralytics/cfg/models/v9/yolov9e.yaml,sha256=Olr2PlADpkD6N1TiVyAJEMzkrA7SbNul1nOaUF8CS38,2355
|
| 142 |
+
ultralytics/cfg/models/v9/yolov9m.yaml,sha256=WcKQ3xRsC1JMgA42Hx4xzr4FZmtE6B3wKvqhlQxkqw8,1411
|
| 143 |
+
ultralytics/cfg/models/v9/yolov9s.yaml,sha256=cWkQtYNWWOckOBXjd8XrJ_q5v6T_C54xGMP1S3qnpZU,1392
|
| 144 |
+
ultralytics/cfg/models/v9/yolov9t.yaml,sha256=Q8GpSXE7fumhuJiQg4a2SkuS_UmnXqp-eoZxW_C0vEo,1375
|
| 145 |
+
ultralytics/cfg/trackers/botsort.yaml,sha256=jNiJMNO-VVe-B3fzhO7P8KNqcBGFD-YT_ApoF4v9WwE,1385
|
| 146 |
+
ultralytics/cfg/trackers/bytetrack.yaml,sha256=OVcB2UenSRed7j4yexGBtzDEypjnysWiqwUoCq5XO4s,856
|
| 147 |
+
ultralytics/cfg/trackers/deepocsort.yaml,sha256=2N6cOrpVc5LYSWsVRS0NxtWM86LotVLT2iZvImwlLMA,1901
|
| 148 |
+
ultralytics/cfg/trackers/fasttrack.yaml,sha256=YAeLULJ9sh54zQ3BCTY5yO53tPhqzNvFZlfTrClEPtc,1584
|
| 149 |
+
ultralytics/cfg/trackers/ocsort.yaml,sha256=VduR8U2z8BRm2Banrw-fqu63T0SF2mMBnH7WmpqvtuM,1267
|
| 150 |
+
ultralytics/cfg/trackers/tracktrack.yaml,sha256=M_zQz0ICP6vBz_k-h2n5SeP5Kjkhmot94Vf8YSod43o,1889
|
| 151 |
+
ultralytics/data/__init__.py,sha256=KsV__8wWRNzjd-iUeIX57Pvtmet28MSxjHqG1ux-YoM,702
|
| 152 |
+
ultralytics/data/__pycache__/__init__.cpython-314.pyc,,
|
| 153 |
+
ultralytics/data/__pycache__/annotator.cpython-314.pyc,,
|
| 154 |
+
ultralytics/data/__pycache__/augment.cpython-314.pyc,,
|
| 155 |
+
ultralytics/data/__pycache__/base.cpython-314.pyc,,
|
| 156 |
+
ultralytics/data/__pycache__/build.cpython-314.pyc,,
|
| 157 |
+
ultralytics/data/__pycache__/converter.cpython-314.pyc,,
|
| 158 |
+
ultralytics/data/__pycache__/dataset.cpython-314.pyc,,
|
| 159 |
+
ultralytics/data/__pycache__/loaders.cpython-314.pyc,,
|
| 160 |
+
ultralytics/data/__pycache__/split.cpython-314.pyc,,
|
| 161 |
+
ultralytics/data/__pycache__/split_dota.cpython-314.pyc,,
|
| 162 |
+
ultralytics/data/__pycache__/utils.cpython-314.pyc,,
|
| 163 |
+
ultralytics/data/annotator.py,sha256=iu1En-LzlR4RyR3ocftthnAog_peQHV9ForPRo_QcX8,2985
|
| 164 |
+
ultralytics/data/augment.py,sha256=gjcuITBVF8mdeOzbtotdSWJspmk-77gE83Nu0lyfYJw,137544
|
| 165 |
+
ultralytics/data/base.py,sha256=aRWZbN8aApEmycYRcdZbpgz4Y6IFV77S4q88NM6csCk,21125
|
| 166 |
+
ultralytics/data/build.py,sha256=aH-W8UzHZHntjJtq_tSQ-Q7IbuqJj86wCrfbz8Fdlvc,17816
|
| 167 |
+
ultralytics/data/converter.py,sha256=r4JcwdMWHy6LIRo1Mgk-OS2-H03D8t4h2SzIAPDiizA,41508
|
| 168 |
+
ultralytics/data/dataset.py,sha256=dpAKQkdPsTt4ciZ9FMbJZFqecGBAagz7Athtw5ITaQM,50820
|
| 169 |
+
ultralytics/data/loaders.py,sha256=3S6ypo1pamNk5MWBHGzeVtB-kiXBMwQQHhYY2AXnmyM,31697
|
| 170 |
+
ultralytics/data/scripts/download_weights.sh,sha256=0y8XtZxOru7dVThXDFUXLHBuICgOIqZNUwpyL4Rh6lg,595
|
| 171 |
+
ultralytics/data/scripts/get_coco.sh,sha256=UuJpJeo3qQpTHVINeOpmP0NYmg8PhEFE3A8J3jKrnPw,1768
|
| 172 |
+
ultralytics/data/scripts/get_coco128.sh,sha256=qmRQl_hOKrsdHrTrnyQuFIH01oDz3lfaz138OgGfLt8,650
|
| 173 |
+
ultralytics/data/scripts/get_imagenet.sh,sha256=hr42H16bM47iT27rgS7MpEo-GeOZAYUQXgr0B2cwn48,1705
|
| 174 |
+
ultralytics/data/split.py,sha256=Ds8Etjc9lLpfNmY3mChxvg_wuuWd350QLf2mQHu7-kg,5122
|
| 175 |
+
ultralytics/data/split_dota.py,sha256=dqz3DApL8eAkMCKeD8UEyR2UV8rjXbCqQzUrrd702Fk,12873
|
| 176 |
+
ultralytics/data/utils.py,sha256=XqVrAiI2vBJREwkvGKFXlsOWHwqjpaFHIGHFawmnqc4,40392
|
| 177 |
+
ultralytics/engine/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
|
| 178 |
+
ultralytics/engine/__pycache__/__init__.cpython-314.pyc,,
|
| 179 |
+
ultralytics/engine/__pycache__/exporter.cpython-314.pyc,,
|
| 180 |
+
ultralytics/engine/__pycache__/model.cpython-314.pyc,,
|
| 181 |
+
ultralytics/engine/__pycache__/predictor.cpython-314.pyc,,
|
| 182 |
+
ultralytics/engine/__pycache__/results.cpython-314.pyc,,
|
| 183 |
+
ultralytics/engine/__pycache__/trainer.cpython-314.pyc,,
|
| 184 |
+
ultralytics/engine/__pycache__/tuner.cpython-314.pyc,,
|
| 185 |
+
ultralytics/engine/__pycache__/validator.cpython-314.pyc,,
|
| 186 |
+
ultralytics/engine/exporter.py,sha256=I1MOSeVAdqWWMi0IAodhOLTYvC8heHbyioOyv9YGaFE,74087
|
| 187 |
+
ultralytics/engine/model.py,sha256=4xxyMqTMTE6VtcKX0SV0ypTpPTXpuy3JZ0TlxFchUxc,55936
|
| 188 |
+
ultralytics/engine/predictor.py,sha256=LcgTiMZqEKBpv-pUnHe0txE6Sfbel8SwcRaaghPgg9A,23490
|
| 189 |
+
ultralytics/engine/results.py,sha256=sUc7ir53VOk3bVarmNHDcHFgRQ8DTF_AULVOJO-MDdo,71545
|
| 190 |
+
ultralytics/engine/trainer.py,sha256=RINrpq_oAfyWsg_IssVcFpRfql82gWUdFYUvAuRAI1M,63982
|
| 191 |
+
ultralytics/engine/tuner.py,sha256=0hP39op56BS8GX29RLdO-a5h3YTNjc-xExcp1gxSgkc,27999
|
| 192 |
+
ultralytics/engine/validator.py,sha256=yaOtrP0W2a_Oh1-L92B2foDQShXRajj7wVQdsBZtqYI,18703
|
| 193 |
+
ultralytics/hub/__init__.py,sha256=7LyzMguIzOnUz1CgrXYvAy93w_navq9oGuoVa3iZmII,6729
|
| 194 |
+
ultralytics/hub/__pycache__/__init__.cpython-314.pyc,,
|
| 195 |
+
ultralytics/hub/__pycache__/auth.cpython-314.pyc,,
|
| 196 |
+
ultralytics/hub/__pycache__/session.cpython-314.pyc,,
|
| 197 |
+
ultralytics/hub/__pycache__/utils.cpython-314.pyc,,
|
| 198 |
+
ultralytics/hub/auth.py,sha256=sNT8jyHXTHe5egiy9WvRgyIWjI22I57enGiHkhQlJXM,6699
|
| 199 |
+
ultralytics/hub/google/__init__.py,sha256=r06Ld4TuZEBOqg4iagpeN-eMAkg43T2OTxOH4_7IfkM,8445
|
| 200 |
+
ultralytics/hub/google/__pycache__/__init__.cpython-314.pyc,,
|
| 201 |
+
ultralytics/hub/session.py,sha256=bHUYgKkhzWSzH_VHd6Tg3MrlrEwnODx5hQ4McMB1jWY,18354
|
| 202 |
+
ultralytics/hub/utils.py,sha256=NyG2aQdA-OJtHhJfETZ5QQCuZ-CICIkNDneDWb5lidg,6822
|
| 203 |
+
ultralytics/models/__init__.py,sha256=ZJ0u7d_x0DTU1BLrF8L-8E4QoUHtrEiQ41jIFNWLBW0,642
|
| 204 |
+
ultralytics/models/__pycache__/__init__.cpython-314.pyc,,
|
| 205 |
+
ultralytics/models/fastsam/__init__.py,sha256=Ku89Fy_X8ok3YPEUajjUZ5i4O08jdJMjJHt-3Z99Frk,231
|
| 206 |
+
ultralytics/models/fastsam/__pycache__/__init__.cpython-314.pyc,,
|
| 207 |
+
ultralytics/models/fastsam/__pycache__/model.cpython-314.pyc,,
|
| 208 |
+
ultralytics/models/fastsam/__pycache__/predict.cpython-314.pyc,,
|
| 209 |
+
ultralytics/models/fastsam/__pycache__/utils.cpython-314.pyc,,
|
| 210 |
+
ultralytics/models/fastsam/__pycache__/val.cpython-314.pyc,,
|
| 211 |
+
ultralytics/models/fastsam/model.py,sha256=HN6CAHCTwMmyBCQlXx4wMBU7XqkvVHyUawRaxn2Gur8,3426
|
| 212 |
+
ultralytics/models/fastsam/predict.py,sha256=01araYUgwWO_Yz_W6mTZusOj7v-S3175eUqkpbxv5P8,8853
|
| 213 |
+
ultralytics/models/fastsam/utils.py,sha256=de9ieh4pBUuTNh5HTiNdRpWZhXAaSfNo3R1FNMt2GOE,879
|
| 214 |
+
ultralytics/models/fastsam/val.py,sha256=MJUKx_NpFEeuqSq9ynX1FJSK6F5RhUJB-PqhQp2Q0YM,2091
|
| 215 |
+
ultralytics/models/nas/__init__.py,sha256=Q4ZQak8xNWtV5YSw_pFu0anbCyDxxEAuMMDfMzu6-0s,207
|
| 216 |
+
ultralytics/models/nas/__pycache__/__init__.cpython-314.pyc,,
|
| 217 |
+
ultralytics/models/nas/__pycache__/model.cpython-314.pyc,,
|
| 218 |
+
ultralytics/models/nas/__pycache__/predict.cpython-314.pyc,,
|
| 219 |
+
ultralytics/models/nas/__pycache__/val.cpython-314.pyc,,
|
| 220 |
+
ultralytics/models/nas/model.py,sha256=as1NSv1pCDbyA-vNzD6pgmEIJVlinx4y20slISYsIoY,3910
|
| 221 |
+
ultralytics/models/nas/predict.py,sha256=4nbuo9nbvnvI3qVH1ylhLCjo-7oW39MumIesm-1eU3Y,2692
|
| 222 |
+
ultralytics/models/nas/val.py,sha256=MIRym3LQNDIRxnYs5xcOiLkKOgv3enZFXh5_g9Pq2hA,1543
|
| 223 |
+
ultralytics/models/rtdetr/__init__.py,sha256=F4NEQqtcVKFxj97Dh7rkn2Vu3JG4Ea_nxqrBB-9P1vc,225
|
| 224 |
+
ultralytics/models/rtdetr/__pycache__/__init__.cpython-314.pyc,,
|
| 225 |
+
ultralytics/models/rtdetr/__pycache__/model.cpython-314.pyc,,
|
| 226 |
+
ultralytics/models/rtdetr/__pycache__/predict.cpython-314.pyc,,
|
| 227 |
+
ultralytics/models/rtdetr/__pycache__/train.cpython-314.pyc,,
|
| 228 |
+
ultralytics/models/rtdetr/__pycache__/val.cpython-314.pyc,,
|
| 229 |
+
ultralytics/models/rtdetr/model.py,sha256=jJzSh_5E__rVQO7_IkmncpC4jIdu9xNiIxlTTIaFJVw,2269
|
| 230 |
+
ultralytics/models/rtdetr/predict.py,sha256=SU5UPoyxLmFCZ2IsSaYb6vux8bsrw90K79FajFDdl80,3969
|
| 231 |
+
ultralytics/models/rtdetr/train.py,sha256=exPmset_CWK3ZBer3btEvDLttgMPXusMr21WsJF3bkg,3740
|
| 232 |
+
ultralytics/models/rtdetr/val.py,sha256=dvDDlV44X3Yi51EJ-vln_8_JOTuX0b4pPIMcqDg2qbo,8936
|
| 233 |
+
ultralytics/models/sam/__init__.py,sha256=hofz9cGGhxEWpZXX8yLp5k_LQUmWL_Shd9kfzK4U6z0,592
|
| 234 |
+
ultralytics/models/sam/__pycache__/__init__.cpython-314.pyc,,
|
| 235 |
+
ultralytics/models/sam/__pycache__/amg.cpython-314.pyc,,
|
| 236 |
+
ultralytics/models/sam/__pycache__/build.cpython-314.pyc,,
|
| 237 |
+
ultralytics/models/sam/__pycache__/build_sam3.cpython-314.pyc,,
|
| 238 |
+
ultralytics/models/sam/__pycache__/model.cpython-314.pyc,,
|
| 239 |
+
ultralytics/models/sam/__pycache__/predict.cpython-314.pyc,,
|
| 240 |
+
ultralytics/models/sam/amg.py,sha256=aYvJ7jQMkTR3X9KV7SHi3qP3yNchQggWNUurTRZwxQg,11786
|
| 241 |
+
ultralytics/models/sam/build.py,sha256=si1hdoTAeHK4tNd8GhpzTTlPvis_baGDlYm-EVelkPU,12860
|
| 242 |
+
ultralytics/models/sam/build_sam3.py,sha256=dFlaZIdEP7ZPPWD4p5vV8YzrnNnFvEdnigee6xF3kFU,12206
|
| 243 |
+
ultralytics/models/sam/model.py,sha256=uySve5lRbaKqzpyeAMWazzrghXvEf2Hhat9NrlY8d5g,7372
|
| 244 |
+
ultralytics/models/sam/modules/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
|
| 245 |
+
ultralytics/models/sam/modules/__pycache__/__init__.cpython-314.pyc,,
|
| 246 |
+
ultralytics/models/sam/modules/__pycache__/blocks.cpython-314.pyc,,
|
| 247 |
+
ultralytics/models/sam/modules/__pycache__/decoders.cpython-314.pyc,,
|
| 248 |
+
ultralytics/models/sam/modules/__pycache__/encoders.cpython-314.pyc,,
|
| 249 |
+
ultralytics/models/sam/modules/__pycache__/memory_attention.cpython-314.pyc,,
|
| 250 |
+
ultralytics/models/sam/modules/__pycache__/sam.cpython-314.pyc,,
|
| 251 |
+
ultralytics/models/sam/modules/__pycache__/tiny_encoder.cpython-314.pyc,,
|
| 252 |
+
ultralytics/models/sam/modules/__pycache__/transformer.cpython-314.pyc,,
|
| 253 |
+
ultralytics/models/sam/modules/__pycache__/utils.cpython-314.pyc,,
|
| 254 |
+
ultralytics/models/sam/modules/blocks.py,sha256=8YzIRTXywRovNb-ds6VMcvHd-gPsij336Muo8LzPV3U,44466
|
| 255 |
+
ultralytics/models/sam/modules/decoders.py,sha256=MGUC8zs8FFtSacBwrp4Nva7sgYmCXpULPW-TmVXz4wg,25045
|
| 256 |
+
ultralytics/models/sam/modules/encoders.py,sha256=dggzE0L6f-Yt3UCQRUBfihZtmAspgCyySb6TqdFZW1U,35521
|
| 257 |
+
ultralytics/models/sam/modules/memory_attention.py,sha256=x8AjFkmK7sx4qXDCdJ_yBsxtQBqeldYNBMRe8ntpLHs,13287
|
| 258 |
+
ultralytics/models/sam/modules/sam.py,sha256=91DEeUIwHhREoJ7Bxr6lD5ztonGUlnZOV9fR7x98ho8,61669
|
| 259 |
+
ultralytics/models/sam/modules/tiny_encoder.py,sha256=xnroC5KLwHG4rdcto2IWyJrR7hbUUF7201-meGh5XlM,42355
|
| 260 |
+
ultralytics/models/sam/modules/transformer.py,sha256=qGcEt5coPyWeaXjK1nzt-ID5HW2Q30u6tAxSyOkx3Sg,14884
|
| 261 |
+
ultralytics/models/sam/modules/utils.py,sha256=HwHAf_yxMnYc1cs5bAnPIDyOkIbrUMw0qha9TB8olU0,21371
|
| 262 |
+
ultralytics/models/sam/predict.py,sha256=-YXDCbX-fIn1bFlZZzInmdnwFXnVcp0UaPqsrK-HW2U,204699
|
| 263 |
+
ultralytics/models/sam/sam3/__init__.py,sha256=aM4-KimnYgIFe-e5ctLT8e6k9PagvuvKFaHaagDZM7E,144
|
| 264 |
+
ultralytics/models/sam/sam3/__pycache__/__init__.cpython-314.pyc,,
|
| 265 |
+
ultralytics/models/sam/sam3/__pycache__/decoder.cpython-314.pyc,,
|
| 266 |
+
ultralytics/models/sam/sam3/__pycache__/encoder.cpython-314.pyc,,
|
| 267 |
+
ultralytics/models/sam/sam3/__pycache__/geometry_encoders.cpython-314.pyc,,
|
| 268 |
+
ultralytics/models/sam/sam3/__pycache__/maskformer_segmentation.cpython-314.pyc,,
|
| 269 |
+
ultralytics/models/sam/sam3/__pycache__/model_misc.cpython-314.pyc,,
|
| 270 |
+
ultralytics/models/sam/sam3/__pycache__/necks.cpython-314.pyc,,
|
| 271 |
+
ultralytics/models/sam/sam3/__pycache__/sam3_image.cpython-314.pyc,,
|
| 272 |
+
ultralytics/models/sam/sam3/__pycache__/text_encoder_ve.cpython-314.pyc,,
|
| 273 |
+
ultralytics/models/sam/sam3/__pycache__/vitdet.cpython-314.pyc,,
|
| 274 |
+
ultralytics/models/sam/sam3/__pycache__/vl_combiner.cpython-314.pyc,,
|
| 275 |
+
ultralytics/models/sam/sam3/decoder.py,sha256=pjNDET-GRcaDhB9oWnuAOGED_pTsM-3MGjL7LSBLj5U,23006
|
| 276 |
+
ultralytics/models/sam/sam3/encoder.py,sha256=zHDR-8W5e9dH_2KG4BbXb89PnHY08V2v-bzrEOSYnjc,21751
|
| 277 |
+
ultralytics/models/sam/sam3/geometry_encoders.py,sha256=C2u5RD0sCdShp6KsrratSOwpNUmqRQ72wJ409-_q5oE,17667
|
| 278 |
+
ultralytics/models/sam/sam3/maskformer_segmentation.py,sha256=jf9qJj7xyTVGp7OZ5uJQF0EUD468EOnBm1PsjiTO2ug,10735
|
| 279 |
+
ultralytics/models/sam/sam3/model_misc.py,sha256=rA0ZOMH-S2NrO7tyBcVDmmI0DdAmWRyR827AZIHi3nA,7926
|
| 280 |
+
ultralytics/models/sam/sam3/necks.py,sha256=SmkgJZBJSMXW5XBY5rEsSu5mjtWT2IE0jH4eWtwLOFA,4767
|
| 281 |
+
ultralytics/models/sam/sam3/sam3_image.py,sha256=IxwnI0TM1oRiUcOjAmOolDlFNcWTirtlIeA8QpYE6GE,13454
|
| 282 |
+
ultralytics/models/sam/sam3/text_encoder_ve.py,sha256=iv8-6VA3t4yJ1M42RPjHDlFuH9P_nNRSNyaoFn2sjMw,12283
|
| 283 |
+
ultralytics/models/sam/sam3/vitdet.py,sha256=Ni6fR3WBfp_FLvOP8MVdnRUk_1jOae16yjyox4cSJBg,22130
|
| 284 |
+
ultralytics/models/sam/sam3/vl_combiner.py,sha256=l7IiBmljzotrNb3egQG4aGEp2RZIKugeQ25MJn3QBE4,6998
|
| 285 |
+
ultralytics/models/utils/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
|
| 286 |
+
ultralytics/models/utils/__pycache__/__init__.cpython-314.pyc,,
|
| 287 |
+
ultralytics/models/utils/__pycache__/loss.cpython-314.pyc,,
|
| 288 |
+
ultralytics/models/utils/__pycache__/ops.cpython-314.pyc,,
|
| 289 |
+
ultralytics/models/utils/loss.py,sha256=JlSDpkqrndY-VrP6GoZLg4kW3d3suiHa-yEh_FE7v68,21142
|
| 290 |
+
ultralytics/models/utils/ops.py,sha256=7yEfr8ESpxUwWoBw8AU_rDj69ND58ovATZHJoRJFF3g,15203
|
| 291 |
+
ultralytics/models/yolo/__init__.py,sha256=eV7Rvr7cwHILl0LYbCiqNChori_FPk_yahpNge_x_6M,329
|
| 292 |
+
ultralytics/models/yolo/__pycache__/__init__.cpython-314.pyc,,
|
| 293 |
+
ultralytics/models/yolo/__pycache__/model.cpython-314.pyc,,
|
| 294 |
+
ultralytics/models/yolo/classify/__init__.py,sha256=9--HVaNOfI1K7rn_rRqclL8FUAnpfeBrRqEQIaQw2xM,383
|
| 295 |
+
ultralytics/models/yolo/classify/__pycache__/__init__.cpython-314.pyc,,
|
| 296 |
+
ultralytics/models/yolo/classify/__pycache__/predict.cpython-314.pyc,,
|
| 297 |
+
ultralytics/models/yolo/classify/__pycache__/train.cpython-314.pyc,,
|
| 298 |
+
ultralytics/models/yolo/classify/__pycache__/val.cpython-314.pyc,,
|
| 299 |
+
ultralytics/models/yolo/classify/predict.py,sha256=pRNrwGVdAuDJdm-0rSY5C7MCdjmHA75tmTk8phtPACI,4202
|
| 300 |
+
ultralytics/models/yolo/classify/train.py,sha256=1PeNeMtgkQJsb_fFNB-Ll6hEVqnu8uZJJNUjpw8mW2Q,10161
|
| 301 |
+
ultralytics/models/yolo/classify/val.py,sha256=PSpCXXG9sSMCffRX4rM4bFlHMvq6VWVaq3ygnnx48os,10534
|
| 302 |
+
ultralytics/models/yolo/detect/__init__.py,sha256=GIRsLYR-kT4JJx7lh4ZZAFGBZj0aebokuU0A7JbjDVA,257
|
| 303 |
+
ultralytics/models/yolo/detect/__pycache__/__init__.cpython-314.pyc,,
|
| 304 |
+
ultralytics/models/yolo/detect/__pycache__/predict.cpython-314.pyc,,
|
| 305 |
+
ultralytics/models/yolo/detect/__pycache__/train.cpython-314.pyc,,
|
| 306 |
+
ultralytics/models/yolo/detect/__pycache__/val.cpython-314.pyc,,
|
| 307 |
+
ultralytics/models/yolo/detect/predict.py,sha256=L01OgXeC2lbZ1oZAhHJ6lXal0nY3DMGBFDViKUGiOF0,5474
|
| 308 |
+
ultralytics/models/yolo/detect/train.py,sha256=w4XGYTfd0QkHBb9sv35haasRR9onQXikp1YTu9DA00Y,12565
|
| 309 |
+
ultralytics/models/yolo/detect/val.py,sha256=VQaL4b0y3cNJHP47C_UUnOtG_TAavwAm5mmSZPaWRWo,24109
|
| 310 |
+
ultralytics/models/yolo/model.py,sha256=RMWkHQercvbdtqrLK3Byv8G34OqqrArXW_k3zNc1smk,19181
|
| 311 |
+
ultralytics/models/yolo/obb/__init__.py,sha256=tQmpG8wVHsajWkZdmD6cjGohJ4ki64iSXQT8JY_dydo,221
|
| 312 |
+
ultralytics/models/yolo/obb/__pycache__/__init__.cpython-314.pyc,,
|
| 313 |
+
ultralytics/models/yolo/obb/__pycache__/predict.cpython-314.pyc,,
|
| 314 |
+
ultralytics/models/yolo/obb/__pycache__/train.cpython-314.pyc,,
|
| 315 |
+
ultralytics/models/yolo/obb/__pycache__/val.cpython-314.pyc,,
|
| 316 |
+
ultralytics/models/yolo/obb/predict.py,sha256=VA5yRo32IVakZ_5nY75KArfaXnZbANzTkxMVGDm-co4,2634
|
| 317 |
+
ultralytics/models/yolo/obb/train.py,sha256=I7mxTdoR1-BtAgMAI9jkhzm6QuTr546jeT_ere4nzyI,3437
|
| 318 |
+
ultralytics/models/yolo/obb/val.py,sha256=Vchk94T5AOUXmKncCPIOlnfmDlkzgD6oglZm6BrOc58,14563
|
| 319 |
+
ultralytics/models/yolo/pose/__init__.py,sha256=_9OFLj19XwvJHBRxQtVW5CV7rvJ_3hDPE97miit0sPc,227
|
| 320 |
+
ultralytics/models/yolo/pose/__pycache__/__init__.cpython-314.pyc,,
|
| 321 |
+
ultralytics/models/yolo/pose/__pycache__/predict.cpython-314.pyc,,
|
| 322 |
+
ultralytics/models/yolo/pose/__pycache__/train.cpython-314.pyc,,
|
| 323 |
+
ultralytics/models/yolo/pose/__pycache__/val.cpython-314.pyc,,
|
| 324 |
+
ultralytics/models/yolo/pose/predict.py,sha256=a_D6-0qCRhTL_ccFe6UTNB1jgaB3Mp1wedLDQpeLPeM,3175
|
| 325 |
+
ultralytics/models/yolo/pose/train.py,sha256=OpySjq7H_0zgGaHlMPne_0etFginGHzrfrMiyQ9rhwA,5073
|
| 326 |
+
ultralytics/models/yolo/pose/val.py,sha256=cynNhSzq7PEpTAr1Tc-e7t8ed5YGaoYXn_9faVFFCcU,12111
|
| 327 |
+
ultralytics/models/yolo/segment/__init__.py,sha256=3IThhZ1wlkY9FvmWm9cE-5-ZyE6F1FgzAtQ6jOOFzzw,275
|
| 328 |
+
ultralytics/models/yolo/segment/__pycache__/__init__.cpython-314.pyc,,
|
| 329 |
+
ultralytics/models/yolo/segment/__pycache__/predict.cpython-314.pyc,,
|
| 330 |
+
ultralytics/models/yolo/segment/__pycache__/train.cpython-314.pyc,,
|
| 331 |
+
ultralytics/models/yolo/segment/__pycache__/val.cpython-314.pyc,,
|
| 332 |
+
ultralytics/models/yolo/segment/predict.py,sha256=L4DCWXgvMwsSs_S16xE0VBa4PpnWr4baO75ZQIm94Bw,5556
|
| 333 |
+
ultralytics/models/yolo/segment/train.py,sha256=o5sz1iTc5jZqc9dq1ZEdW_-KSaVBnltppJjlYbls1Hk,3042
|
| 334 |
+
ultralytics/models/yolo/segment/val.py,sha256=CANSHjE1Pz4OJIEfPBCeCqT7XibZYgA_6-1lIr0vtsk,13374
|
| 335 |
+
ultralytics/models/yolo/semantic/__init__.py,sha256=yzL8Q1Ap2etFevc5YPsPv57zDFXldRM0X2vRjArFP7E,323
|
| 336 |
+
ultralytics/models/yolo/semantic/__pycache__/__init__.cpython-314.pyc,,
|
| 337 |
+
ultralytics/models/yolo/semantic/__pycache__/predict.cpython-314.pyc,,
|
| 338 |
+
ultralytics/models/yolo/semantic/__pycache__/train.cpython-314.pyc,,
|
| 339 |
+
ultralytics/models/yolo/semantic/__pycache__/val.cpython-314.pyc,,
|
| 340 |
+
ultralytics/models/yolo/semantic/predict.py,sha256=froSr3vLy1B4MpSzsTw_pezKAJhHJm5BR-99KDAfAbM,4133
|
| 341 |
+
ultralytics/models/yolo/semantic/train.py,sha256=Mw7U5xq-u1yq95IQCAT9guEuk-Uqub_chgwp0eqs3JU,6359
|
| 342 |
+
ultralytics/models/yolo/semantic/val.py,sha256=7xDs1eraL_BYzMn9qwKpdSnRy8mKwQ0xXAky9G-rtbs,8556
|
| 343 |
+
ultralytics/models/yolo/world/__init__.py,sha256=nlh8I6t8hMGz_vZg8QSlsUW1R-2eKvn9CGUoPPQEGhA,131
|
| 344 |
+
ultralytics/models/yolo/world/__pycache__/__init__.cpython-314.pyc,,
|
| 345 |
+
ultralytics/models/yolo/world/__pycache__/train.cpython-314.pyc,,
|
| 346 |
+
ultralytics/models/yolo/world/__pycache__/train_world.cpython-314.pyc,,
|
| 347 |
+
ultralytics/models/yolo/world/train.py,sha256=Q9cYDLkS3V-ijwA1nGNRyhzfix_ghILv7wsZoVNP4YQ,7960
|
| 348 |
+
ultralytics/models/yolo/world/train_world.py,sha256=yb0FVhOGAlhbc6-pqPPjEtFZpYdQyb4nwvfyskt8ZVE,9449
|
| 349 |
+
ultralytics/models/yolo/yoloe/__init__.py,sha256=zaZo1_ommaxNv7mD7xpdSomNF4s8mpOcCVTXspg0ncY,760
|
| 350 |
+
ultralytics/models/yolo/yoloe/__pycache__/__init__.cpython-314.pyc,,
|
| 351 |
+
ultralytics/models/yolo/yoloe/__pycache__/predict.cpython-314.pyc,,
|
| 352 |
+
ultralytics/models/yolo/yoloe/__pycache__/train.cpython-314.pyc,,
|
| 353 |
+
ultralytics/models/yolo/yoloe/__pycache__/train_seg.cpython-314.pyc,,
|
| 354 |
+
ultralytics/models/yolo/yoloe/__pycache__/val.cpython-314.pyc,,
|
| 355 |
+
ultralytics/models/yolo/yoloe/predict.py,sha256=LOoVkBxoUYIlZppnEVL8bJKSPoF1mhdk821ci6r74N4,7097
|
| 356 |
+
ultralytics/models/yolo/yoloe/train.py,sha256=9ac3_1F6LRgCTAt6AIVcoL5kKERcjgEMpPrMgw5nDTQ,12595
|
| 357 |
+
ultralytics/models/yolo/yoloe/train_seg.py,sha256=dZ3zxIOWIQ4myqrfWmQswr_r4VGtFirdMHPzHUMojg4,5097
|
| 358 |
+
ultralytics/models/yolo/yoloe/val.py,sha256=VWBIeuBeK0k_U6S1t-mDHxg-t9hokqmVAERAwHccunk,9713
|
| 359 |
+
ultralytics/nn/__init__.py,sha256=538LZPUKKvc3JCMgiQ4VLGqRN2ZAaVLFcQbeNNHFkEA,545
|
| 360 |
+
ultralytics/nn/__pycache__/__init__.cpython-314.pyc,,
|
| 361 |
+
ultralytics/nn/__pycache__/autobackend.cpython-314.pyc,,
|
| 362 |
+
ultralytics/nn/__pycache__/distill_model.cpython-314.pyc,,
|
| 363 |
+
ultralytics/nn/__pycache__/tasks.cpython-314.pyc,,
|
| 364 |
+
ultralytics/nn/__pycache__/text_model.cpython-314.pyc,,
|
| 365 |
+
ultralytics/nn/autobackend.py,sha256=46Ziy87SJzVV5Q1YzXNDTHGKaxbEJV9YaKICLaFhrBE,15549
|
| 366 |
+
ultralytics/nn/backends/__init__.py,sha256=BOZ1KMblYX5Pj0CP5piUuj30bU2ey5x_s6C22fnsTwM,1444
|
| 367 |
+
ultralytics/nn/backends/__pycache__/__init__.cpython-314.pyc,,
|
| 368 |
+
ultralytics/nn/backends/__pycache__/axelera.cpython-314.pyc,,
|
| 369 |
+
ultralytics/nn/backends/__pycache__/base.cpython-314.pyc,,
|
| 370 |
+
ultralytics/nn/backends/__pycache__/coreml.cpython-314.pyc,,
|
| 371 |
+
ultralytics/nn/backends/__pycache__/deepx.cpython-314.pyc,,
|
| 372 |
+
ultralytics/nn/backends/__pycache__/executorch.cpython-314.pyc,,
|
| 373 |
+
ultralytics/nn/backends/__pycache__/litert.cpython-314.pyc,,
|
| 374 |
+
ultralytics/nn/backends/__pycache__/mnn.cpython-314.pyc,,
|
| 375 |
+
ultralytics/nn/backends/__pycache__/ncnn.cpython-314.pyc,,
|
| 376 |
+
ultralytics/nn/backends/__pycache__/onnx.cpython-314.pyc,,
|
| 377 |
+
ultralytics/nn/backends/__pycache__/openvino.cpython-314.pyc,,
|
| 378 |
+
ultralytics/nn/backends/__pycache__/paddle.cpython-314.pyc,,
|
| 379 |
+
ultralytics/nn/backends/__pycache__/pytorch.cpython-314.pyc,,
|
| 380 |
+
ultralytics/nn/backends/__pycache__/qnn.cpython-314.pyc,,
|
| 381 |
+
ultralytics/nn/backends/__pycache__/rknn.cpython-314.pyc,,
|
| 382 |
+
ultralytics/nn/backends/__pycache__/tensorflow.cpython-314.pyc,,
|
| 383 |
+
ultralytics/nn/backends/__pycache__/tensorrt.cpython-314.pyc,,
|
| 384 |
+
ultralytics/nn/backends/__pycache__/triton.cpython-314.pyc,,
|
| 385 |
+
ultralytics/nn/backends/axelera.py,sha256=ICm5vWpmG0Kj9n7u8NdSk1OMYMbnmcKSIhWZKsqoqzw,1808
|
| 386 |
+
ultralytics/nn/backends/base.py,sha256=oKiRw45T5D_65bHmTQQPxVevChVZQimPLMJzMlC8hMQ,5610
|
| 387 |
+
ultralytics/nn/backends/coreml.py,sha256=K6MwsadI1pWGvOn1g2A-C0nchc4Uc7RbbJ2F6elpHk8,2914
|
| 388 |
+
ultralytics/nn/backends/deepx.py,sha256=M4Zfvbft2fSNLilO5Pr_nHwNf-jfNB5xlSa5_KvwCtQ,2795
|
| 389 |
+
ultralytics/nn/backends/executorch.py,sha256=-Wi2Rc1iw6y-919AzcbM6OiQz4wkXAo3fUHUw2lZdXs,1867
|
| 390 |
+
ultralytics/nn/backends/litert.py,sha256=7yRTtCVSpA-U5OM52FNkftLtviKwgJcljO6GinSVnUw,5472
|
| 391 |
+
ultralytics/nn/backends/mnn.py,sha256=8egQJ1oiYZIe4QXXCwPuEhsiIFwX45eB_Qiy5-lU8ho,1954
|
| 392 |
+
ultralytics/nn/backends/ncnn.py,sha256=9ra3OfcpGQbAqV0UO8VyGLZ3IGQVT1kx_q4_Q4ikT_o,2474
|
| 393 |
+
ultralytics/nn/backends/onnx.py,sha256=DTUupgde6zNPegexEKJomRkI2KX5irDEezRSptLbIHo,8892
|
| 394 |
+
ultralytics/nn/backends/openvino.py,sha256=G_DpC_roE9x2Er0lzWppipAPK94DW4IeT7D0XQE3e1Y,4330
|
| 395 |
+
ultralytics/nn/backends/paddle.py,sha256=AQGdiQk9SHZl0waOm_5B5wD46mOMsB1spYxPtrg6MRY,3020
|
| 396 |
+
ultralytics/nn/backends/pytorch.py,sha256=IqJQtsLXBN1oKO7N1ZiE_Qbq0LmKaW_cUVEOIuAR6q4,5512
|
| 397 |
+
ultralytics/nn/backends/qnn.py,sha256=QlPu7L3VaYQGBAdN-kX1WIMe0n7_Ok48aYUi4JpRMkA,3402
|
| 398 |
+
ultralytics/nn/backends/rknn.py,sha256=3rt5VxIAnX339fyieASo2WQZntoVe9L454SuKBZJ5Kw,2303
|
| 399 |
+
ultralytics/nn/backends/tensorflow.py,sha256=_AuU2xXUs-vxioKvj7FUjtd74iEpVoLo4nw5IorT_7o,7670
|
| 400 |
+
ultralytics/nn/backends/tensorrt.py,sha256=FKTIpxa-CkCzNsRmxuO8h9XhXKJqr9Q7O3ejLl3VutI,6128
|
| 401 |
+
ultralytics/nn/backends/triton.py,sha256=tfPmifMNxSlH95BPiqASGQd-6k_9URGHYE9HTlQpYFc,1463
|
| 402 |
+
ultralytics/nn/distill_model.py,sha256=iZufaosRy4RIb0qWRuYZFYeguwZBXiLuiL9J3YrK99Y,13607
|
| 403 |
+
ultralytics/nn/modules/__init__.py,sha256=hwd6eMhbHFCcf3WYzZhZ5byX7fjh47v0iB5BrBaaZOY,3366
|
| 404 |
+
ultralytics/nn/modules/__pycache__/__init__.cpython-314.pyc,,
|
| 405 |
+
ultralytics/nn/modules/__pycache__/activation.cpython-314.pyc,,
|
| 406 |
+
ultralytics/nn/modules/__pycache__/block.cpython-314.pyc,,
|
| 407 |
+
ultralytics/nn/modules/__pycache__/conv.cpython-314.pyc,,
|
| 408 |
+
ultralytics/nn/modules/__pycache__/head.cpython-314.pyc,,
|
| 409 |
+
ultralytics/nn/modules/__pycache__/transformer.cpython-314.pyc,,
|
| 410 |
+
ultralytics/nn/modules/__pycache__/utils.cpython-314.pyc,,
|
| 411 |
+
ultralytics/nn/modules/activation.py,sha256=J6n-CJKFK0YbhwcRDqm9zEJM9pSAEycj5quQss_3x6E,2219
|
| 412 |
+
ultralytics/nn/modules/block.py,sha256=IO2ga-etf-pp24FhyR9mgTcapq7bHcrhjbGgBHg-HL0,74891
|
| 413 |
+
ultralytics/nn/modules/conv.py,sha256=yALzbqFZbYkQ8rZR1Xh3tQpJYIV7l8u1og1Eodu6p3Q,21090
|
| 414 |
+
ultralytics/nn/modules/head.py,sha256=VwERbYaIGCesnh50Yt-qRMM5N71o4jMkdjRZaFcp4G8,82857
|
| 415 |
+
ultralytics/nn/modules/transformer.py,sha256=XWxpBPt3NyLrhYZj3k2GAXMdDvvac04vprpocHLGdIs,32713
|
| 416 |
+
ultralytics/nn/modules/utils.py,sha256=DBtRQkH8Xc7SU5j287Ow9cJHiKXl65MMUhggY0EyYRE,5665
|
| 417 |
+
ultralytics/nn/tasks.py,sha256=ZkwUIshXWgi20KTp8kbyeZ6UnHgp0WlC0PyJbp8tDiQ,85035
|
| 418 |
+
ultralytics/nn/text_model.py,sha256=Dd0UszKWIJd-hECeTQv7ROzrg_uejxz7b-LbOXP9IuA,15429
|
| 419 |
+
ultralytics/optim/__init__.py,sha256=Sl3Dx2eiaJd_u4VbmqcBqWWDF8FHnO5W0nBEL8_M_C4,130
|
| 420 |
+
ultralytics/optim/__pycache__/__init__.cpython-314.pyc,,
|
| 421 |
+
ultralytics/optim/__pycache__/muon.cpython-314.pyc,,
|
| 422 |
+
ultralytics/optim/muon.py,sha256=Iu-WCU6JFpbMuLsUwXxmmh4uIZaYlD8uKapV2ygSwe4,14241
|
| 423 |
+
ultralytics/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
|
| 424 |
+
ultralytics/solutions/__init__.py,sha256=Jj7OcRiYjHH-e104H4xTgjjR5W6aPB4mBRndbaSPmgU,1209
|
| 425 |
+
ultralytics/solutions/__pycache__/__init__.cpython-314.pyc,,
|
| 426 |
+
ultralytics/solutions/__pycache__/ai_gym.cpython-314.pyc,,
|
| 427 |
+
ultralytics/solutions/__pycache__/analytics.cpython-314.pyc,,
|
| 428 |
+
ultralytics/solutions/__pycache__/config.cpython-314.pyc,,
|
| 429 |
+
ultralytics/solutions/__pycache__/distance_calculation.cpython-314.pyc,,
|
| 430 |
+
ultralytics/solutions/__pycache__/heatmap.cpython-314.pyc,,
|
| 431 |
+
ultralytics/solutions/__pycache__/instance_segmentation.cpython-314.pyc,,
|
| 432 |
+
ultralytics/solutions/__pycache__/object_blurrer.cpython-314.pyc,,
|
| 433 |
+
ultralytics/solutions/__pycache__/object_counter.cpython-314.pyc,,
|
| 434 |
+
ultralytics/solutions/__pycache__/object_cropper.cpython-314.pyc,,
|
| 435 |
+
ultralytics/solutions/__pycache__/parking_management.cpython-314.pyc,,
|
| 436 |
+
ultralytics/solutions/__pycache__/queue_management.cpython-314.pyc,,
|
| 437 |
+
ultralytics/solutions/__pycache__/region_counter.cpython-314.pyc,,
|
| 438 |
+
ultralytics/solutions/__pycache__/security_alarm.cpython-314.pyc,,
|
| 439 |
+
ultralytics/solutions/__pycache__/similarity_search.cpython-314.pyc,,
|
| 440 |
+
ultralytics/solutions/__pycache__/solutions.cpython-314.pyc,,
|
| 441 |
+
ultralytics/solutions/__pycache__/speed_estimation.cpython-314.pyc,,
|
| 442 |
+
ultralytics/solutions/__pycache__/streamlit_inference.cpython-314.pyc,,
|
| 443 |
+
ultralytics/solutions/__pycache__/trackzone.cpython-314.pyc,,
|
| 444 |
+
ultralytics/solutions/__pycache__/vision_eye.cpython-314.pyc,,
|
| 445 |
+
ultralytics/solutions/ai_gym.py,sha256=MuoDqkaNm8Et8L9Ze3ryH31wvlM0wsT338HEH3iwdxk,5246
|
| 446 |
+
ultralytics/solutions/analytics.py,sha256=UpOwO15NVJhLzBhHLay6TCbUk8EWSUKAplQMb6KWIxI,12776
|
| 447 |
+
ultralytics/solutions/config.py,sha256=S-OF0oUnRKnO85v_Naj8FjTaoMhbR7tLY03Cm5PPKY4,5857
|
| 448 |
+
ultralytics/solutions/distance_calculation.py,sha256=RcpRDodEHAJUug9tobtQKt5_bySNA8NMSRiaL347Q1U,5891
|
| 449 |
+
ultralytics/solutions/heatmap.py,sha256=JdAbk338nWsR7j6KT_K1ts3lAhhO5BRtc6UAJhSVSNQ,5474
|
| 450 |
+
ultralytics/solutions/instance_segmentation.py,sha256=uP810WlECIRAbwgX4lXqV5l8vvLp7zvf0FG0RlaYjUE,3786
|
| 451 |
+
ultralytics/solutions/object_blurrer.py,sha256=EZrv3oU68kEaahAxlhk9cF5ZKFtoVaW8bDB4Css9xe0,3981
|
| 452 |
+
ultralytics/solutions/object_counter.py,sha256=omt2wsfj-E6G5wqODiQeNgaMBfecRaIHaTMJIxFDG1c,9359
|
| 453 |
+
ultralytics/solutions/object_cropper.py,sha256=9NLr4egGJNPX_2wtf4nQtRo1f_wZlpv7fgJt2Xkp0j0,3551
|
| 454 |
+
ultralytics/solutions/parking_management.py,sha256=Q0fEFKlv6dKKWuw_4jmWaeHQVXGppzuU7Vr_HqVYqHM,13770
|
| 455 |
+
ultralytics/solutions/queue_management.py,sha256=NtrGJmxKSlu5gsQw2vmj5E9fQWgIvGDE56IQ_PfMZ_Q,4393
|
| 456 |
+
ultralytics/solutions/region_counter.py,sha256=A6j9MBy8cguZabGP4jl06UQ5sOi2uxiEu6KyZprOD2k,6387
|
| 457 |
+
ultralytics/solutions/security_alarm.py,sha256=c7odhqvxXOSiLVk1W1deAzDyJ5bQukS_shHayVbl8gc,6273
|
| 458 |
+
ultralytics/solutions/similarity_search.py,sha256=ARkqa47WtSRgdcAeOvX64zLIWDcD3sFcec7O-u17CJ4,9907
|
| 459 |
+
ultralytics/solutions/solutions.py,sha256=m8wJ1UXOu2LlxjRJyycif6Tm0Ix5xgsI2WN_LCbUGuc,37600
|
| 460 |
+
ultralytics/solutions/speed_estimation.py,sha256=-DAhcWd8b4acfnbeUCSvqkUGRwL5ogkcphACQCkMV6o,5861
|
| 461 |
+
ultralytics/solutions/streamlit_inference.py,sha256=MyT3xItA0ZygnHEircYWg28hS0QV2jnU3LKTHPvNAo0,13352
|
| 462 |
+
ultralytics/solutions/templates/similarity-search.html,sha256=epX8XDLasOUx8ISPuKP9M0SRUjRcv_FE1r_EG3QpBtw,4177
|
| 463 |
+
ultralytics/solutions/trackzone.py,sha256=An9tNETx_5DY6xy2ZI8mcrNMXRzEezjm3HRseoO7R2A,3910
|
| 464 |
+
ultralytics/solutions/vision_eye.py,sha256=bSXmJ93DyLu4_CWgbF3GkHzh_VpiEmkK5vVJDPPGzI4,2982
|
| 465 |
+
ultralytics/trackers/__init__.py,sha256=-1tfYXBxpb-y2rYB7H5oD2R0bxbwEfKXIRdz8dzW5JI,482
|
| 466 |
+
ultralytics/trackers/__pycache__/__init__.cpython-314.pyc,,
|
| 467 |
+
ultralytics/trackers/__pycache__/basetrack.cpython-314.pyc,,
|
| 468 |
+
ultralytics/trackers/__pycache__/bot_sort.cpython-314.pyc,,
|
| 469 |
+
ultralytics/trackers/__pycache__/byte_tracker.cpython-314.pyc,,
|
| 470 |
+
ultralytics/trackers/__pycache__/deep_oc_sort.cpython-314.pyc,,
|
| 471 |
+
ultralytics/trackers/__pycache__/fast_tracker.cpython-314.pyc,,
|
| 472 |
+
ultralytics/trackers/__pycache__/oc_sort.cpython-314.pyc,,
|
| 473 |
+
ultralytics/trackers/__pycache__/track.cpython-314.pyc,,
|
| 474 |
+
ultralytics/trackers/__pycache__/track_tracker.cpython-314.pyc,,
|
| 475 |
+
ultralytics/trackers/basetrack.py,sha256=nvCUuaVP8vUskRi1vRovhLozGqVXJ39UGG3hFyjC9-g,3752
|
| 476 |
+
ultralytics/trackers/bot_sort.py,sha256=mzLPzJ8LUtAfTLz3bOJ535Bun2yyoQvfkrPc33sr6dk,9914
|
| 477 |
+
ultralytics/trackers/byte_tracker.py,sha256=AMfB_4sQdvyJNHBxUZrgsGowv84A3e2UgmYg4Gixko8,22774
|
| 478 |
+
ultralytics/trackers/deep_oc_sort.py,sha256=71i4eEbr9CBvVHPOnngsVBJoLiIiN4stdgXv6xNlNoA,12131
|
| 479 |
+
ultralytics/trackers/fast_tracker.py,sha256=p5WsgyQdu5YrjLHyNJ6pJmVOaK0cOMpsh0Of_T9XirY,17615
|
| 480 |
+
ultralytics/trackers/oc_sort.py,sha256=1WPlyaNvtf8V01-SuuBJOaLxd0uq_z4oetFfuX0G9lI,15425
|
| 481 |
+
ultralytics/trackers/track.py,sha256=G8hnMhWwXbC5TR4LiTDDT2JW15brP2MyBqtp0WL1k4M,5679
|
| 482 |
+
ultralytics/trackers/track_tracker.py,sha256=-00hMzXO11r82mCONiK3FN_-vSxV73dv6MJhlWdJtb0,26992
|
| 483 |
+
ultralytics/trackers/utils/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
|
| 484 |
+
ultralytics/trackers/utils/__pycache__/__init__.cpython-314.pyc,,
|
| 485 |
+
ultralytics/trackers/utils/__pycache__/gmc.cpython-314.pyc,,
|
| 486 |
+
ultralytics/trackers/utils/__pycache__/kalman_filter.cpython-314.pyc,,
|
| 487 |
+
ultralytics/trackers/utils/__pycache__/matching.cpython-314.pyc,,
|
| 488 |
+
ultralytics/trackers/utils/__pycache__/reid.cpython-314.pyc,,
|
| 489 |
+
ultralytics/trackers/utils/__pycache__/stracks.cpython-314.pyc,,
|
| 490 |
+
ultralytics/trackers/utils/gmc.py,sha256=nDqdj8Uy3mu-1u0_PswtAps8cigdsH6NpOIHT6U4sLA,13800
|
| 491 |
+
ultralytics/trackers/utils/kalman_filter.py,sha256=qajNBNN9aOHp-2aQctXcl5lw0Jee20zW0KRARgQ3P64,22597
|
| 492 |
+
ultralytics/trackers/utils/matching.py,sha256=DF3N3edc40PKliYnPj2V4uoGG89p8uCsDvUZrBqv_gc,7789
|
| 493 |
+
ultralytics/trackers/utils/reid.py,sha256=8gqRJBvLzYanFcmteoI5v6uAk8aauneZLiWtHkqHDfw,7440
|
| 494 |
+
ultralytics/trackers/utils/stracks.py,sha256=shlxdya-Qu7bXHEUKPfKUQUPitciKRpDzNmBlPWxzk4,7522
|
| 495 |
+
ultralytics/utils/__init__.py,sha256=wxeotoLBMD3hpnvjxtb8BZ8v9M34g_EJJRdBS3ukUHQ,57905
|
| 496 |
+
ultralytics/utils/__pycache__/__init__.cpython-314.pyc,,
|
| 497 |
+
ultralytics/utils/__pycache__/autobatch.cpython-314.pyc,,
|
| 498 |
+
ultralytics/utils/__pycache__/autodevice.cpython-314.pyc,,
|
| 499 |
+
ultralytics/utils/__pycache__/benchmarks.cpython-314.pyc,,
|
| 500 |
+
ultralytics/utils/__pycache__/checks.cpython-314.pyc,,
|
| 501 |
+
ultralytics/utils/__pycache__/cpu.cpython-314.pyc,,
|
| 502 |
+
ultralytics/utils/__pycache__/dist.cpython-314.pyc,,
|
| 503 |
+
ultralytics/utils/__pycache__/downloads.cpython-314.pyc,,
|
| 504 |
+
ultralytics/utils/__pycache__/errors.cpython-314.pyc,,
|
| 505 |
+
ultralytics/utils/__pycache__/events.cpython-314.pyc,,
|
| 506 |
+
ultralytics/utils/__pycache__/files.cpython-314.pyc,,
|
| 507 |
+
ultralytics/utils/__pycache__/git.cpython-314.pyc,,
|
| 508 |
+
ultralytics/utils/__pycache__/instance.cpython-314.pyc,,
|
| 509 |
+
ultralytics/utils/__pycache__/logger.cpython-314.pyc,,
|
| 510 |
+
ultralytics/utils/__pycache__/loss.cpython-314.pyc,,
|
| 511 |
+
ultralytics/utils/__pycache__/metrics.cpython-314.pyc,,
|
| 512 |
+
ultralytics/utils/__pycache__/nms.cpython-314.pyc,,
|
| 513 |
+
ultralytics/utils/__pycache__/ops.cpython-314.pyc,,
|
| 514 |
+
ultralytics/utils/__pycache__/patches.cpython-314.pyc,,
|
| 515 |
+
ultralytics/utils/__pycache__/plotting.cpython-314.pyc,,
|
| 516 |
+
ultralytics/utils/__pycache__/tal.cpython-314.pyc,,
|
| 517 |
+
ultralytics/utils/__pycache__/torch_utils.cpython-314.pyc,,
|
| 518 |
+
ultralytics/utils/__pycache__/tqdm.cpython-314.pyc,,
|
| 519 |
+
ultralytics/utils/__pycache__/triton.cpython-314.pyc,,
|
| 520 |
+
ultralytics/utils/__pycache__/tuner.cpython-314.pyc,,
|
| 521 |
+
ultralytics/utils/__pycache__/uploads.cpython-314.pyc,,
|
| 522 |
+
ultralytics/utils/autobatch.py,sha256=nwixv8vPmIXHPq_A8nF1cxWobdduk_5nDjmJTeVu7_8,5675
|
| 523 |
+
ultralytics/utils/autodevice.py,sha256=ZC-C_hfuHsyx3VcNrk85U4Rtyr0rWoSWhJlOuOkWHXQ,9006
|
| 524 |
+
ultralytics/utils/benchmarks.py,sha256=o1cC5TnGTrcPsMEVhMLDHG5l1C9iY4OuuFIT_DPi-G4,28409
|
| 525 |
+
ultralytics/utils/callbacks/__init__.py,sha256=hzL63Rce6VkZhP4Lcim9LKjadixaQG86nKqPhk7IkS0,242
|
| 526 |
+
ultralytics/utils/callbacks/__pycache__/__init__.cpython-314.pyc,,
|
| 527 |
+
ultralytics/utils/callbacks/__pycache__/base.cpython-314.pyc,,
|
| 528 |
+
ultralytics/utils/callbacks/__pycache__/clearml.cpython-314.pyc,,
|
| 529 |
+
ultralytics/utils/callbacks/__pycache__/comet.cpython-314.pyc,,
|
| 530 |
+
ultralytics/utils/callbacks/__pycache__/dvc.cpython-314.pyc,,
|
| 531 |
+
ultralytics/utils/callbacks/__pycache__/hub.cpython-314.pyc,,
|
| 532 |
+
ultralytics/utils/callbacks/__pycache__/mlflow.cpython-314.pyc,,
|
| 533 |
+
ultralytics/utils/callbacks/__pycache__/neptune.cpython-314.pyc,,
|
| 534 |
+
ultralytics/utils/callbacks/__pycache__/platform.cpython-314.pyc,,
|
| 535 |
+
ultralytics/utils/callbacks/__pycache__/raytune.cpython-314.pyc,,
|
| 536 |
+
ultralytics/utils/callbacks/__pycache__/tensorboard.cpython-314.pyc,,
|
| 537 |
+
ultralytics/utils/callbacks/__pycache__/wb.cpython-314.pyc,,
|
| 538 |
+
ultralytics/utils/callbacks/base.py,sha256=pqpFn3mZsLa8sXBkxabjHd6S098Ngf3-qpoyES29GPo,7468
|
| 539 |
+
ultralytics/utils/callbacks/clearml.py,sha256=AH7JwdZ8qtzlj11Q3MBzoUAzI6fYTb5drqAdpmxpSC8,5902
|
| 540 |
+
ultralytics/utils/callbacks/comet.py,sha256=NNfwkYRYKF4lgml931aXOZsOOilAIm1uvH34dlAyWLA,25146
|
| 541 |
+
ultralytics/utils/callbacks/dvc.py,sha256=DzT-Q314fap4g7rzXWeTfKw_5aTfnJIkqACAaFGXeg8,7494
|
| 542 |
+
ultralytics/utils/callbacks/hub.py,sha256=tOFYxZLOO7o3cJcrJvz3Y-RqzonXZAy3yZZBVexRsyo,4249
|
| 543 |
+
ultralytics/utils/callbacks/mlflow.py,sha256=5WaeD3Kfp7x3j7wJwb_kjPxs24IjLRhN3l9wVHc09-0,6744
|
| 544 |
+
ultralytics/utils/callbacks/neptune.py,sha256=_vt3cMwDHCR-LyT3KtRikGpj6AG11oQ-skUUUUdZ74o,4391
|
| 545 |
+
ultralytics/utils/callbacks/platform.py,sha256=PvGS7Ay8DU5yi3Lnq8wJ4rUY3aNaNI6HHigZufVR_7Q,20278
|
| 546 |
+
ultralytics/utils/callbacks/raytune.py,sha256=Y0dFyNZVRuFovSh7nkgUIHTQL3xIXOACElgHuYbg_5I,1278
|
| 547 |
+
ultralytics/utils/callbacks/tensorboard.py,sha256=K7b6KtC7rimfzqFu-NDZ_55Tbd7eC6TckqQdTNPuQ6U,5039
|
| 548 |
+
ultralytics/utils/callbacks/wb.py,sha256=PUdXGIFCRpTB3l0ElBWiOBa855Np6362PRWZBUtvgxE,8172
|
| 549 |
+
ultralytics/utils/checks.py,sha256=lLTAhhAzUXl5jnVyVgJ8LzmyI6HBSMF98LLocJ-2F-U,42574
|
| 550 |
+
ultralytics/utils/cpu.py,sha256=OksKOlX93AsbSsFuoYvLXRXgpkOibrZSwQyW6lipt4Q,3493
|
| 551 |
+
ultralytics/utils/dist.py,sha256=2kKQ5M6TGHFiTzYvkoAFk7EalpcJ7muZH980RqrMd4c,5003
|
| 552 |
+
ultralytics/utils/downloads.py,sha256=p3F3iGI0-L74E4HHbuvfgcNYI5OGJpQgFq-_xtx4FDo,25277
|
| 553 |
+
ultralytics/utils/errors.py,sha256=dUZcTWpbJJHqEuWHM6IbeoJJ4TzA_yHBP8E7tEEpBVs,1388
|
| 554 |
+
ultralytics/utils/events.py,sha256=kfu8j-JKG7dNn8AHNkylUn1g4dc_gyTb40gy2SWk_lk,4911
|
| 555 |
+
ultralytics/utils/export/__init__.py,sha256=zCgN-9-KWp18ouy5YsQ_7a81gKnosIerhc4S3o_2wxg,918
|
| 556 |
+
ultralytics/utils/export/__pycache__/__init__.cpython-314.pyc,,
|
| 557 |
+
ultralytics/utils/export/__pycache__/axelera.cpython-314.pyc,,
|
| 558 |
+
ultralytics/utils/export/__pycache__/coreml.cpython-314.pyc,,
|
| 559 |
+
ultralytics/utils/export/__pycache__/deepx.cpython-314.pyc,,
|
| 560 |
+
ultralytics/utils/export/__pycache__/engine.cpython-314.pyc,,
|
| 561 |
+
ultralytics/utils/export/__pycache__/executorch.cpython-314.pyc,,
|
| 562 |
+
ultralytics/utils/export/__pycache__/imx.cpython-314.pyc,,
|
| 563 |
+
ultralytics/utils/export/__pycache__/litert.cpython-314.pyc,,
|
| 564 |
+
ultralytics/utils/export/__pycache__/mnn.cpython-314.pyc,,
|
| 565 |
+
ultralytics/utils/export/__pycache__/ncnn.cpython-314.pyc,,
|
| 566 |
+
ultralytics/utils/export/__pycache__/onnx.cpython-314.pyc,,
|
| 567 |
+
ultralytics/utils/export/__pycache__/openvino.cpython-314.pyc,,
|
| 568 |
+
ultralytics/utils/export/__pycache__/paddle.cpython-314.pyc,,
|
| 569 |
+
ultralytics/utils/export/__pycache__/qnn.cpython-314.pyc,,
|
| 570 |
+
ultralytics/utils/export/__pycache__/rknn.cpython-314.pyc,,
|
| 571 |
+
ultralytics/utils/export/__pycache__/tensorflow.cpython-314.pyc,,
|
| 572 |
+
ultralytics/utils/export/__pycache__/torchscript.cpython-314.pyc,,
|
| 573 |
+
ultralytics/utils/export/axelera.py,sha256=TweXW60VBlzvcvilaWmqJzP5b54wZGwvRVn24v0jWYI,5545
|
| 574 |
+
ultralytics/utils/export/coreml.py,sha256=BDKtWWz4Nm9c3Bi0nx8yoCaozjHgAdkkb96Z8KgfqdU,11523
|
| 575 |
+
ultralytics/utils/export/deepx.py,sha256=gjvFL5Gm_dwKBjCsAQEqDSuUx25Vf9TLwxCvxtroa4o,2713
|
| 576 |
+
ultralytics/utils/export/engine.py,sha256=PX2bqXJM90FuHcL2812Uogdzk0wRCme2Pgiu9m9G29o,17931
|
| 577 |
+
ultralytics/utils/export/executorch.py,sha256=AcIAh0kLWLO2EN2DK2jw5lkRNyNBgbK68XMMDg1E-f4,2829
|
| 578 |
+
ultralytics/utils/export/imx.py,sha256=ag2sBHgV588RUHH7UKkU1OueKPM1gafOg5N5OiEJjwQ,15243
|
| 579 |
+
ultralytics/utils/export/litert.py,sha256=FrCiOJqvHvGfwikVocPKqd_m6Vij_ScJCLtjUGgE4Ns,8493
|
| 580 |
+
ultralytics/utils/export/mnn.py,sha256=bc-OoP3mFBP1L4oD5b1vP9FST0kLkXRMd2FMnWgTfBs,1892
|
| 581 |
+
ultralytics/utils/export/ncnn.py,sha256=ZbEIZpfe11H7oumoHKvR0WqOfjPJgw10EkIwZIX4Lv4,2457
|
| 582 |
+
ultralytics/utils/export/onnx.py,sha256=XCVK9dicgpjY0n6qphq8Wzj4GsiBRbMXA7iCThJHDxM,2118
|
| 583 |
+
ultralytics/utils/export/openvino.py,sha256=lPtPGa_PmA2znzUJLM1F-nWQTxY8cR271xuAkFn2mzo,2657
|
| 584 |
+
ultralytics/utils/export/paddle.py,sha256=UsclTfcKSGDnDcFGbepAgJvdpvhDKnhmWshMYy34nQw,1812
|
| 585 |
+
ultralytics/utils/export/qnn.py,sha256=xYcJ7T7hacJCMpUQD5d1Z1zzY64xdgBp3_PWzXcxiFk,8108
|
| 586 |
+
ultralytics/utils/export/rknn.py,sha256=NIIzNchOdow84KuGBRLasndAfDLfRToMrUG3voLvn7c,3434
|
| 587 |
+
ultralytics/utils/export/tensorflow.py,sha256=oejAd88q_qSPXHr5TvxUS_LA_YhuguUoe0yyfR3pDIo,12536
|
| 588 |
+
ultralytics/utils/export/torchscript.py,sha256=fQ9R26g5dmkmoo8U3Xef7gSL6iN3Ow6ub78KlNEHPO8,1627
|
| 589 |
+
ultralytics/utils/files.py,sha256=6Tb_-9a6PJ8HqzUH7GNhJSy05NOqrTjz1UyU_Virx6k,8194
|
| 590 |
+
ultralytics/utils/git.py,sha256=pAQMO940AN7k84dose1YxxP5Q9XnQ5QwFB1QVz9t6mI,6961
|
| 591 |
+
ultralytics/utils/instance.py,sha256=1J96OcekaHAzU6MmzhslQ4LIOsn2fjrvN4A1usf0VsE,19458
|
| 592 |
+
ultralytics/utils/logger.py,sha256=wkB8-qOs4vaCF7BFwFgNAXDClXZWWE36BQgV4o7n-uA,25796
|
| 593 |
+
ultralytics/utils/loss.py,sha256=8zHE_0O3PY7KcE28BSPPLi-O2Se8p4nMctKCucvApB8,64366
|
| 594 |
+
ultralytics/utils/metrics.py,sha256=mLGJb9Nz-tnUv7W9mj-Bp9YSXIwEksUMveaNwi_e7xk,82605
|
| 595 |
+
ultralytics/utils/nms.py,sha256=HqIpiuzBr1lFNm_kemp2TnyNUKPhav_Vwbucj4RuyNc,14376
|
| 596 |
+
ultralytics/utils/ops.py,sha256=LXtA4hxoQ3MTcP1tZhWIgglXgpDhusx2i2Ww-yACKGs,31385
|
| 597 |
+
ultralytics/utils/patches.py,sha256=aUAfRBneYVSzYozmF4bVV2HIik20vCEdOfL-cbVHlf4,9560
|
| 598 |
+
ultralytics/utils/plotting.py,sha256=ppbf5uGvMoHcz4MXQFIWp1x3ri4pMF_6QjkGISa0d2c,52948
|
| 599 |
+
ultralytics/utils/tal.py,sha256=dViDwOf6qlggWgMDDhEYcoKfpM5QdDi_RFtKejA1DD8,24671
|
| 600 |
+
ultralytics/utils/torch_utils.py,sha256=_2tOtMqugg0dKAiUmpH1WR1rjLYA9mZYWVJ210YSrYQ,42511
|
| 601 |
+
ultralytics/utils/tqdm.py,sha256=IFqrg15NUngaWJ6kXkcGWl47RhOmsvBNu1d5-TcM9Pg,16402
|
| 602 |
+
ultralytics/utils/triton.py,sha256=qfA4VJvGVUjUj-uuQzHc0eZ989-iZkdMmuqo4WnotU0,5215
|
| 603 |
+
ultralytics/utils/tuner.py,sha256=fHaIMz8gGwZEylSEb10sCHqVeoBCZ1BsxZtccPw19Hs,20840
|
| 604 |
+
ultralytics/utils/uploads.py,sha256=wLIIdzQmJYk3yyV-JC3GP2hxuEZ_ypNZeuh59QZuc7o,3809
|
.venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/REQUESTED
ADDED
|
File without changes
|
.venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: setuptools (82.0.1)
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py3-none-any
|
| 5 |
+
|
.venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/entry_points.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[console_scripts]
|
| 2 |
+
ultralytics = ultralytics.cfg:entrypoint
|
| 3 |
+
yolo = ultralytics.cfg:entrypoint
|
.venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/licenses/LICENSE
ADDED
|
@@ -0,0 +1,661 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
GNU AFFERO GENERAL PUBLIC LICENSE
|
| 2 |
+
Version 3, 19 November 2007
|
| 3 |
+
|
| 4 |
+
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
| 5 |
+
Everyone is permitted to copy and distribute verbatim copies
|
| 6 |
+
of this license document, but changing it is not allowed.
|
| 7 |
+
|
| 8 |
+
Preamble
|
| 9 |
+
|
| 10 |
+
The GNU Affero General Public License is a free, copyleft license for
|
| 11 |
+
software and other kinds of works, specifically designed to ensure
|
| 12 |
+
cooperation with the community in the case of network server software.
|
| 13 |
+
|
| 14 |
+
The licenses for most software and other practical works are designed
|
| 15 |
+
to take away your freedom to share and change the works. By contrast,
|
| 16 |
+
our General Public Licenses are intended to guarantee your freedom to
|
| 17 |
+
share and change all versions of a program--to make sure it remains free
|
| 18 |
+
software for all its users.
|
| 19 |
+
|
| 20 |
+
When we speak of free software, we are referring to freedom, not
|
| 21 |
+
price. Our General Public Licenses are designed to make sure that you
|
| 22 |
+
have the freedom to distribute copies of free software (and charge for
|
| 23 |
+
them if you wish), that you receive source code or can get it if you
|
| 24 |
+
want it, that you can change the software or use pieces of it in new
|
| 25 |
+
free programs, and that you know you can do these things.
|
| 26 |
+
|
| 27 |
+
Developers that use our General Public Licenses protect your rights
|
| 28 |
+
with two steps: (1) assert copyright on the software, and (2) offer
|
| 29 |
+
you this License which gives you legal permission to copy, distribute
|
| 30 |
+
and/or modify the software.
|
| 31 |
+
|
| 32 |
+
A secondary benefit of defending all users' freedom is that
|
| 33 |
+
improvements made in alternate versions of the program, if they
|
| 34 |
+
receive widespread use, become available for other developers to
|
| 35 |
+
incorporate. Many developers of free software are heartened and
|
| 36 |
+
encouraged by the resulting cooperation. However, in the case of
|
| 37 |
+
software used on network servers, this result may fail to come about.
|
| 38 |
+
The GNU General Public License permits making a modified version and
|
| 39 |
+
letting the public access it on a server without ever releasing its
|
| 40 |
+
source code to the public.
|
| 41 |
+
|
| 42 |
+
The GNU Affero General Public License is designed specifically to
|
| 43 |
+
ensure that, in such cases, the modified source code becomes available
|
| 44 |
+
to the community. It requires the operator of a network server to
|
| 45 |
+
provide the source code of the modified version running there to the
|
| 46 |
+
users of that server. Therefore, public use of a modified version, on
|
| 47 |
+
a publicly accessible server, gives the public access to the source
|
| 48 |
+
code of the modified version.
|
| 49 |
+
|
| 50 |
+
An older license, called the Affero General Public License and
|
| 51 |
+
published by Affero, was designed to accomplish similar goals. This is
|
| 52 |
+
a different license, not a version of the Affero GPL, but Affero has
|
| 53 |
+
released a new version of the Affero GPL which permits relicensing under
|
| 54 |
+
this license.
|
| 55 |
+
|
| 56 |
+
The precise terms and conditions for copying, distribution and
|
| 57 |
+
modification follow.
|
| 58 |
+
|
| 59 |
+
TERMS AND CONDITIONS
|
| 60 |
+
|
| 61 |
+
0. Definitions.
|
| 62 |
+
|
| 63 |
+
"This License" refers to version 3 of the GNU Affero General Public License.
|
| 64 |
+
|
| 65 |
+
"Copyright" also means copyright-like laws that apply to other kinds of
|
| 66 |
+
works, such as semiconductor masks.
|
| 67 |
+
|
| 68 |
+
"The Program" refers to any copyrightable work licensed under this
|
| 69 |
+
License. Each licensee is addressed as "you". "Licensees" and
|
| 70 |
+
"recipients" may be individuals or organizations.
|
| 71 |
+
|
| 72 |
+
To "modify" a work means to copy from or adapt all or part of the work
|
| 73 |
+
in a fashion requiring copyright permission, other than the making of an
|
| 74 |
+
exact copy. The resulting work is called a "modified version" of the
|
| 75 |
+
earlier work or a work "based on" the earlier work.
|
| 76 |
+
|
| 77 |
+
A "covered work" means either the unmodified Program or a work based
|
| 78 |
+
on the Program.
|
| 79 |
+
|
| 80 |
+
To "propagate" a work means to do anything with it that, without
|
| 81 |
+
permission, would make you directly or secondarily liable for
|
| 82 |
+
infringement under applicable copyright law, except executing it on a
|
| 83 |
+
computer or modifying a private copy. Propagation includes copying,
|
| 84 |
+
distribution (with or without modification), making available to the
|
| 85 |
+
public, and in some countries other activities as well.
|
| 86 |
+
|
| 87 |
+
To "convey" a work means any kind of propagation that enables other
|
| 88 |
+
parties to make or receive copies. Mere interaction with a user through
|
| 89 |
+
a computer network, with no transfer of a copy, is not conveying.
|
| 90 |
+
|
| 91 |
+
An interactive user interface displays "Appropriate Legal Notices"
|
| 92 |
+
to the extent that it includes a convenient and prominently visible
|
| 93 |
+
feature that (1) displays an appropriate copyright notice, and (2)
|
| 94 |
+
tells the user that there is no warranty for the work (except to the
|
| 95 |
+
extent that warranties are provided), that licensees may convey the
|
| 96 |
+
work under this License, and how to view a copy of this License. If
|
| 97 |
+
the interface presents a list of user commands or options, such as a
|
| 98 |
+
menu, a prominent item in the list meets this criterion.
|
| 99 |
+
|
| 100 |
+
1. Source Code.
|
| 101 |
+
|
| 102 |
+
The "source code" for a work means the preferred form of the work
|
| 103 |
+
for making modifications to it. "Object code" means any non-source
|
| 104 |
+
form of a work.
|
| 105 |
+
|
| 106 |
+
A "Standard Interface" means an interface that either is an official
|
| 107 |
+
standard defined by a recognized standards body, or, in the case of
|
| 108 |
+
interfaces specified for a particular programming language, one that
|
| 109 |
+
is widely used among developers working in that language.
|
| 110 |
+
|
| 111 |
+
The "System Libraries" of an executable work include anything, other
|
| 112 |
+
than the work as a whole, that (a) is included in the normal form of
|
| 113 |
+
packaging a Major Component, but which is not part of that Major
|
| 114 |
+
Component, and (b) serves only to enable use of the work with that
|
| 115 |
+
Major Component, or to implement a Standard Interface for which an
|
| 116 |
+
implementation is available to the public in source code form. A
|
| 117 |
+
"Major Component", in this context, means a major essential component
|
| 118 |
+
(kernel, window system, and so on) of the specific operating system
|
| 119 |
+
(if any) on which the executable work runs, or a compiler used to
|
| 120 |
+
produce the work, or an object code interpreter used to run it.
|
| 121 |
+
|
| 122 |
+
The "Corresponding Source" for a work in object code form means all
|
| 123 |
+
the source code needed to generate, install, and (for an executable
|
| 124 |
+
work) run the object code and to modify the work, including scripts to
|
| 125 |
+
control those activities. However, it does not include the work's
|
| 126 |
+
System Libraries, or general-purpose tools or generally available free
|
| 127 |
+
programs which are used unmodified in performing those activities but
|
| 128 |
+
which are not part of the work. For example, Corresponding Source
|
| 129 |
+
includes interface definition files associated with source files for
|
| 130 |
+
the work, and the source code for shared libraries and dynamically
|
| 131 |
+
linked subprograms that the work is specifically designed to require,
|
| 132 |
+
such as by intimate data communication or control flow between those
|
| 133 |
+
subprograms and other parts of the work.
|
| 134 |
+
|
| 135 |
+
The Corresponding Source need not include anything that users
|
| 136 |
+
can regenerate automatically from other parts of the Corresponding
|
| 137 |
+
Source.
|
| 138 |
+
|
| 139 |
+
The Corresponding Source for a work in source code form is that
|
| 140 |
+
same work.
|
| 141 |
+
|
| 142 |
+
2. Basic Permissions.
|
| 143 |
+
|
| 144 |
+
All rights granted under this License are granted for the term of
|
| 145 |
+
copyright on the Program, and are irrevocable provided the stated
|
| 146 |
+
conditions are met. This License explicitly affirms your unlimited
|
| 147 |
+
permission to run the unmodified Program. The output from running a
|
| 148 |
+
covered work is covered by this License only if the output, given its
|
| 149 |
+
content, constitutes a covered work. This License acknowledges your
|
| 150 |
+
rights of fair use or other equivalent, as provided by copyright law.
|
| 151 |
+
|
| 152 |
+
You may make, run and propagate covered works that you do not
|
| 153 |
+
convey, without conditions so long as your license otherwise remains
|
| 154 |
+
in force. You may convey covered works to others for the sole purpose
|
| 155 |
+
of having them make modifications exclusively for you, or provide you
|
| 156 |
+
with facilities for running those works, provided that you comply with
|
| 157 |
+
the terms of this License in conveying all material for which you do
|
| 158 |
+
not control copyright. Those thus making or running the covered works
|
| 159 |
+
for you must do so exclusively on your behalf, under your direction
|
| 160 |
+
and control, on terms that prohibit them from making any copies of
|
| 161 |
+
your copyrighted material outside their relationship with you.
|
| 162 |
+
|
| 163 |
+
Conveying under any other circumstances is permitted solely under
|
| 164 |
+
the conditions stated below. Sublicensing is not allowed; section 10
|
| 165 |
+
makes it unnecessary.
|
| 166 |
+
|
| 167 |
+
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
| 168 |
+
|
| 169 |
+
No covered work shall be deemed part of an effective technological
|
| 170 |
+
measure under any applicable law fulfilling obligations under article
|
| 171 |
+
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
| 172 |
+
similar laws prohibiting or restricting circumvention of such
|
| 173 |
+
measures.
|
| 174 |
+
|
| 175 |
+
When you convey a covered work, you waive any legal power to forbid
|
| 176 |
+
circumvention of technological measures to the extent such circumvention
|
| 177 |
+
is effected by exercising rights under this License with respect to
|
| 178 |
+
the covered work, and you disclaim any intention to limit operation or
|
| 179 |
+
modification of the work as a means of enforcing, against the work's
|
| 180 |
+
users, your or third parties' legal rights to forbid circumvention of
|
| 181 |
+
technological measures.
|
| 182 |
+
|
| 183 |
+
4. Conveying Verbatim Copies.
|
| 184 |
+
|
| 185 |
+
You may convey verbatim copies of the Program's source code as you
|
| 186 |
+
receive it, in any medium, provided that you conspicuously and
|
| 187 |
+
appropriately publish on each copy an appropriate copyright notice;
|
| 188 |
+
keep intact all notices stating that this License and any
|
| 189 |
+
non-permissive terms added in accord with section 7 apply to the code;
|
| 190 |
+
keep intact all notices of the absence of any warranty; and give all
|
| 191 |
+
recipients a copy of this License along with the Program.
|
| 192 |
+
|
| 193 |
+
You may charge any price or no price for each copy that you convey,
|
| 194 |
+
and you may offer support or warranty protection for a fee.
|
| 195 |
+
|
| 196 |
+
5. Conveying Modified Source Versions.
|
| 197 |
+
|
| 198 |
+
You may convey a work based on the Program, or the modifications to
|
| 199 |
+
produce it from the Program, in the form of source code under the
|
| 200 |
+
terms of section 4, provided that you also meet all of these conditions:
|
| 201 |
+
|
| 202 |
+
a) The work must carry prominent notices stating that you modified
|
| 203 |
+
it, and giving a relevant date.
|
| 204 |
+
|
| 205 |
+
b) The work must carry prominent notices stating that it is
|
| 206 |
+
released under this License and any conditions added under section
|
| 207 |
+
7. This requirement modifies the requirement in section 4 to
|
| 208 |
+
"keep intact all notices".
|
| 209 |
+
|
| 210 |
+
c) You must license the entire work, as a whole, under this
|
| 211 |
+
License to anyone who comes into possession of a copy. This
|
| 212 |
+
License will therefore apply, along with any applicable section 7
|
| 213 |
+
additional terms, to the whole of the work, and all its parts,
|
| 214 |
+
regardless of how they are packaged. This License gives no
|
| 215 |
+
permission to license the work in any other way, but it does not
|
| 216 |
+
invalidate such permission if you have separately received it.
|
| 217 |
+
|
| 218 |
+
d) If the work has interactive user interfaces, each must display
|
| 219 |
+
Appropriate Legal Notices; however, if the Program has interactive
|
| 220 |
+
interfaces that do not display Appropriate Legal Notices, your
|
| 221 |
+
work need not make them do so.
|
| 222 |
+
|
| 223 |
+
A compilation of a covered work with other separate and independent
|
| 224 |
+
works, which are not by their nature extensions of the covered work,
|
| 225 |
+
and which are not combined with it such as to form a larger program,
|
| 226 |
+
in or on a volume of a storage or distribution medium, is called an
|
| 227 |
+
"aggregate" if the compilation and its resulting copyright are not
|
| 228 |
+
used to limit the access or legal rights of the compilation's users
|
| 229 |
+
beyond what the individual works permit. Inclusion of a covered work
|
| 230 |
+
in an aggregate does not cause this License to apply to the other
|
| 231 |
+
parts of the aggregate.
|
| 232 |
+
|
| 233 |
+
6. Conveying Non-Source Forms.
|
| 234 |
+
|
| 235 |
+
You may convey a covered work in object code form under the terms
|
| 236 |
+
of sections 4 and 5, provided that you also convey the
|
| 237 |
+
machine-readable Corresponding Source under the terms of this License,
|
| 238 |
+
in one of these ways:
|
| 239 |
+
|
| 240 |
+
a) Convey the object code in, or embodied in, a physical product
|
| 241 |
+
(including a physical distribution medium), accompanied by the
|
| 242 |
+
Corresponding Source fixed on a durable physical medium
|
| 243 |
+
customarily used for software interchange.
|
| 244 |
+
|
| 245 |
+
b) Convey the object code in, or embodied in, a physical product
|
| 246 |
+
(including a physical distribution medium), accompanied by a
|
| 247 |
+
written offer, valid for at least three years and valid for as
|
| 248 |
+
long as you offer spare parts or customer support for that product
|
| 249 |
+
model, to give anyone who possesses the object code either (1) a
|
| 250 |
+
copy of the Corresponding Source for all the software in the
|
| 251 |
+
product that is covered by this License, on a durable physical
|
| 252 |
+
medium customarily used for software interchange, for a price no
|
| 253 |
+
more than your reasonable cost of physically performing this
|
| 254 |
+
conveying of source, or (2) access to copy the
|
| 255 |
+
Corresponding Source from a network server at no charge.
|
| 256 |
+
|
| 257 |
+
c) Convey individual copies of the object code with a copy of the
|
| 258 |
+
written offer to provide the Corresponding Source. This
|
| 259 |
+
alternative is allowed only occasionally and noncommercially, and
|
| 260 |
+
only if you received the object code with such an offer, in accord
|
| 261 |
+
with subsection 6b.
|
| 262 |
+
|
| 263 |
+
d) Convey the object code by offering access from a designated
|
| 264 |
+
place (gratis or for a charge), and offer equivalent access to the
|
| 265 |
+
Corresponding Source in the same way through the same place at no
|
| 266 |
+
further charge. You need not require recipients to copy the
|
| 267 |
+
Corresponding Source along with the object code. If the place to
|
| 268 |
+
copy the object code is a network server, the Corresponding Source
|
| 269 |
+
may be on a different server (operated by you or a third party)
|
| 270 |
+
that supports equivalent copying facilities, provided you maintain
|
| 271 |
+
clear directions next to the object code saying where to find the
|
| 272 |
+
Corresponding Source. Regardless of what server hosts the
|
| 273 |
+
Corresponding Source, you remain obligated to ensure that it is
|
| 274 |
+
available for as long as needed to satisfy these requirements.
|
| 275 |
+
|
| 276 |
+
e) Convey the object code using peer-to-peer transmission, provided
|
| 277 |
+
you inform other peers where the object code and Corresponding
|
| 278 |
+
Source of the work are being offered to the general public at no
|
| 279 |
+
charge under subsection 6d.
|
| 280 |
+
|
| 281 |
+
A separable portion of the object code, whose source code is excluded
|
| 282 |
+
from the Corresponding Source as a System Library, need not be
|
| 283 |
+
included in conveying the object code work.
|
| 284 |
+
|
| 285 |
+
A "User Product" is either (1) a "consumer product", which means any
|
| 286 |
+
tangible personal property which is normally used for personal, family,
|
| 287 |
+
or household purposes, or (2) anything designed or sold for incorporation
|
| 288 |
+
into a dwelling. In determining whether a product is a consumer product,
|
| 289 |
+
doubtful cases shall be resolved in favor of coverage. For a particular
|
| 290 |
+
product received by a particular user, "normally used" refers to a
|
| 291 |
+
typical or common use of that class of product, regardless of the status
|
| 292 |
+
of the particular user or of the way in which the particular user
|
| 293 |
+
actually uses, or expects or is expected to use, the product. A product
|
| 294 |
+
is a consumer product regardless of whether the product has substantial
|
| 295 |
+
commercial, industrial or non-consumer uses, unless such uses represent
|
| 296 |
+
the only significant mode of use of the product.
|
| 297 |
+
|
| 298 |
+
"Installation Information" for a User Product means any methods,
|
| 299 |
+
procedures, authorization keys, or other information required to install
|
| 300 |
+
and execute modified versions of a covered work in that User Product from
|
| 301 |
+
a modified version of its Corresponding Source. The information must
|
| 302 |
+
suffice to ensure that the continued functioning of the modified object
|
| 303 |
+
code is in no case prevented or interfered with solely because
|
| 304 |
+
modification has been made.
|
| 305 |
+
|
| 306 |
+
If you convey an object code work under this section in, or with, or
|
| 307 |
+
specifically for use in, a User Product, and the conveying occurs as
|
| 308 |
+
part of a transaction in which the right of possession and use of the
|
| 309 |
+
User Product is transferred to the recipient in perpetuity or for a
|
| 310 |
+
fixed term (regardless of how the transaction is characterized), the
|
| 311 |
+
Corresponding Source conveyed under this section must be accompanied
|
| 312 |
+
by the Installation Information. But this requirement does not apply
|
| 313 |
+
if neither you nor any third party retains the ability to install
|
| 314 |
+
modified object code on the User Product (for example, the work has
|
| 315 |
+
been installed in ROM).
|
| 316 |
+
|
| 317 |
+
The requirement to provide Installation Information does not include a
|
| 318 |
+
requirement to continue to provide support service, warranty, or updates
|
| 319 |
+
for a work that has been modified or installed by the recipient, or for
|
| 320 |
+
the User Product in which it has been modified or installed. Access to a
|
| 321 |
+
network may be denied when the modification itself materially and
|
| 322 |
+
adversely affects the operation of the network or violates the rules and
|
| 323 |
+
protocols for communication across the network.
|
| 324 |
+
|
| 325 |
+
Corresponding Source conveyed, and Installation Information provided,
|
| 326 |
+
in accord with this section must be in a format that is publicly
|
| 327 |
+
documented (and with an implementation available to the public in
|
| 328 |
+
source code form), and must require no special password or key for
|
| 329 |
+
unpacking, reading or copying.
|
| 330 |
+
|
| 331 |
+
7. Additional Terms.
|
| 332 |
+
|
| 333 |
+
"Additional permissions" are terms that supplement the terms of this
|
| 334 |
+
License by making exceptions from one or more of its conditions.
|
| 335 |
+
Additional permissions that are applicable to the entire Program shall
|
| 336 |
+
be treated as though they were included in this License, to the extent
|
| 337 |
+
that they are valid under applicable law. If additional permissions
|
| 338 |
+
apply only to part of the Program, that part may be used separately
|
| 339 |
+
under those permissions, but the entire Program remains governed by
|
| 340 |
+
this License without regard to the additional permissions.
|
| 341 |
+
|
| 342 |
+
When you convey a copy of a covered work, you may at your option
|
| 343 |
+
remove any additional permissions from that copy, or from any part of
|
| 344 |
+
it. (Additional permissions may be written to require their own
|
| 345 |
+
removal in certain cases when you modify the work.) You may place
|
| 346 |
+
additional permissions on material, added by you to a covered work,
|
| 347 |
+
for which you have or can give appropriate copyright permission.
|
| 348 |
+
|
| 349 |
+
Notwithstanding any other provision of this License, for material you
|
| 350 |
+
add to a covered work, you may (if authorized by the copyright holders of
|
| 351 |
+
that material) supplement the terms of this License with terms:
|
| 352 |
+
|
| 353 |
+
a) Disclaiming warranty or limiting liability differently from the
|
| 354 |
+
terms of sections 15 and 16 of this License; or
|
| 355 |
+
|
| 356 |
+
b) Requiring preservation of specified reasonable legal notices or
|
| 357 |
+
author attributions in that material or in the Appropriate Legal
|
| 358 |
+
Notices displayed by works containing it; or
|
| 359 |
+
|
| 360 |
+
c) Prohibiting misrepresentation of the origin of that material, or
|
| 361 |
+
requiring that modified versions of such material be marked in
|
| 362 |
+
reasonable ways as different from the original version; or
|
| 363 |
+
|
| 364 |
+
d) Limiting the use for publicity purposes of names of licensors or
|
| 365 |
+
authors of the material; or
|
| 366 |
+
|
| 367 |
+
e) Declining to grant rights under trademark law for use of some
|
| 368 |
+
trade names, trademarks, or service marks; or
|
| 369 |
+
|
| 370 |
+
f) Requiring indemnification of licensors and authors of that
|
| 371 |
+
material by anyone who conveys the material (or modified versions of
|
| 372 |
+
it) with contractual assumptions of liability to the recipient, for
|
| 373 |
+
any liability that these contractual assumptions directly impose on
|
| 374 |
+
those licensors and authors.
|
| 375 |
+
|
| 376 |
+
All other non-permissive additional terms are considered "further
|
| 377 |
+
restrictions" within the meaning of section 10. If the Program as you
|
| 378 |
+
received it, or any part of it, contains a notice stating that it is
|
| 379 |
+
governed by this License along with a term that is a further
|
| 380 |
+
restriction, you may remove that term. If a license document contains
|
| 381 |
+
a further restriction but permits relicensing or conveying under this
|
| 382 |
+
License, you may add to a covered work material governed by the terms
|
| 383 |
+
of that license document, provided that the further restriction does
|
| 384 |
+
not survive such relicensing or conveying.
|
| 385 |
+
|
| 386 |
+
If you add terms to a covered work in accord with this section, you
|
| 387 |
+
must place, in the relevant source files, a statement of the
|
| 388 |
+
additional terms that apply to those files, or a notice indicating
|
| 389 |
+
where to find the applicable terms.
|
| 390 |
+
|
| 391 |
+
Additional terms, permissive or non-permissive, may be stated in the
|
| 392 |
+
form of a separately written license, or stated as exceptions;
|
| 393 |
+
the above requirements apply either way.
|
| 394 |
+
|
| 395 |
+
8. Termination.
|
| 396 |
+
|
| 397 |
+
You may not propagate or modify a covered work except as expressly
|
| 398 |
+
provided under this License. Any attempt otherwise to propagate or
|
| 399 |
+
modify it is void, and will automatically terminate your rights under
|
| 400 |
+
this License (including any patent licenses granted under the third
|
| 401 |
+
paragraph of section 11).
|
| 402 |
+
|
| 403 |
+
However, if you cease all violation of this License, then your
|
| 404 |
+
license from a particular copyright holder is reinstated (a)
|
| 405 |
+
provisionally, unless and until the copyright holder explicitly and
|
| 406 |
+
finally terminates your license, and (b) permanently, if the copyright
|
| 407 |
+
holder fails to notify you of the violation by some reasonable means
|
| 408 |
+
prior to 60 days after the cessation.
|
| 409 |
+
|
| 410 |
+
Moreover, your license from a particular copyright holder is
|
| 411 |
+
reinstated permanently if the copyright holder notifies you of the
|
| 412 |
+
violation by some reasonable means, this is the first time you have
|
| 413 |
+
received notice of violation of this License (for any work) from that
|
| 414 |
+
copyright holder, and you cure the violation prior to 30 days after
|
| 415 |
+
your receipt of the notice.
|
| 416 |
+
|
| 417 |
+
Termination of your rights under this section does not terminate the
|
| 418 |
+
licenses of parties who have received copies or rights from you under
|
| 419 |
+
this License. If your rights have been terminated and not permanently
|
| 420 |
+
reinstated, you do not qualify to receive new licenses for the same
|
| 421 |
+
material under section 10.
|
| 422 |
+
|
| 423 |
+
9. Acceptance Not Required for Having Copies.
|
| 424 |
+
|
| 425 |
+
You are not required to accept this License in order to receive or
|
| 426 |
+
run a copy of the Program. Ancillary propagation of a covered work
|
| 427 |
+
occurring solely as a consequence of using peer-to-peer transmission
|
| 428 |
+
to receive a copy likewise does not require acceptance. However,
|
| 429 |
+
nothing other than this License grants you permission to propagate or
|
| 430 |
+
modify any covered work. These actions infringe copyright if you do
|
| 431 |
+
not accept this License. Therefore, by modifying or propagating a
|
| 432 |
+
covered work, you indicate your acceptance of this License to do so.
|
| 433 |
+
|
| 434 |
+
10. Automatic Licensing of Downstream Recipients.
|
| 435 |
+
|
| 436 |
+
Each time you convey a covered work, the recipient automatically
|
| 437 |
+
receives a license from the original licensors, to run, modify and
|
| 438 |
+
propagate that work, subject to this License. You are not responsible
|
| 439 |
+
for enforcing compliance by third parties with this License.
|
| 440 |
+
|
| 441 |
+
An "entity transaction" is a transaction transferring control of an
|
| 442 |
+
organization, or substantially all assets of one, or subdividing an
|
| 443 |
+
organization, or merging organizations. If propagation of a covered
|
| 444 |
+
work results from an entity transaction, each party to that
|
| 445 |
+
transaction who receives a copy of the work also receives whatever
|
| 446 |
+
licenses to the work the party's predecessor in interest had or could
|
| 447 |
+
give under the previous paragraph, plus a right to possession of the
|
| 448 |
+
Corresponding Source of the work from the predecessor in interest, if
|
| 449 |
+
the predecessor has it or can get it with reasonable efforts.
|
| 450 |
+
|
| 451 |
+
You may not impose any further restrictions on the exercise of the
|
| 452 |
+
rights granted or affirmed under this License. For example, you may
|
| 453 |
+
not impose a license fee, royalty, or other charge for exercise of
|
| 454 |
+
rights granted under this License, and you may not initiate litigation
|
| 455 |
+
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
| 456 |
+
any patent claim is infringed by making, using, selling, offering for
|
| 457 |
+
sale, or importing the Program or any portion of it.
|
| 458 |
+
|
| 459 |
+
11. Patents.
|
| 460 |
+
|
| 461 |
+
A "contributor" is a copyright holder who authorizes use under this
|
| 462 |
+
License of the Program or a work on which the Program is based. The
|
| 463 |
+
work thus licensed is called the contributor's "contributor version".
|
| 464 |
+
|
| 465 |
+
A contributor's "essential patent claims" are all patent claims
|
| 466 |
+
owned or controlled by the contributor, whether already acquired or
|
| 467 |
+
hereafter acquired, that would be infringed by some manner, permitted
|
| 468 |
+
by this License, of making, using, or selling its contributor version,
|
| 469 |
+
but do not include claims that would be infringed only as a
|
| 470 |
+
consequence of further modification of the contributor version. For
|
| 471 |
+
purposes of this definition, "control" includes the right to grant
|
| 472 |
+
patent sublicenses in a manner consistent with the requirements of
|
| 473 |
+
this License.
|
| 474 |
+
|
| 475 |
+
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
| 476 |
+
patent license under the contributor's essential patent claims, to
|
| 477 |
+
make, use, sell, offer for sale, import and otherwise run, modify and
|
| 478 |
+
propagate the contents of its contributor version.
|
| 479 |
+
|
| 480 |
+
In the following three paragraphs, a "patent license" is any express
|
| 481 |
+
agreement or commitment, however denominated, not to enforce a patent
|
| 482 |
+
(such as an express permission to practice a patent or covenant not to
|
| 483 |
+
sue for patent infringement). To "grant" such a patent license to a
|
| 484 |
+
party means to make such an agreement or commitment not to enforce a
|
| 485 |
+
patent against the party.
|
| 486 |
+
|
| 487 |
+
If you convey a covered work, knowingly relying on a patent license,
|
| 488 |
+
and the Corresponding Source of the work is not available for anyone
|
| 489 |
+
to copy, free of charge and under the terms of this License, through a
|
| 490 |
+
publicly available network server or other readily accessible means,
|
| 491 |
+
then you must either (1) cause the Corresponding Source to be so
|
| 492 |
+
available, or (2) arrange to deprive yourself of the benefit of the
|
| 493 |
+
patent license for this particular work, or (3) arrange, in a manner
|
| 494 |
+
consistent with the requirements of this License, to extend the patent
|
| 495 |
+
license to downstream recipients. "Knowingly relying" means you have
|
| 496 |
+
actual knowledge that, but for the patent license, your conveying the
|
| 497 |
+
covered work in a country, or your recipient's use of the covered work
|
| 498 |
+
in a country, would infringe one or more identifiable patents in that
|
| 499 |
+
country that you have reason to believe are valid.
|
| 500 |
+
|
| 501 |
+
If, pursuant to or in connection with a single transaction or
|
| 502 |
+
arrangement, you convey, or propagate by procuring conveyance of, a
|
| 503 |
+
covered work, and grant a patent license to some of the parties
|
| 504 |
+
receiving the covered work authorizing them to use, propagate, modify
|
| 505 |
+
or convey a specific copy of the covered work, then the patent license
|
| 506 |
+
you grant is automatically extended to all recipients of the covered
|
| 507 |
+
work and works based on it.
|
| 508 |
+
|
| 509 |
+
A patent license is "discriminatory" if it does not include within
|
| 510 |
+
the scope of its coverage, prohibits the exercise of, or is
|
| 511 |
+
conditioned on the non-exercise of one or more of the rights that are
|
| 512 |
+
specifically granted under this License. You may not convey a covered
|
| 513 |
+
work if you are a party to an arrangement with a third party that is
|
| 514 |
+
in the business of distributing software, under which you make payment
|
| 515 |
+
to the third party based on the extent of your activity of conveying
|
| 516 |
+
the work, and under which the third party grants, to any of the
|
| 517 |
+
parties who would receive the covered work from you, a discriminatory
|
| 518 |
+
patent license (a) in connection with copies of the covered work
|
| 519 |
+
conveyed by you (or copies made from those copies), or (b) primarily
|
| 520 |
+
for and in connection with specific products or compilations that
|
| 521 |
+
contain the covered work, unless you entered into that arrangement,
|
| 522 |
+
or that patent license was granted, prior to 28 March 2007.
|
| 523 |
+
|
| 524 |
+
Nothing in this License shall be construed as excluding or limiting
|
| 525 |
+
any implied license or other defenses to infringement that may
|
| 526 |
+
otherwise be available to you under applicable patent law.
|
| 527 |
+
|
| 528 |
+
12. No Surrender of Others' Freedom.
|
| 529 |
+
|
| 530 |
+
If conditions are imposed on you (whether by court order, agreement or
|
| 531 |
+
otherwise) that contradict the conditions of this License, they do not
|
| 532 |
+
excuse you from the conditions of this License. If you cannot convey a
|
| 533 |
+
covered work so as to satisfy simultaneously your obligations under this
|
| 534 |
+
License and any other pertinent obligations, then as a consequence you may
|
| 535 |
+
not convey it at all. For example, if you agree to terms that obligate you
|
| 536 |
+
to collect a royalty for further conveying from those to whom you convey
|
| 537 |
+
the Program, the only way you could satisfy both those terms and this
|
| 538 |
+
License would be to refrain entirely from conveying the Program.
|
| 539 |
+
|
| 540 |
+
13. Remote Network Interaction; Use with the GNU General Public License.
|
| 541 |
+
|
| 542 |
+
Notwithstanding any other provision of this License, if you modify the
|
| 543 |
+
Program, your modified version must prominently offer all users
|
| 544 |
+
interacting with it remotely through a computer network (if your version
|
| 545 |
+
supports such interaction) an opportunity to receive the Corresponding
|
| 546 |
+
Source of your version by providing access to the Corresponding Source
|
| 547 |
+
from a network server at no charge, through some standard or customary
|
| 548 |
+
means of facilitating copying of software. This Corresponding Source
|
| 549 |
+
shall include the Corresponding Source for any work covered by version 3
|
| 550 |
+
of the GNU General Public License that is incorporated pursuant to the
|
| 551 |
+
following paragraph.
|
| 552 |
+
|
| 553 |
+
Notwithstanding any other provision of this License, you have
|
| 554 |
+
permission to link or combine any covered work with a work licensed
|
| 555 |
+
under version 3 of the GNU General Public License into a single
|
| 556 |
+
combined work, and to convey the resulting work. The terms of this
|
| 557 |
+
License will continue to apply to the part which is the covered work,
|
| 558 |
+
but the work with which it is combined will remain governed by version
|
| 559 |
+
3 of the GNU General Public License.
|
| 560 |
+
|
| 561 |
+
14. Revised Versions of this License.
|
| 562 |
+
|
| 563 |
+
The Free Software Foundation may publish revised and/or new versions of
|
| 564 |
+
the GNU Affero General Public License from time to time. Such new versions
|
| 565 |
+
will be similar in spirit to the present version, but may differ in detail to
|
| 566 |
+
address new problems or concerns.
|
| 567 |
+
|
| 568 |
+
Each version is given a distinguishing version number. If the
|
| 569 |
+
Program specifies that a certain numbered version of the GNU Affero General
|
| 570 |
+
Public License "or any later version" applies to it, you have the
|
| 571 |
+
option of following the terms and conditions either of that numbered
|
| 572 |
+
version or of any later version published by the Free Software
|
| 573 |
+
Foundation. If the Program does not specify a version number of the
|
| 574 |
+
GNU Affero General Public License, you may choose any version ever published
|
| 575 |
+
by the Free Software Foundation.
|
| 576 |
+
|
| 577 |
+
If the Program specifies that a proxy can decide which future
|
| 578 |
+
versions of the GNU Affero General Public License can be used, that proxy's
|
| 579 |
+
public statement of acceptance of a version permanently authorizes you
|
| 580 |
+
to choose that version for the Program.
|
| 581 |
+
|
| 582 |
+
Later license versions may give you additional or different
|
| 583 |
+
permissions. However, no additional obligations are imposed on any
|
| 584 |
+
author or copyright holder as a result of your choosing to follow a
|
| 585 |
+
later version.
|
| 586 |
+
|
| 587 |
+
15. Disclaimer of Warranty.
|
| 588 |
+
|
| 589 |
+
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
| 590 |
+
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
| 591 |
+
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
| 592 |
+
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
| 593 |
+
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
| 594 |
+
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
| 595 |
+
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
| 596 |
+
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
| 597 |
+
|
| 598 |
+
16. Limitation of Liability.
|
| 599 |
+
|
| 600 |
+
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
| 601 |
+
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
| 602 |
+
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
| 603 |
+
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
| 604 |
+
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
| 605 |
+
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
| 606 |
+
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
| 607 |
+
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
| 608 |
+
SUCH DAMAGES.
|
| 609 |
+
|
| 610 |
+
17. Interpretation of Sections 15 and 16.
|
| 611 |
+
|
| 612 |
+
If the disclaimer of warranty and limitation of liability provided
|
| 613 |
+
above cannot be given local legal effect according to their terms,
|
| 614 |
+
reviewing courts shall apply local law that most closely approximates
|
| 615 |
+
an absolute waiver of all civil liability in connection with the
|
| 616 |
+
Program, unless a warranty or assumption of liability accompanies a
|
| 617 |
+
copy of the Program in return for a fee.
|
| 618 |
+
|
| 619 |
+
END OF TERMS AND CONDITIONS
|
| 620 |
+
|
| 621 |
+
How to Apply These Terms to Your New Programs
|
| 622 |
+
|
| 623 |
+
If you develop a new program, and you want it to be of the greatest
|
| 624 |
+
possible use to the public, the best way to achieve this is to make it
|
| 625 |
+
free software which everyone can redistribute and change under these terms.
|
| 626 |
+
|
| 627 |
+
To do so, attach the following notices to the program. It is safest
|
| 628 |
+
to attach them to the start of each source file to most effectively
|
| 629 |
+
state the exclusion of warranty; and each file should have at least
|
| 630 |
+
the "copyright" line and a pointer to where the full notice is found.
|
| 631 |
+
|
| 632 |
+
<one line to give the program's name and a brief idea of what it does.>
|
| 633 |
+
Copyright (C) <year> <name of author>
|
| 634 |
+
|
| 635 |
+
This program is free software: you can redistribute it and/or modify
|
| 636 |
+
it under the terms of the GNU Affero General Public License as published by
|
| 637 |
+
the Free Software Foundation, either version 3 of the License, or
|
| 638 |
+
(at your option) any later version.
|
| 639 |
+
|
| 640 |
+
This program is distributed in the hope that it will be useful,
|
| 641 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 642 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 643 |
+
GNU Affero General Public License for more details.
|
| 644 |
+
|
| 645 |
+
You should have received a copy of the GNU Affero General Public License
|
| 646 |
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
| 647 |
+
|
| 648 |
+
Also add information on how to contact you by electronic and paper mail.
|
| 649 |
+
|
| 650 |
+
If your software can interact with users remotely through a computer
|
| 651 |
+
network, you should also make sure that it provides a way for users to
|
| 652 |
+
get its source. For example, if your program is a web application, its
|
| 653 |
+
interface could display a "Source" link that leads users to an archive
|
| 654 |
+
of the code. There are many ways you could offer source, and different
|
| 655 |
+
solutions will be better for different programs; see section 13 for the
|
| 656 |
+
specific requirements.
|
| 657 |
+
|
| 658 |
+
You should also get your employer (if you work as a programmer) or school,
|
| 659 |
+
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
| 660 |
+
For more information on this, and how to apply and follow the GNU AGPL, see
|
| 661 |
+
<https://www.gnu.org/licenses/>.
|
.venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
ultralytics
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/files.cpython-314.pyc
ADDED
|
Binary file (12.3 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/git.cpython-314.pyc
ADDED
|
Binary file (13.2 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/instance.cpython-314.pyc
ADDED
|
Binary file (30.1 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/logger.cpython-314.pyc
ADDED
|
Binary file (34.2 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/loss.cpython-314.pyc
ADDED
|
Binary file (92.5 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/metrics.cpython-314.pyc
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:40456bcab958ad592b9e08bba95131a6e23467fb19429af5a01d99e971c7a032
|
| 3 |
+
size 125188
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/nms.cpython-314.pyc
ADDED
|
Binary file (17.2 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/ops.cpython-314.pyc
ADDED
|
Binary file (44.1 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/patches.cpython-314.pyc
ADDED
|
Binary file (12.4 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/plotting.cpython-314.pyc
ADDED
|
Binary file (75.5 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tal.cpython-314.pyc
ADDED
|
Binary file (30.2 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/torch_utils.cpython-314.pyc
ADDED
|
Binary file (61 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tqdm.cpython-314.pyc
ADDED
|
Binary file (25 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/triton.cpython-314.pyc
ADDED
|
Binary file (7.37 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tuner.cpython-314.pyc
ADDED
|
Binary file (24.3 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/uploads.cpython-314.pyc
ADDED
|
Binary file (6.25 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/autobatch.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
"""Functions for estimating the best YOLO batch size to use a fraction of the available CUDA memory in PyTorch."""
|
| 3 |
+
|
| 4 |
+
from __future__ import annotations
|
| 5 |
+
|
| 6 |
+
import os
|
| 7 |
+
from copy import deepcopy
|
| 8 |
+
|
| 9 |
+
import numpy as np
|
| 10 |
+
import torch
|
| 11 |
+
|
| 12 |
+
from ultralytics.utils import DEFAULT_CFG, LOGGER, colorstr
|
| 13 |
+
from ultralytics.utils.torch_utils import autocast, profile_ops
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def check_train_batch_size(
|
| 17 |
+
model: torch.nn.Module,
|
| 18 |
+
imgsz: int = 640,
|
| 19 |
+
amp: bool = True,
|
| 20 |
+
batch: int | float = -1,
|
| 21 |
+
max_num_obj: int = 1,
|
| 22 |
+
dataset_size: int = 0,
|
| 23 |
+
) -> int:
|
| 24 |
+
"""Compute optimal YOLO training batch size using the autobatch() function.
|
| 25 |
+
|
| 26 |
+
Args:
|
| 27 |
+
model (torch.nn.Module): YOLO model to check batch size for.
|
| 28 |
+
imgsz (int, optional): Image size used for training.
|
| 29 |
+
amp (bool, optional): Use automatic mixed precision if True.
|
| 30 |
+
batch (int | float, optional): Fraction of GPU memory to use. If -1, use default.
|
| 31 |
+
max_num_obj (int, optional): The maximum number of objects from dataset.
|
| 32 |
+
dataset_size (int, optional): Total number of training images. If > 0, batch size will not exceed this value.
|
| 33 |
+
|
| 34 |
+
Returns:
|
| 35 |
+
(int): Optimal batch size computed using the autobatch() function.
|
| 36 |
+
|
| 37 |
+
Notes:
|
| 38 |
+
If 0.0 < batch < 1.0, it's used as the fraction of GPU memory to use.
|
| 39 |
+
Otherwise, a default fraction of 0.6 is used.
|
| 40 |
+
"""
|
| 41 |
+
with autocast(enabled=amp):
|
| 42 |
+
return autobatch(
|
| 43 |
+
deepcopy(model).train(),
|
| 44 |
+
imgsz,
|
| 45 |
+
fraction=batch if 0.0 < batch < 1.0 else 0.6,
|
| 46 |
+
max_num_obj=max_num_obj,
|
| 47 |
+
dataset_size=dataset_size,
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def autobatch(
|
| 52 |
+
model: torch.nn.Module,
|
| 53 |
+
imgsz: int = 640,
|
| 54 |
+
fraction: float = 0.60,
|
| 55 |
+
batch_size: int = DEFAULT_CFG.batch,
|
| 56 |
+
max_num_obj: int = 1,
|
| 57 |
+
dataset_size: int = 0,
|
| 58 |
+
) -> int:
|
| 59 |
+
"""Automatically estimate the best YOLO batch size to use a fraction of the available CUDA memory.
|
| 60 |
+
|
| 61 |
+
Args:
|
| 62 |
+
model (torch.nn.Module): YOLO model to compute batch size for.
|
| 63 |
+
imgsz (int, optional): The image size used as input for the YOLO model.
|
| 64 |
+
fraction (float, optional): The fraction of available CUDA memory to use.
|
| 65 |
+
batch_size (int, optional): The default batch size to use if an error is detected.
|
| 66 |
+
max_num_obj (int, optional): The maximum number of objects from dataset.
|
| 67 |
+
dataset_size (int, optional): Total number of training images. If > 0, batch size will not exceed this value.
|
| 68 |
+
|
| 69 |
+
Returns:
|
| 70 |
+
(int): The optimal batch size.
|
| 71 |
+
"""
|
| 72 |
+
# Check device
|
| 73 |
+
prefix = colorstr("AutoBatch: ")
|
| 74 |
+
LOGGER.info(f"{prefix}Computing optimal batch size for imgsz={imgsz} at {fraction * 100}% CUDA memory utilization.")
|
| 75 |
+
device = next(model.parameters()).device # get model device
|
| 76 |
+
if device.type in {"cpu", "mps"}:
|
| 77 |
+
LOGGER.warning(f"{prefix}intended for CUDA devices, using default batch-size {batch_size}")
|
| 78 |
+
return batch_size
|
| 79 |
+
if torch.backends.cudnn.benchmark:
|
| 80 |
+
LOGGER.warning(f"{prefix}Requires torch.backends.cudnn.benchmark=False, using default batch-size {batch_size}")
|
| 81 |
+
return batch_size
|
| 82 |
+
|
| 83 |
+
# Inspect CUDA memory
|
| 84 |
+
gb = 1 << 30 # bytes to GiB (1024 ** 3)
|
| 85 |
+
d = f"CUDA:{os.getenv('CUDA_VISIBLE_DEVICES', '0').strip()[0]}" # 'CUDA:0'
|
| 86 |
+
properties = torch.cuda.get_device_properties(device) # device properties
|
| 87 |
+
t = properties.total_memory / gb # GiB total
|
| 88 |
+
r = torch.cuda.memory_reserved(device) / gb # GiB reserved
|
| 89 |
+
a = torch.cuda.memory_allocated(device) / gb # GiB allocated
|
| 90 |
+
f = t - (r + a) # GiB free
|
| 91 |
+
LOGGER.info(f"{prefix}{d} ({properties.name}) {t:.2f}G total, {r:.2f}G reserved, {a:.2f}G allocated, {f:.2f}G free")
|
| 92 |
+
|
| 93 |
+
# Profile batch sizes
|
| 94 |
+
batch_sizes = [1, 2, 4, 8, 16] if t < 16 else [1, 2, 4, 8, 16, 32, 64]
|
| 95 |
+
if dataset_size > 0:
|
| 96 |
+
batch_sizes = [b for b in batch_sizes if b <= dataset_size]
|
| 97 |
+
ch = model.yaml.get("channels", 3)
|
| 98 |
+
try:
|
| 99 |
+
img = [torch.empty(b, ch, imgsz, imgsz) for b in batch_sizes]
|
| 100 |
+
results = profile_ops(img, model, n=1, device=device, max_num_obj=max_num_obj)
|
| 101 |
+
|
| 102 |
+
# Fit a solution
|
| 103 |
+
xy = [
|
| 104 |
+
[x, y[2]]
|
| 105 |
+
for i, (x, y) in enumerate(zip(batch_sizes, results))
|
| 106 |
+
if y # valid result
|
| 107 |
+
and isinstance(y[2], (int, float)) # is numeric
|
| 108 |
+
and 0 < y[2] < t # between 0 and GPU limit
|
| 109 |
+
and (i == 0 or not results[i - 1] or y[2] > results[i - 1][2]) # first item or increasing memory
|
| 110 |
+
]
|
| 111 |
+
fit_x, fit_y = zip(*xy) if xy else ([], [])
|
| 112 |
+
p = np.polyfit(fit_x, fit_y, deg=1) # first-degree (linear) polynomial fit
|
| 113 |
+
b = int((round(f * fraction) - p[1]) / p[0]) # y intercept (optimal batch size)
|
| 114 |
+
if None in results: # some sizes failed
|
| 115 |
+
i = results.index(None) # first fail index
|
| 116 |
+
if b >= batch_sizes[i]: # y intercept above failure point
|
| 117 |
+
b = batch_sizes[max(i - 1, 0)] # select prior safe point
|
| 118 |
+
if b < 1 or b > 1024: # b outside of safe range
|
| 119 |
+
LOGGER.warning(f"{prefix}batch={b} outside safe range, using default batch-size {batch_size}.")
|
| 120 |
+
b = batch_size
|
| 121 |
+
if dataset_size > 0:
|
| 122 |
+
b = min(b, dataset_size)
|
| 123 |
+
|
| 124 |
+
fraction = (np.polyval(p, b) + r + a) / t # predicted fraction
|
| 125 |
+
LOGGER.info(f"{prefix}Using batch-size {b} for {d} {t * fraction:.2f}G/{t:.2f}G ({fraction * 100:.0f}%) ✅")
|
| 126 |
+
return b
|
| 127 |
+
except Exception as e:
|
| 128 |
+
LOGGER.warning(f"{prefix}error detected: {e}, using default batch-size {batch_size}.")
|
| 129 |
+
return batch_size
|
| 130 |
+
finally:
|
| 131 |
+
torch.cuda.empty_cache()
|
.venv/lib/python3.14/site-packages/ultralytics/utils/autodevice.py
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import random
|
| 6 |
+
from typing import Any
|
| 7 |
+
|
| 8 |
+
from ultralytics.utils import LOGGER
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class GPUInfo:
|
| 12 |
+
"""Manages NVIDIA GPU information via pynvml with robust error handling.
|
| 13 |
+
|
| 14 |
+
Provides methods to query detailed GPU statistics (utilization, memory, temp, power) and select the most idle GPUs
|
| 15 |
+
based on configurable criteria. It safely handles the absence or initialization failure of the pynvml library by
|
| 16 |
+
logging warnings and disabling related features, preventing application crashes.
|
| 17 |
+
|
| 18 |
+
Includes fallback logic using `torch.cuda` for basic device counting if NVML is unavailable during GPU
|
| 19 |
+
selection. Manages NVML initialization and shutdown internally.
|
| 20 |
+
|
| 21 |
+
Attributes:
|
| 22 |
+
pynvml (module | None): The `pynvml` module if successfully imported and initialized, otherwise `None`.
|
| 23 |
+
nvml_available (bool): Indicates if `pynvml` is ready for use. True if `nvmlInit()` succeeded, False otherwise.
|
| 24 |
+
gpu_stats (list[dict[str, Any]]): A list of dictionaries, each holding stats for one GPU, populated on
|
| 25 |
+
initialization and by `refresh_stats()`. Keys include: 'index', 'name', 'utilization' (%), 'memory_used' (MiB),
|
| 26 |
+
'memory_total' (MiB), 'memory_free' (MiB), 'temperature' (C), 'power_draw' (W), 'power_limit' (W or 'N/A').
|
| 27 |
+
Empty if NVML is unavailable or queries fail.
|
| 28 |
+
|
| 29 |
+
Methods:
|
| 30 |
+
refresh_stats: Refresh the internal gpu_stats list by querying NVML.
|
| 31 |
+
print_status: Print GPU status in a compact table format using current stats.
|
| 32 |
+
select_idle_gpu: Select the most idle GPUs based on utilization and free memory.
|
| 33 |
+
shutdown: Shut down NVML if it was initialized.
|
| 34 |
+
|
| 35 |
+
Examples:
|
| 36 |
+
Initialize GPUInfo and print status
|
| 37 |
+
>>> gpu_info = GPUInfo()
|
| 38 |
+
>>> gpu_info.print_status()
|
| 39 |
+
|
| 40 |
+
Select idle GPUs with minimum memory requirements
|
| 41 |
+
>>> selected = gpu_info.select_idle_gpu(count=2, min_memory_fraction=0.2)
|
| 42 |
+
>>> print(f"Selected GPU indices: {selected}")
|
| 43 |
+
"""
|
| 44 |
+
|
| 45 |
+
def __init__(self):
|
| 46 |
+
"""Initialize GPUInfo, attempting to import and initialize pynvml."""
|
| 47 |
+
self.pynvml: Any | None = None
|
| 48 |
+
self.nvml_available: bool = False
|
| 49 |
+
self.gpu_stats: list[dict[str, Any]] = []
|
| 50 |
+
|
| 51 |
+
try:
|
| 52 |
+
import pynvml # scoped as slow import
|
| 53 |
+
|
| 54 |
+
self.pynvml = pynvml
|
| 55 |
+
pynvml.nvmlInit()
|
| 56 |
+
self.nvml_available = True
|
| 57 |
+
self.refresh_stats()
|
| 58 |
+
except Exception as e:
|
| 59 |
+
LOGGER.warning(f"Failed to initialize pynvml, GPU stats disabled: {e}")
|
| 60 |
+
|
| 61 |
+
def __del__(self):
|
| 62 |
+
"""Ensure NVML is shut down when the object is garbage collected."""
|
| 63 |
+
self.shutdown()
|
| 64 |
+
|
| 65 |
+
def shutdown(self):
|
| 66 |
+
"""Shut down NVML if it was initialized."""
|
| 67 |
+
if self.nvml_available and self.pynvml:
|
| 68 |
+
try:
|
| 69 |
+
self.pynvml.nvmlShutdown()
|
| 70 |
+
except Exception:
|
| 71 |
+
pass
|
| 72 |
+
self.nvml_available = False
|
| 73 |
+
|
| 74 |
+
def refresh_stats(self):
|
| 75 |
+
"""Refresh the internal gpu_stats list by querying NVML."""
|
| 76 |
+
self.gpu_stats = []
|
| 77 |
+
if not self.nvml_available or not self.pynvml:
|
| 78 |
+
return
|
| 79 |
+
|
| 80 |
+
try:
|
| 81 |
+
device_count = self.pynvml.nvmlDeviceGetCount()
|
| 82 |
+
self.gpu_stats.extend(self._get_device_stats(i) for i in range(device_count))
|
| 83 |
+
except Exception as e:
|
| 84 |
+
LOGGER.warning(f"Error during device query: {e}")
|
| 85 |
+
self.gpu_stats = []
|
| 86 |
+
|
| 87 |
+
def _get_device_stats(self, index: int) -> dict[str, Any]:
|
| 88 |
+
"""Get stats for a single GPU device."""
|
| 89 |
+
handle = self.pynvml.nvmlDeviceGetHandleByIndex(index)
|
| 90 |
+
memory = self.pynvml.nvmlDeviceGetMemoryInfo(handle)
|
| 91 |
+
util = self.pynvml.nvmlDeviceGetUtilizationRates(handle)
|
| 92 |
+
|
| 93 |
+
def safe_get(func, *args, default=-1, divisor=1):
|
| 94 |
+
try:
|
| 95 |
+
val = func(*args)
|
| 96 |
+
return val // divisor if divisor != 1 and isinstance(val, (int, float)) else val
|
| 97 |
+
except Exception:
|
| 98 |
+
return default
|
| 99 |
+
|
| 100 |
+
temp_type = getattr(self.pynvml, "NVML_TEMPERATURE_GPU", -1)
|
| 101 |
+
|
| 102 |
+
return {
|
| 103 |
+
"index": index,
|
| 104 |
+
"name": self.pynvml.nvmlDeviceGetName(handle),
|
| 105 |
+
"utilization": util.gpu if util else -1,
|
| 106 |
+
"memory_used": memory.used >> 20 if memory else -1, # Convert bytes to MiB
|
| 107 |
+
"memory_total": memory.total >> 20 if memory else -1,
|
| 108 |
+
"memory_free": memory.free >> 20 if memory else -1,
|
| 109 |
+
"temperature": safe_get(self.pynvml.nvmlDeviceGetTemperature, handle, temp_type),
|
| 110 |
+
"power_draw": safe_get(self.pynvml.nvmlDeviceGetPowerUsage, handle, divisor=1000), # Convert mW to W
|
| 111 |
+
"power_limit": safe_get(self.pynvml.nvmlDeviceGetEnforcedPowerLimit, handle, divisor=1000),
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
def print_status(self):
|
| 115 |
+
"""Print GPU status in a compact table format using current stats."""
|
| 116 |
+
self.refresh_stats()
|
| 117 |
+
if not self.gpu_stats:
|
| 118 |
+
LOGGER.warning("No GPU stats available.")
|
| 119 |
+
return
|
| 120 |
+
|
| 121 |
+
stats = self.gpu_stats
|
| 122 |
+
name_len = max(len(gpu.get("name", "N/A")) for gpu in stats)
|
| 123 |
+
hdr = f"{'Idx':<3} {'Name':<{name_len}} {'Util':>6} {'Mem (MiB)':>15} {'Temp':>5} {'Pwr (W)':>10}"
|
| 124 |
+
LOGGER.info(f"\n--- GPU Status ---\n{hdr}\n{'-' * len(hdr)}")
|
| 125 |
+
|
| 126 |
+
for gpu in stats:
|
| 127 |
+
u = f"{gpu['utilization']:>5}%" if gpu["utilization"] >= 0 else " N/A "
|
| 128 |
+
m = f"{gpu['memory_used']:>6}/{gpu['memory_total']:<6}" if gpu["memory_used"] >= 0 else " N/A / N/A "
|
| 129 |
+
t = f"{gpu['temperature']}C" if gpu["temperature"] >= 0 else " N/A "
|
| 130 |
+
p = f"{gpu['power_draw']:>3}/{gpu['power_limit']:<3}" if gpu["power_draw"] >= 0 else " N/A "
|
| 131 |
+
|
| 132 |
+
LOGGER.info(f"{gpu.get('index'):<3d} {gpu.get('name', 'N/A'):<{name_len}} {u:>6} {m:>15} {t:>5} {p:>10}")
|
| 133 |
+
|
| 134 |
+
LOGGER.info(f"{'-' * len(hdr)}\n")
|
| 135 |
+
|
| 136 |
+
def select_idle_gpu(
|
| 137 |
+
self, count: int = 1, min_memory_fraction: float = 0, min_util_fraction: float = 0
|
| 138 |
+
) -> list[int]:
|
| 139 |
+
"""Select the most idle GPUs based on utilization and free memory.
|
| 140 |
+
|
| 141 |
+
Args:
|
| 142 |
+
count (int): The number of idle GPUs to select.
|
| 143 |
+
min_memory_fraction (float): Minimum free memory required as a fraction of total memory.
|
| 144 |
+
min_util_fraction (float): Minimum free utilization rate required from 0.0 - 1.0.
|
| 145 |
+
|
| 146 |
+
Returns:
|
| 147 |
+
(list[int]): Indices of the selected GPUs, sorted by idleness (lowest utilization first).
|
| 148 |
+
|
| 149 |
+
Notes:
|
| 150 |
+
Returns fewer than 'count' if not enough qualify or exist.
|
| 151 |
+
Returns empty list if NVML stats are unavailable or no GPUs meet the criteria.
|
| 152 |
+
"""
|
| 153 |
+
assert min_memory_fraction <= 1.0, f"min_memory_fraction must be <= 1.0, got {min_memory_fraction}"
|
| 154 |
+
assert min_util_fraction <= 1.0, f"min_util_fraction must be <= 1.0, got {min_util_fraction}"
|
| 155 |
+
criteria = (
|
| 156 |
+
f"free memory >= {min_memory_fraction * 100:.1f}% and free utilization >= {min_util_fraction * 100:.1f}%"
|
| 157 |
+
)
|
| 158 |
+
LOGGER.info(f"Searching for {count} idle GPUs with {criteria}...")
|
| 159 |
+
|
| 160 |
+
if count <= 0:
|
| 161 |
+
return []
|
| 162 |
+
|
| 163 |
+
self.refresh_stats()
|
| 164 |
+
if not self.gpu_stats:
|
| 165 |
+
LOGGER.warning("NVML stats unavailable.")
|
| 166 |
+
return []
|
| 167 |
+
|
| 168 |
+
# Filter and sort eligible GPUs
|
| 169 |
+
eligible_gpus = [
|
| 170 |
+
gpu
|
| 171 |
+
for gpu in self.gpu_stats
|
| 172 |
+
if gpu.get("memory_free", 0) / gpu.get("memory_total", 1) >= min_memory_fraction
|
| 173 |
+
and (100 - gpu.get("utilization", 100)) >= min_util_fraction * 100
|
| 174 |
+
]
|
| 175 |
+
# Random tiebreaker prevents race conditions when multiple processes start simultaneously
|
| 176 |
+
# and all GPUs appear equally idle (same utilization and free memory)
|
| 177 |
+
eligible_gpus.sort(key=lambda x: (x.get("utilization", 101), -x.get("memory_free", 0), random.random()))
|
| 178 |
+
|
| 179 |
+
# Select top 'count' indices
|
| 180 |
+
selected = [gpu["index"] for gpu in eligible_gpus[:count]]
|
| 181 |
+
|
| 182 |
+
if selected:
|
| 183 |
+
if len(selected) < count:
|
| 184 |
+
LOGGER.warning(f"Requested {count} GPUs but only {len(selected)} met the idle criteria.")
|
| 185 |
+
LOGGER.info(f"Selected idle CUDA devices {selected}")
|
| 186 |
+
else:
|
| 187 |
+
LOGGER.warning(f"No GPUs met criteria ({criteria}).")
|
| 188 |
+
|
| 189 |
+
return selected
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
if __name__ == "__main__":
|
| 193 |
+
required_free_mem_fraction = 0.2 # Require 20% free VRAM
|
| 194 |
+
required_free_util_fraction = 0.2 # Require 20% free utilization
|
| 195 |
+
num_gpus_to_select = 1
|
| 196 |
+
|
| 197 |
+
gpu_info = GPUInfo()
|
| 198 |
+
gpu_info.print_status()
|
| 199 |
+
|
| 200 |
+
if selected := gpu_info.select_idle_gpu(
|
| 201 |
+
count=num_gpus_to_select,
|
| 202 |
+
min_memory_fraction=required_free_mem_fraction,
|
| 203 |
+
min_util_fraction=required_free_util_fraction,
|
| 204 |
+
):
|
| 205 |
+
print(f"\n==> Using selected GPU indices: {selected}")
|
| 206 |
+
devices = [f"cuda:{idx}" for idx in selected]
|
| 207 |
+
print(f" Target devices: {devices}")
|
.venv/lib/python3.14/site-packages/ultralytics/utils/benchmarks.py
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
"""
|
| 3 |
+
Benchmark YOLO model formats for speed and accuracy.
|
| 4 |
+
|
| 5 |
+
Usage:
|
| 6 |
+
from ultralytics.utils.benchmarks import ProfileModels, benchmark
|
| 7 |
+
ProfileModels(['yolo26n.yaml', 'yolov8s.yaml']).run()
|
| 8 |
+
benchmark(model='yolo26n.pt', imgsz=160)
|
| 9 |
+
|
| 10 |
+
Format | `format=argument` | Model
|
| 11 |
+
--- | --- | ---
|
| 12 |
+
PyTorch | - | yolo26n.pt
|
| 13 |
+
TorchScript | `torchscript` | yolo26n.torchscript
|
| 14 |
+
ONNX | `onnx` | yolo26n.onnx
|
| 15 |
+
OpenVINO | `openvino` | yolo26n_openvino_model/
|
| 16 |
+
TensorRT | `engine` | yolo26n.engine
|
| 17 |
+
CoreML | `coreml` | yolo26n.mlpackage
|
| 18 |
+
TensorFlow SavedModel | `saved_model` | yolo26n_saved_model/
|
| 19 |
+
TensorFlow GraphDef | `pb` | yolo26n.pb
|
| 20 |
+
TensorFlow Edge TPU | `edgetpu` | yolo26n_edgetpu.tflite
|
| 21 |
+
PaddlePaddle | `paddle` | yolo26n_paddle_model/
|
| 22 |
+
MNN | `mnn` | yolo26n.mnn
|
| 23 |
+
NCNN | `ncnn` | yolo26n_ncnn_model/
|
| 24 |
+
IMX | `imx` | yolo26n_imx_model/
|
| 25 |
+
RKNN | `rknn` | yolo26n_rknn_model/
|
| 26 |
+
ExecuTorch | `executorch` | yolo26n_executorch_model/
|
| 27 |
+
Axelera AI | `axelera` | yolo26n_axelera_model/
|
| 28 |
+
"""
|
| 29 |
+
|
| 30 |
+
from __future__ import annotations
|
| 31 |
+
|
| 32 |
+
import glob
|
| 33 |
+
import platform
|
| 34 |
+
import shutil
|
| 35 |
+
import time
|
| 36 |
+
from copy import deepcopy
|
| 37 |
+
from pathlib import Path
|
| 38 |
+
|
| 39 |
+
import numpy as np
|
| 40 |
+
import torch.cuda
|
| 41 |
+
|
| 42 |
+
from ultralytics import YOLO, YOLOWorld
|
| 43 |
+
from ultralytics.cfg import TASK2DATA, TASK2METRIC
|
| 44 |
+
from ultralytics.engine.exporter import export_formats
|
| 45 |
+
from ultralytics.nn.modules import Segment26
|
| 46 |
+
from ultralytics.utils import (
|
| 47 |
+
ARM64,
|
| 48 |
+
ASSETS,
|
| 49 |
+
IS_DOCKER,
|
| 50 |
+
IS_JETSON,
|
| 51 |
+
LINUX,
|
| 52 |
+
LOGGER,
|
| 53 |
+
MACOS,
|
| 54 |
+
TQDM,
|
| 55 |
+
WEIGHTS_DIR,
|
| 56 |
+
is_github_action_running,
|
| 57 |
+
)
|
| 58 |
+
from ultralytics.utils.checks import IS_PYTHON_MINIMUM_3_13, check_imgsz, check_requirements, check_yolo, is_rockchip
|
| 59 |
+
from ultralytics.utils.files import file_size
|
| 60 |
+
from ultralytics.utils.torch_utils import get_cpu_info, select_device
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def benchmark(
|
| 64 |
+
model=WEIGHTS_DIR / "yolo26n.pt",
|
| 65 |
+
data=None,
|
| 66 |
+
imgsz=160,
|
| 67 |
+
quantize=None,
|
| 68 |
+
device="cpu",
|
| 69 |
+
verbose=False,
|
| 70 |
+
eps=1e-3,
|
| 71 |
+
format="",
|
| 72 |
+
**kwargs,
|
| 73 |
+
):
|
| 74 |
+
"""Benchmark a YOLO model across different formats for speed and accuracy.
|
| 75 |
+
|
| 76 |
+
Args:
|
| 77 |
+
model (str | Path): Path to the model file or directory.
|
| 78 |
+
data (str | None): Dataset to evaluate on, inherited from TASK2DATA if not passed.
|
| 79 |
+
imgsz (int): Image size for the benchmark.
|
| 80 |
+
quantize (int | str | None): Precision for export and inference: 16 (FP16), 8 (INT8), or None/32 (FP32).
|
| 81 |
+
device (str): Device to run the benchmark on, either 'cpu' or 'cuda'.
|
| 82 |
+
verbose (bool | float): If True or a float, assert benchmarks pass with given metric.
|
| 83 |
+
eps (float): Epsilon value for divide by zero prevention.
|
| 84 |
+
format (str): Export format for benchmarking. If not supplied all formats are benchmarked.
|
| 85 |
+
**kwargs (Any): Additional keyword arguments for exporter.
|
| 86 |
+
|
| 87 |
+
Returns:
|
| 88 |
+
(polars.DataFrame): A Polars DataFrame with benchmark results for each format, including file size, metric, and
|
| 89 |
+
inference time.
|
| 90 |
+
|
| 91 |
+
Examples:
|
| 92 |
+
Benchmark a YOLO model with default settings:
|
| 93 |
+
>>> from ultralytics.utils.benchmarks import benchmark
|
| 94 |
+
>>> benchmark(model="yolo26n.pt", imgsz=640)
|
| 95 |
+
"""
|
| 96 |
+
imgsz = check_imgsz(imgsz)
|
| 97 |
+
assert imgsz[0] == imgsz[1] if isinstance(imgsz, list) else True, "benchmark() only supports square imgsz."
|
| 98 |
+
|
| 99 |
+
import polars as pl # scope for faster 'import ultralytics'
|
| 100 |
+
|
| 101 |
+
pl.Config.set_tbl_cols(-1) # Show all columns
|
| 102 |
+
pl.Config.set_tbl_rows(-1) # Show all rows
|
| 103 |
+
pl.Config.set_tbl_width_chars(-1) # No width limit
|
| 104 |
+
pl.Config.set_tbl_hide_column_data_types(True) # Hide data types
|
| 105 |
+
pl.Config.set_tbl_hide_dataframe_shape(True) # Hide shape info
|
| 106 |
+
pl.Config.set_tbl_formatting("ASCII_BORDERS_ONLY_CONDENSED")
|
| 107 |
+
|
| 108 |
+
device = select_device(device, verbose=False)
|
| 109 |
+
if isinstance(model, (str, Path)):
|
| 110 |
+
model = YOLO(model)
|
| 111 |
+
data = data or TASK2DATA[model.task] # task to dataset, i.e. coco8.yaml for task=detect
|
| 112 |
+
key = TASK2METRIC[model.task] # task to metric, i.e. metrics/mAP50-95(B) for task=detect
|
| 113 |
+
|
| 114 |
+
y = []
|
| 115 |
+
t0 = time.time()
|
| 116 |
+
|
| 117 |
+
format_arg = format.lower()
|
| 118 |
+
if format_arg:
|
| 119 |
+
formats = frozenset(export_formats()["Argument"])
|
| 120 |
+
assert format in formats, f"Expected format to be one of {formats}, but got '{format_arg}'."
|
| 121 |
+
for name, format, suffix, cpu, gpu, valid_args, _ in zip(*export_formats().values()):
|
| 122 |
+
emoji, filename = "❌", None # export defaults
|
| 123 |
+
try:
|
| 124 |
+
if format_arg and format_arg != format:
|
| 125 |
+
continue
|
| 126 |
+
if IS_PYTHON_MINIMUM_3_13 and not format_arg and format in {"saved_model", "pb", "edgetpu"}:
|
| 127 |
+
continue
|
| 128 |
+
|
| 129 |
+
# Checks
|
| 130 |
+
if format == "pb":
|
| 131 |
+
assert model.task != "obb", "TensorFlow GraphDef not supported for OBB task"
|
| 132 |
+
elif format == "edgetpu":
|
| 133 |
+
assert LINUX and not ARM64, "Edge TPU export only supported on non-aarch64 Linux"
|
| 134 |
+
assert shutil.which("edgetpu_compiler"), "Edge TPU benchmark requires edgetpu_compiler"
|
| 135 |
+
elif format == "coreml":
|
| 136 |
+
assert MACOS or (LINUX and not ARM64), "CoreML export only supported on macOS and non-aarch64 Linux"
|
| 137 |
+
# coremltools deadlocks after OpenVINO on macOS Python 3.13 (conflicting OpenMP runtimes); CoreML
|
| 138 |
+
# is still benchmarked on non-aarch64 Linux Python 3.13.
|
| 139 |
+
assert not (MACOS and IS_PYTHON_MINIMUM_3_13), (
|
| 140 |
+
"CoreML not benchmarked on macOS Python>=3.13 (coremltools/OpenVINO OpenMP deadlock)"
|
| 141 |
+
)
|
| 142 |
+
if format in {"saved_model", "pb", "edgetpu"}:
|
| 143 |
+
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 TensorFlow exports not supported by onnx2tf yet"
|
| 144 |
+
if format == "paddle":
|
| 145 |
+
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 Paddle exports not supported yet"
|
| 146 |
+
assert model.task != "obb", "Paddle OBB bug https://github.com/PaddlePaddle/Paddle/issues/72024"
|
| 147 |
+
assert (LINUX and not IS_JETSON) or MACOS, "Windows and Jetson Paddle exports not supported yet"
|
| 148 |
+
# PaddlePaddle export works standalone on Python 3.13 but its native protobuf clashes with the
|
| 149 |
+
# protobuf>=6.31.1 that TensorFlow loads earlier in this shared benchmark process, causing a segfault.
|
| 150 |
+
assert not IS_PYTHON_MINIMUM_3_13, (
|
| 151 |
+
"PaddlePaddle not benchmarked on Python>=3.13 (protobuf ABI conflict with TensorFlow)"
|
| 152 |
+
)
|
| 153 |
+
if format == "mnn":
|
| 154 |
+
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 MNN exports not supported yet"
|
| 155 |
+
# MNN export works standalone on Python 3.13 but its ONNX-parsing protobuf clashes with the
|
| 156 |
+
# protobuf>=6.31.1 that TensorFlow loads earlier in this shared benchmark process, aborting the run.
|
| 157 |
+
assert not IS_PYTHON_MINIMUM_3_13, (
|
| 158 |
+
"MNN not benchmarked on Python>=3.13 (protobuf ABI conflict with TensorFlow)"
|
| 159 |
+
)
|
| 160 |
+
if format == "ncnn":
|
| 161 |
+
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 NCNN exports not supported yet"
|
| 162 |
+
if format == "imx":
|
| 163 |
+
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 IMX exports not supported"
|
| 164 |
+
assert model.task in {"detect", "classify", "pose", "segment"}, (
|
| 165 |
+
"IMX export is only supported for detection, classification, pose estimation and segmentation tasks"
|
| 166 |
+
)
|
| 167 |
+
assert "C2f" in model.__str__(), "IMX only supported for YOLOv8n and YOLO11n"
|
| 168 |
+
if format == "rknn":
|
| 169 |
+
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 RKNN exports not supported yet"
|
| 170 |
+
assert LINUX, "RKNN only supported on Linux"
|
| 171 |
+
assert not is_rockchip(), "RKNN Inference only supported on Rockchip devices"
|
| 172 |
+
if format == "executorch":
|
| 173 |
+
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 ExecuTorch exports not supported yet"
|
| 174 |
+
if format == "axelera":
|
| 175 |
+
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 Axelera exports not supported"
|
| 176 |
+
assert LINUX and not (ARM64 and IS_DOCKER), (
|
| 177 |
+
"export is only supported on Linux and is not supported on ARM64 Docker."
|
| 178 |
+
)
|
| 179 |
+
assert not (model.task == "segment" and any(isinstance(m, Segment26) for m in model.model.modules())), (
|
| 180 |
+
"Axelera export does not currently support YOLO26 segmentation models"
|
| 181 |
+
)
|
| 182 |
+
if format == "litert":
|
| 183 |
+
assert MACOS or (LINUX and not ARM64), "LiteRT benchmark only supported on Linux x86 and macOS"
|
| 184 |
+
# benchmark() deadlocks on the ai-edge-litert/TensorFlow abseil mutex (RAW: Lock blocking) on macOS CI
|
| 185 |
+
# when litert runs after other TF-based formats in the shared process; still benchmarked locally.
|
| 186 |
+
assert not (MACOS and is_github_action_running()), (
|
| 187 |
+
"LiteRT not benchmarked on macOS CI (ai-edge-litert/TF abseil mutex deadlock)"
|
| 188 |
+
)
|
| 189 |
+
if "cpu" in device.type:
|
| 190 |
+
assert cpu, "inference not supported on CPU"
|
| 191 |
+
if "cuda" in device.type:
|
| 192 |
+
assert gpu, "inference not supported on GPU"
|
| 193 |
+
|
| 194 |
+
# Export
|
| 195 |
+
if format == "-":
|
| 196 |
+
filename = model.pt_path or model.ckpt_path or model.model_name
|
| 197 |
+
exported_model = deepcopy(model) # PyTorch format
|
| 198 |
+
else:
|
| 199 |
+
export_data = data if "data" in valid_args else None
|
| 200 |
+
filename = deepcopy(model).export(
|
| 201 |
+
imgsz=imgsz,
|
| 202 |
+
format=format,
|
| 203 |
+
quantize=quantize,
|
| 204 |
+
data=export_data,
|
| 205 |
+
device=device,
|
| 206 |
+
verbose=False,
|
| 207 |
+
**kwargs,
|
| 208 |
+
)
|
| 209 |
+
exported_model = YOLO(filename, task=model.task)
|
| 210 |
+
assert suffix in str(filename), "export failed"
|
| 211 |
+
emoji = "❎" # indicates export succeeded
|
| 212 |
+
|
| 213 |
+
# Predict
|
| 214 |
+
assert model.task != "pose" or format != "pb", "GraphDef Pose inference is not supported"
|
| 215 |
+
assert format != "edgetpu", "inference not supported"
|
| 216 |
+
assert format != "coreml" or platform.system() == "Darwin", "inference only supported on macOS>=10.13"
|
| 217 |
+
assert format != "axelera", "inference only supported on Axelera hardware"
|
| 218 |
+
exported_model.predict(ASSETS / "bus.jpg", imgsz=imgsz, device=device, quantize=quantize, verbose=False)
|
| 219 |
+
|
| 220 |
+
# Validate
|
| 221 |
+
results = exported_model.val(
|
| 222 |
+
data=data,
|
| 223 |
+
batch=1,
|
| 224 |
+
imgsz=imgsz,
|
| 225 |
+
plots=False,
|
| 226 |
+
device=device,
|
| 227 |
+
quantize=quantize,
|
| 228 |
+
verbose=False,
|
| 229 |
+
conf=0.001, # all the pre-set benchmark mAP values are based on conf=0.001
|
| 230 |
+
)
|
| 231 |
+
metric, speed = results.results_dict[key], results.speed["inference"]
|
| 232 |
+
fps = round(1000 / (speed + eps), 2) # frames per second
|
| 233 |
+
y.append([name, "✅", round(file_size(filename), 1), round(metric, 4), round(speed, 2), fps])
|
| 234 |
+
except Exception as e:
|
| 235 |
+
if verbose:
|
| 236 |
+
assert type(e) is AssertionError, f"Benchmark failure for {name}: {e}"
|
| 237 |
+
LOGGER.error(f"Benchmark failure for {name}: {e}")
|
| 238 |
+
y.append([name, emoji, round(file_size(filename), 1), None, None, None]) # mAP, t_inference
|
| 239 |
+
|
| 240 |
+
# Print results
|
| 241 |
+
check_yolo(device=device) # print system info
|
| 242 |
+
df = pl.DataFrame(y, schema=["Format", "Status❔", "Size (MB)", key, "Inference time (ms/im)", "FPS"], orient="row")
|
| 243 |
+
df = df.with_row_index(" ", offset=1) # add index info
|
| 244 |
+
df_display = df.with_columns(pl.all().cast(pl.String).fill_null("-"))
|
| 245 |
+
|
| 246 |
+
name = model.model_name
|
| 247 |
+
dt = time.time() - t0
|
| 248 |
+
legend = "Benchmarks legend: - ✅ Success - ❎ Export passed but validation failed - ❌️ Export failed"
|
| 249 |
+
s = f"\nBenchmarks complete for {name} on {data} at imgsz={imgsz} ({dt:.2f}s)\n{legend}\n{df_display}\n"
|
| 250 |
+
LOGGER.info(s)
|
| 251 |
+
with open("benchmarks.log", "a", errors="ignore", encoding="utf-8") as f:
|
| 252 |
+
f.write(s)
|
| 253 |
+
|
| 254 |
+
if verbose and isinstance(verbose, float):
|
| 255 |
+
metrics = df[key].to_numpy() # values to compare to floor
|
| 256 |
+
floor = verbose # minimum metric floor to pass, i.e. = 0.29 mAP for YOLOv5n
|
| 257 |
+
assert all(x > floor for x in metrics if not np.isnan(x)), f"Benchmark failure: metric(s) < floor {floor}"
|
| 258 |
+
|
| 259 |
+
return df_display
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
class ProfileModels:
|
| 263 |
+
"""ProfileModels class for profiling different models on ONNX and TensorRT.
|
| 264 |
+
|
| 265 |
+
This class profiles the performance of different models, returning results such as model speed and FLOPs.
|
| 266 |
+
|
| 267 |
+
Attributes:
|
| 268 |
+
paths (list[str]): Paths of the models to profile.
|
| 269 |
+
num_timed_runs (int): Number of timed runs for the profiling.
|
| 270 |
+
num_warmup_runs (int): Number of warmup runs before profiling.
|
| 271 |
+
min_time (float): Minimum number of seconds to profile for.
|
| 272 |
+
imgsz (int): Image size used in the models.
|
| 273 |
+
quantize (int | str | None): Export precision for TensorRT profiling, e.g. 16 (FP16) or 8 (INT8).
|
| 274 |
+
trt (bool): Flag to indicate whether to profile using TensorRT.
|
| 275 |
+
device (torch.device): Device used for profiling.
|
| 276 |
+
|
| 277 |
+
Methods:
|
| 278 |
+
run: Profile YOLO models for speed and accuracy across various formats.
|
| 279 |
+
get_files: Get all relevant model files.
|
| 280 |
+
get_onnx_model_info: Extract metadata from an ONNX model.
|
| 281 |
+
iterative_sigma_clipping: Apply sigma clipping to remove outliers.
|
| 282 |
+
profile_tensorrt_model: Profile a TensorRT model.
|
| 283 |
+
profile_onnx_model: Profile an ONNX model.
|
| 284 |
+
generate_table_row: Generate a table row with model metrics.
|
| 285 |
+
generate_results_dict: Generate a dictionary of profiling results.
|
| 286 |
+
print_table: Print a formatted table of results.
|
| 287 |
+
|
| 288 |
+
Examples:
|
| 289 |
+
Profile models and print results
|
| 290 |
+
>>> from ultralytics.utils.benchmarks import ProfileModels
|
| 291 |
+
>>> profiler = ProfileModels(["yolo26n.yaml", "yolov8s.yaml"], imgsz=640)
|
| 292 |
+
>>> profiler.run()
|
| 293 |
+
"""
|
| 294 |
+
|
| 295 |
+
def __init__(
|
| 296 |
+
self,
|
| 297 |
+
paths: list[str],
|
| 298 |
+
num_timed_runs: int = 100,
|
| 299 |
+
num_warmup_runs: int = 10,
|
| 300 |
+
min_time: float = 60,
|
| 301 |
+
imgsz: int = 640,
|
| 302 |
+
quantize: int | str | None = 16,
|
| 303 |
+
trt: bool = True,
|
| 304 |
+
device: torch.device | str | None = None,
|
| 305 |
+
):
|
| 306 |
+
"""Initialize the ProfileModels class for profiling models.
|
| 307 |
+
|
| 308 |
+
Args:
|
| 309 |
+
paths (list[str]): List of paths of the models to be profiled.
|
| 310 |
+
num_timed_runs (int): Number of timed runs for the profiling.
|
| 311 |
+
num_warmup_runs (int): Number of warmup runs before the actual profiling starts.
|
| 312 |
+
min_time (float): Minimum time in seconds for profiling a model.
|
| 313 |
+
imgsz (int): Size of the image used during profiling.
|
| 314 |
+
quantize (int | str | None): Export precision for TensorRT profiling, e.g. 16 (FP16, default) or 8 (INT8).
|
| 315 |
+
trt (bool): Flag to indicate whether to profile using TensorRT.
|
| 316 |
+
device (torch.device | str | None): Device used for profiling. If None, it is determined automatically.
|
| 317 |
+
|
| 318 |
+
Notes:
|
| 319 |
+
quantize applies only to the TensorRT profiling export; ONNX profiling stays FP32 (FP16 is slower on CPU).
|
| 320 |
+
"""
|
| 321 |
+
self.paths = paths
|
| 322 |
+
self.num_timed_runs = num_timed_runs
|
| 323 |
+
self.num_warmup_runs = num_warmup_runs
|
| 324 |
+
self.min_time = min_time
|
| 325 |
+
self.imgsz = imgsz
|
| 326 |
+
self.quantize = quantize
|
| 327 |
+
self.trt = trt # run TensorRT profiling
|
| 328 |
+
self.device = device if isinstance(device, torch.device) else select_device(device)
|
| 329 |
+
|
| 330 |
+
def run(self):
|
| 331 |
+
"""Profile YOLO models for speed and accuracy across various formats including ONNX and TensorRT.
|
| 332 |
+
|
| 333 |
+
Returns:
|
| 334 |
+
(list[dict]): List of dictionaries containing profiling results for each model.
|
| 335 |
+
|
| 336 |
+
Examples:
|
| 337 |
+
Profile models and print results
|
| 338 |
+
>>> from ultralytics.utils.benchmarks import ProfileModels
|
| 339 |
+
>>> profiler = ProfileModels(["yolo26n.yaml", "yolo11s.yaml"])
|
| 340 |
+
>>> results = profiler.run()
|
| 341 |
+
"""
|
| 342 |
+
files = self.get_files()
|
| 343 |
+
|
| 344 |
+
if not files:
|
| 345 |
+
LOGGER.warning("No matching *.pt or *.onnx files found.")
|
| 346 |
+
return []
|
| 347 |
+
|
| 348 |
+
table_rows = []
|
| 349 |
+
output = []
|
| 350 |
+
for file in files:
|
| 351 |
+
engine_file = file.with_suffix(".engine")
|
| 352 |
+
if file.suffix in {".pt", ".yaml", ".yml"}:
|
| 353 |
+
model = YOLO(str(file))
|
| 354 |
+
model.fuse() # to report correct params and GFLOPs in model.info()
|
| 355 |
+
model_info = model.info(imgsz=self.imgsz)
|
| 356 |
+
if self.trt and self.device.type != "cpu" and not engine_file.is_file():
|
| 357 |
+
engine_file = model.export(
|
| 358 |
+
format="engine",
|
| 359 |
+
quantize=self.quantize,
|
| 360 |
+
imgsz=self.imgsz,
|
| 361 |
+
device=self.device,
|
| 362 |
+
verbose=False,
|
| 363 |
+
)
|
| 364 |
+
onnx_file = model.export(
|
| 365 |
+
format="onnx",
|
| 366 |
+
imgsz=self.imgsz,
|
| 367 |
+
device=self.device,
|
| 368 |
+
verbose=False,
|
| 369 |
+
)
|
| 370 |
+
elif file.suffix == ".onnx":
|
| 371 |
+
model_info = self.get_onnx_model_info(file)
|
| 372 |
+
onnx_file = file
|
| 373 |
+
else:
|
| 374 |
+
continue
|
| 375 |
+
|
| 376 |
+
t_engine = self.profile_tensorrt_model(str(engine_file))
|
| 377 |
+
t_onnx = self.profile_onnx_model(str(onnx_file))
|
| 378 |
+
table_rows.append(self.generate_table_row(file.stem, t_onnx, t_engine, model_info))
|
| 379 |
+
output.append(self.generate_results_dict(file.stem, t_onnx, t_engine, model_info))
|
| 380 |
+
|
| 381 |
+
self.print_table(table_rows)
|
| 382 |
+
return output
|
| 383 |
+
|
| 384 |
+
def get_files(self):
|
| 385 |
+
"""Return a list of paths for all relevant model files given by the user.
|
| 386 |
+
|
| 387 |
+
Returns:
|
| 388 |
+
(list[Path]): List of Path objects for the model files.
|
| 389 |
+
"""
|
| 390 |
+
files = []
|
| 391 |
+
for path in self.paths:
|
| 392 |
+
path = Path(path)
|
| 393 |
+
if path.is_dir():
|
| 394 |
+
extensions = ["*.pt", "*.onnx", "*.yaml"]
|
| 395 |
+
files.extend([file for ext in extensions for file in glob.glob(str(path / ext))])
|
| 396 |
+
elif path.suffix in {".pt", ".yaml", ".yml"}: # add non-existing
|
| 397 |
+
files.append(str(path))
|
| 398 |
+
else:
|
| 399 |
+
files.extend(glob.glob(str(path)))
|
| 400 |
+
|
| 401 |
+
LOGGER.info(f"Profiling: {sorted(files)}")
|
| 402 |
+
return [Path(file) for file in sorted(files)]
|
| 403 |
+
|
| 404 |
+
@staticmethod
|
| 405 |
+
def get_onnx_model_info(onnx_file: str):
|
| 406 |
+
"""Extract metadata from an ONNX model file including layers, parameters, gradients, and FLOPs."""
|
| 407 |
+
return 0.0, 0.0, 0.0, 0.0 # return (num_layers, num_params, num_gradients, num_flops)
|
| 408 |
+
|
| 409 |
+
@staticmethod
|
| 410 |
+
def iterative_sigma_clipping(data: np.ndarray, sigma: float = 2, max_iters: int = 3):
|
| 411 |
+
"""Apply iterative sigma clipping to data to remove outliers.
|
| 412 |
+
|
| 413 |
+
Args:
|
| 414 |
+
data (np.ndarray): Input data array.
|
| 415 |
+
sigma (float): Number of standard deviations to use for clipping.
|
| 416 |
+
max_iters (int): Maximum number of iterations for the clipping process.
|
| 417 |
+
|
| 418 |
+
Returns:
|
| 419 |
+
(np.ndarray): Clipped data array with outliers removed.
|
| 420 |
+
"""
|
| 421 |
+
data = np.array(data)
|
| 422 |
+
for _ in range(max_iters):
|
| 423 |
+
mean, std = np.mean(data), np.std(data)
|
| 424 |
+
clipped_data = data[(data > mean - sigma * std) & (data < mean + sigma * std)]
|
| 425 |
+
if len(clipped_data) == len(data):
|
| 426 |
+
break
|
| 427 |
+
data = clipped_data
|
| 428 |
+
return data
|
| 429 |
+
|
| 430 |
+
def profile_tensorrt_model(self, engine_file: str, eps: float = 1e-3):
|
| 431 |
+
"""Profile YOLO model performance with TensorRT, measuring average run time and standard deviation.
|
| 432 |
+
|
| 433 |
+
Args:
|
| 434 |
+
engine_file (str): Path to the TensorRT engine file.
|
| 435 |
+
eps (float): Small epsilon value to prevent division by zero.
|
| 436 |
+
|
| 437 |
+
Returns:
|
| 438 |
+
(tuple[float, float]): Mean and standard deviation of inference time in milliseconds.
|
| 439 |
+
"""
|
| 440 |
+
if not self.trt or not Path(engine_file).is_file():
|
| 441 |
+
return 0.0, 0.0
|
| 442 |
+
|
| 443 |
+
# Model and input
|
| 444 |
+
model = YOLO(engine_file)
|
| 445 |
+
input_data = np.zeros((self.imgsz, self.imgsz, 3), dtype=np.uint8) # use uint8 for Classify
|
| 446 |
+
|
| 447 |
+
# Warmup runs
|
| 448 |
+
elapsed = 0.0
|
| 449 |
+
for _ in range(3):
|
| 450 |
+
start_time = time.time()
|
| 451 |
+
for _ in range(self.num_warmup_runs):
|
| 452 |
+
model(input_data, imgsz=self.imgsz, verbose=False)
|
| 453 |
+
elapsed = time.time() - start_time
|
| 454 |
+
|
| 455 |
+
# Compute number of runs as higher of min_time or num_timed_runs
|
| 456 |
+
num_runs = max(round(self.min_time / (elapsed + eps) * self.num_warmup_runs), self.num_timed_runs * 50)
|
| 457 |
+
|
| 458 |
+
# Timed runs
|
| 459 |
+
run_times = []
|
| 460 |
+
for _ in TQDM(range(num_runs), desc=engine_file):
|
| 461 |
+
results = model(input_data, imgsz=self.imgsz, verbose=False)
|
| 462 |
+
run_times.append(results[0].speed["inference"]) # Convert to milliseconds
|
| 463 |
+
|
| 464 |
+
run_times = self.iterative_sigma_clipping(np.array(run_times), sigma=2, max_iters=3) # sigma clipping
|
| 465 |
+
return np.mean(run_times), np.std(run_times)
|
| 466 |
+
|
| 467 |
+
@staticmethod
|
| 468 |
+
def check_dynamic(tensor_shape):
|
| 469 |
+
"""Check whether the tensor shape in the ONNX model is dynamic."""
|
| 470 |
+
return not all(isinstance(dim, int) and dim >= 0 for dim in tensor_shape)
|
| 471 |
+
|
| 472 |
+
def profile_onnx_model(self, onnx_file: str, eps: float = 1e-3):
|
| 473 |
+
"""Profile an ONNX model, measuring average inference time and standard deviation across multiple runs.
|
| 474 |
+
|
| 475 |
+
Args:
|
| 476 |
+
onnx_file (str): Path to the ONNX model file.
|
| 477 |
+
eps (float): Small epsilon value to prevent division by zero.
|
| 478 |
+
|
| 479 |
+
Returns:
|
| 480 |
+
(tuple[float, float]): Mean and standard deviation of inference time in milliseconds.
|
| 481 |
+
"""
|
| 482 |
+
check_requirements([("onnxruntime", "onnxruntime-gpu")]) # either package meets requirements
|
| 483 |
+
import onnxruntime as ort
|
| 484 |
+
|
| 485 |
+
# Session with either 'TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider'
|
| 486 |
+
sess_options = ort.SessionOptions()
|
| 487 |
+
sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
|
| 488 |
+
sess_options.intra_op_num_threads = 8 # Limit the number of threads
|
| 489 |
+
sess = ort.InferenceSession(onnx_file, sess_options, providers=["CPUExecutionProvider"])
|
| 490 |
+
|
| 491 |
+
input_data_dict = {}
|
| 492 |
+
for input_tensor in sess.get_inputs():
|
| 493 |
+
input_type = input_tensor.type
|
| 494 |
+
if self.check_dynamic(input_tensor.shape):
|
| 495 |
+
if len(input_tensor.shape) != 4 and self.check_dynamic(input_tensor.shape[1:]):
|
| 496 |
+
raise ValueError(f"Unsupported dynamic shape {input_tensor.shape} of {input_tensor.name}")
|
| 497 |
+
input_shape = (
|
| 498 |
+
(1, 3, self.imgsz, self.imgsz) if len(input_tensor.shape) == 4 else (1, *input_tensor.shape[1:])
|
| 499 |
+
)
|
| 500 |
+
else:
|
| 501 |
+
input_shape = input_tensor.shape
|
| 502 |
+
|
| 503 |
+
# Mapping ONNX datatype to numpy datatype
|
| 504 |
+
if "float16" in input_type:
|
| 505 |
+
input_dtype = np.float16
|
| 506 |
+
elif "float" in input_type:
|
| 507 |
+
input_dtype = np.float32
|
| 508 |
+
elif "double" in input_type:
|
| 509 |
+
input_dtype = np.float64
|
| 510 |
+
elif "int64" in input_type:
|
| 511 |
+
input_dtype = np.int64
|
| 512 |
+
elif "int32" in input_type:
|
| 513 |
+
input_dtype = np.int32
|
| 514 |
+
else:
|
| 515 |
+
raise ValueError(f"Unsupported ONNX datatype {input_type}")
|
| 516 |
+
|
| 517 |
+
input_data = np.random.rand(*input_shape).astype(input_dtype)
|
| 518 |
+
input_name = input_tensor.name
|
| 519 |
+
input_data_dict[input_name] = input_data
|
| 520 |
+
|
| 521 |
+
output_name = sess.get_outputs()[0].name
|
| 522 |
+
|
| 523 |
+
# Warmup runs
|
| 524 |
+
elapsed = 0.0
|
| 525 |
+
for _ in range(3):
|
| 526 |
+
start_time = time.time()
|
| 527 |
+
for _ in range(self.num_warmup_runs):
|
| 528 |
+
sess.run([output_name], input_data_dict)
|
| 529 |
+
elapsed = time.time() - start_time
|
| 530 |
+
|
| 531 |
+
# Compute number of runs as higher of min_time or num_timed_runs
|
| 532 |
+
num_runs = max(round(self.min_time / (elapsed + eps) * self.num_warmup_runs), self.num_timed_runs)
|
| 533 |
+
|
| 534 |
+
# Timed runs
|
| 535 |
+
run_times = []
|
| 536 |
+
for _ in TQDM(range(num_runs), desc=onnx_file):
|
| 537 |
+
start_time = time.time()
|
| 538 |
+
sess.run([output_name], input_data_dict)
|
| 539 |
+
run_times.append((time.time() - start_time) * 1000) # Convert to milliseconds
|
| 540 |
+
|
| 541 |
+
run_times = self.iterative_sigma_clipping(np.array(run_times), sigma=2, max_iters=5) # sigma clipping
|
| 542 |
+
return np.mean(run_times), np.std(run_times)
|
| 543 |
+
|
| 544 |
+
def generate_table_row(
|
| 545 |
+
self,
|
| 546 |
+
model_name: str,
|
| 547 |
+
t_onnx: tuple[float, float],
|
| 548 |
+
t_engine: tuple[float, float],
|
| 549 |
+
model_info: tuple[float, float, float, float],
|
| 550 |
+
):
|
| 551 |
+
"""Generate a table row string with model performance metrics.
|
| 552 |
+
|
| 553 |
+
Args:
|
| 554 |
+
model_name (str): Name of the model.
|
| 555 |
+
t_onnx (tuple): ONNX model inference time statistics (mean, std).
|
| 556 |
+
t_engine (tuple): TensorRT engine inference time statistics (mean, std).
|
| 557 |
+
model_info (tuple): Model information (layers, params, gradients, flops).
|
| 558 |
+
|
| 559 |
+
Returns:
|
| 560 |
+
(str): Formatted table row string with model metrics.
|
| 561 |
+
"""
|
| 562 |
+
_layers, params, _gradients, flops = model_info
|
| 563 |
+
return (
|
| 564 |
+
f"| {model_name:18s} | {self.imgsz} | - | {t_onnx[0]:.1f}±{t_onnx[1]:.1f} ms | {t_engine[0]:.1f}±"
|
| 565 |
+
f"{t_engine[1]:.1f} ms | {params / 1e6:.1f} | {flops:.1f} |"
|
| 566 |
+
)
|
| 567 |
+
|
| 568 |
+
@staticmethod
|
| 569 |
+
def generate_results_dict(
|
| 570 |
+
model_name: str,
|
| 571 |
+
t_onnx: tuple[float, float],
|
| 572 |
+
t_engine: tuple[float, float],
|
| 573 |
+
model_info: tuple[float, float, float, float],
|
| 574 |
+
):
|
| 575 |
+
"""Generate a dictionary of profiling results.
|
| 576 |
+
|
| 577 |
+
Args:
|
| 578 |
+
model_name (str): Name of the model.
|
| 579 |
+
t_onnx (tuple): ONNX model inference time statistics (mean, std).
|
| 580 |
+
t_engine (tuple): TensorRT engine inference time statistics (mean, std).
|
| 581 |
+
model_info (tuple): Model information (layers, params, gradients, flops).
|
| 582 |
+
|
| 583 |
+
Returns:
|
| 584 |
+
(dict): Dictionary containing profiling results.
|
| 585 |
+
"""
|
| 586 |
+
_layers, params, _gradients, flops = model_info
|
| 587 |
+
return {
|
| 588 |
+
"model/name": model_name,
|
| 589 |
+
"model/parameters": params,
|
| 590 |
+
"model/GFLOPs": round(flops, 3),
|
| 591 |
+
"model/speed_ONNX(ms)": round(t_onnx[0], 3),
|
| 592 |
+
"model/speed_TensorRT(ms)": round(t_engine[0], 3),
|
| 593 |
+
}
|
| 594 |
+
|
| 595 |
+
@staticmethod
|
| 596 |
+
def print_table(table_rows: list[str]):
|
| 597 |
+
"""Print a formatted table of model profiling results.
|
| 598 |
+
|
| 599 |
+
Args:
|
| 600 |
+
table_rows (list[str]): List of formatted table row strings.
|
| 601 |
+
"""
|
| 602 |
+
gpu = torch.cuda.get_device_name(0) if torch.cuda.is_available() else "GPU"
|
| 603 |
+
headers = [
|
| 604 |
+
"Model",
|
| 605 |
+
"size<br><sup>(pixels)",
|
| 606 |
+
"mAP<sup>val<br>50-95",
|
| 607 |
+
f"Speed<br><sup>CPU ({get_cpu_info()}) ONNX<br>(ms)",
|
| 608 |
+
f"Speed<br><sup>{gpu} TensorRT<br>(ms)",
|
| 609 |
+
"params<br><sup>(M)",
|
| 610 |
+
"FLOPs<br><sup>(B)",
|
| 611 |
+
]
|
| 612 |
+
header = "|" + "|".join(f" {h} " for h in headers) + "|"
|
| 613 |
+
separator = "|" + "|".join("-" * (len(h) + 2) for h in headers) + "|"
|
| 614 |
+
|
| 615 |
+
LOGGER.info(f"\n\n{header}")
|
| 616 |
+
LOGGER.info(separator)
|
| 617 |
+
for row in table_rows:
|
| 618 |
+
LOGGER.info(row)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__init__.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
from .base import add_integration_callbacks, default_callbacks, get_default_callbacks
|
| 4 |
+
|
| 5 |
+
__all__ = "add_integration_callbacks", "default_callbacks", "get_default_callbacks"
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (361 Bytes). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/base.cpython-314.pyc
ADDED
|
Binary file (8.01 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/clearml.cpython-314.pyc
ADDED
|
Binary file (9.51 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/comet.cpython-314.pyc
ADDED
|
Binary file (32 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/dvc.cpython-314.pyc
ADDED
|
Binary file (10.9 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/hub.cpython-314.pyc
ADDED
|
Binary file (5.98 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/mlflow.cpython-314.pyc
ADDED
|
Binary file (9.59 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/neptune.cpython-314.pyc
ADDED
|
Binary file (8.18 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/platform.cpython-314.pyc
ADDED
|
Binary file (26.3 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/raytune.cpython-314.pyc
ADDED
|
Binary file (1.71 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/tensorboard.cpython-314.pyc
ADDED
|
Binary file (7.34 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/wb.cpython-314.pyc
ADDED
|
Binary file (11.6 kB). View file
|
|
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/base.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
"""Base callbacks for Ultralytics training, validation, prediction, and export processes."""
|
| 3 |
+
|
| 4 |
+
from collections import defaultdict
|
| 5 |
+
from copy import deepcopy
|
| 6 |
+
|
| 7 |
+
# Trainer callbacks ----------------------------------------------------------------------------------------------------
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def on_pretrain_routine_start(trainer):
|
| 11 |
+
"""Called at the beginning of the pre-training routine, before data loading and model setup."""
|
| 12 |
+
pass
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def on_pretrain_routine_end(trainer):
|
| 16 |
+
"""Called at the end of the pre-training routine, after data loading and model setup are complete."""
|
| 17 |
+
pass
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def on_train_start(trainer):
|
| 21 |
+
"""Called when the training starts, before the first epoch begins."""
|
| 22 |
+
pass
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def on_train_epoch_start(trainer):
|
| 26 |
+
"""Called at the start of each training epoch, before batch iteration begins."""
|
| 27 |
+
pass
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def on_train_batch_start(trainer):
|
| 31 |
+
"""Called at the start of each training batch, before the forward pass."""
|
| 32 |
+
pass
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def optimizer_step(trainer):
|
| 36 |
+
"""Called during the optimizer step. Reserved for custom integrations; not called by default."""
|
| 37 |
+
pass
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def on_before_zero_grad(trainer):
|
| 41 |
+
"""Called before the gradients are set to zero. Reserved for custom integrations; not called by default."""
|
| 42 |
+
pass
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def on_train_batch_end(trainer):
|
| 46 |
+
"""Called at the end of each training batch, after the backward pass. Optimizer step may be deferred by
|
| 47 |
+
accumulation.
|
| 48 |
+
"""
|
| 49 |
+
pass
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def on_train_epoch_end(trainer):
|
| 53 |
+
"""Called at the end of each training epoch, after all batches but before validation."""
|
| 54 |
+
pass
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def on_fit_epoch_end(trainer):
|
| 58 |
+
"""Called at the end of each fit epoch (train + val), after validation and any checkpoint save."""
|
| 59 |
+
pass
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def on_model_save(trainer):
|
| 63 |
+
"""Called when the model checkpoint is saved, after validation."""
|
| 64 |
+
pass
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def on_train_end(trainer):
|
| 68 |
+
"""Called when the training ends, after final evaluation of the best model."""
|
| 69 |
+
pass
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def on_params_update(trainer):
|
| 73 |
+
"""Called when the model parameters are updated. Reserved for custom integrations; not called by default."""
|
| 74 |
+
pass
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def teardown(trainer):
|
| 78 |
+
"""Called during the teardown of the training process."""
|
| 79 |
+
pass
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
# Validator callbacks --------------------------------------------------------------------------------------------------
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def on_val_start(validator):
|
| 86 |
+
"""Called when the validation starts."""
|
| 87 |
+
pass
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def on_val_batch_start(validator):
|
| 91 |
+
"""Called at the start of each validation batch."""
|
| 92 |
+
pass
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def on_val_batch_end(validator):
|
| 96 |
+
"""Called at the end of each validation batch."""
|
| 97 |
+
pass
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def on_val_end(validator):
|
| 101 |
+
"""Called when the validation ends."""
|
| 102 |
+
pass
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
# Predictor callbacks --------------------------------------------------------------------------------------------------
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def on_predict_start(predictor):
|
| 109 |
+
"""Called when the prediction starts."""
|
| 110 |
+
pass
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def on_predict_batch_start(predictor):
|
| 114 |
+
"""Called at the start of each prediction batch."""
|
| 115 |
+
pass
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def on_predict_batch_end(predictor):
|
| 119 |
+
"""Called at the end of each prediction batch."""
|
| 120 |
+
pass
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def on_predict_postprocess_end(predictor):
|
| 124 |
+
"""Called after the post-processing of the prediction ends."""
|
| 125 |
+
pass
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
def on_predict_end(predictor):
|
| 129 |
+
"""Called when the prediction ends."""
|
| 130 |
+
pass
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
# Exporter callbacks ---------------------------------------------------------------------------------------------------
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def on_export_start(exporter):
|
| 137 |
+
"""Called when the model export starts."""
|
| 138 |
+
pass
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def on_export_end(exporter):
|
| 142 |
+
"""Called when the model export ends."""
|
| 143 |
+
pass
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
default_callbacks = {
|
| 147 |
+
# Run in trainer
|
| 148 |
+
"on_pretrain_routine_start": [on_pretrain_routine_start],
|
| 149 |
+
"on_pretrain_routine_end": [on_pretrain_routine_end],
|
| 150 |
+
"on_train_start": [on_train_start],
|
| 151 |
+
"on_train_epoch_start": [on_train_epoch_start],
|
| 152 |
+
"on_train_batch_start": [on_train_batch_start],
|
| 153 |
+
"optimizer_step": [optimizer_step],
|
| 154 |
+
"on_before_zero_grad": [on_before_zero_grad],
|
| 155 |
+
"on_train_batch_end": [on_train_batch_end],
|
| 156 |
+
"on_train_epoch_end": [on_train_epoch_end],
|
| 157 |
+
"on_fit_epoch_end": [on_fit_epoch_end], # fit = train + val
|
| 158 |
+
"on_model_save": [on_model_save],
|
| 159 |
+
"on_train_end": [on_train_end],
|
| 160 |
+
"on_params_update": [on_params_update],
|
| 161 |
+
"teardown": [teardown],
|
| 162 |
+
# Run in validator
|
| 163 |
+
"on_val_start": [on_val_start],
|
| 164 |
+
"on_val_batch_start": [on_val_batch_start],
|
| 165 |
+
"on_val_batch_end": [on_val_batch_end],
|
| 166 |
+
"on_val_end": [on_val_end],
|
| 167 |
+
# Run in predictor
|
| 168 |
+
"on_predict_start": [on_predict_start],
|
| 169 |
+
"on_predict_batch_start": [on_predict_batch_start],
|
| 170 |
+
"on_predict_postprocess_end": [on_predict_postprocess_end],
|
| 171 |
+
"on_predict_batch_end": [on_predict_batch_end],
|
| 172 |
+
"on_predict_end": [on_predict_end],
|
| 173 |
+
# Run in exporter
|
| 174 |
+
"on_export_start": [on_export_start],
|
| 175 |
+
"on_export_end": [on_export_end],
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def get_default_callbacks():
|
| 180 |
+
"""Get the default callbacks for Ultralytics training, validation, prediction, and export processes.
|
| 181 |
+
|
| 182 |
+
Returns:
|
| 183 |
+
(dict): Dictionary of default callbacks for various training events. Each key represents an event during the
|
| 184 |
+
training process, and the corresponding value is a list of callback functions executed when that
|
| 185 |
+
event occurs.
|
| 186 |
+
|
| 187 |
+
Examples:
|
| 188 |
+
>>> callbacks = get_default_callbacks()
|
| 189 |
+
>>> print(list(callbacks.keys())) # show all available callback events
|
| 190 |
+
['on_pretrain_routine_start', 'on_pretrain_routine_end', ...]
|
| 191 |
+
"""
|
| 192 |
+
return defaultdict(list, deepcopy(default_callbacks))
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def add_integration_callbacks(instance):
|
| 196 |
+
"""Add integration callbacks to the instance's callbacks dictionary.
|
| 197 |
+
|
| 198 |
+
This function loads and adds various integration callbacks to the provided instance. The specific callbacks added
|
| 199 |
+
depend on the type of instance provided. All instances receive HUB callbacks, while Trainer instances also receive
|
| 200 |
+
additional callbacks for various integrations like ClearML, Comet, DVC, MLflow, Neptune, Ray Tune, TensorBoard, and
|
| 201 |
+
Weights & Biases.
|
| 202 |
+
|
| 203 |
+
Args:
|
| 204 |
+
instance (Trainer | Predictor | Validator | Exporter): The object instance to which callbacks will be added. The
|
| 205 |
+
type of instance determines which callbacks are loaded.
|
| 206 |
+
|
| 207 |
+
Examples:
|
| 208 |
+
>>> from ultralytics.engine.trainer import BaseTrainer
|
| 209 |
+
>>> trainer = BaseTrainer()
|
| 210 |
+
>>> add_integration_callbacks(trainer)
|
| 211 |
+
"""
|
| 212 |
+
from .hub import callbacks as hub_cb
|
| 213 |
+
from .platform import callbacks as platform_cb
|
| 214 |
+
|
| 215 |
+
# Load Ultralytics callbacks
|
| 216 |
+
callbacks_list = [hub_cb, platform_cb]
|
| 217 |
+
|
| 218 |
+
# Load training callbacks
|
| 219 |
+
if "Trainer" in instance.__class__.__name__:
|
| 220 |
+
from .clearml import callbacks as clear_cb
|
| 221 |
+
from .comet import callbacks as comet_cb
|
| 222 |
+
from .dvc import callbacks as dvc_cb
|
| 223 |
+
from .mlflow import callbacks as mlflow_cb
|
| 224 |
+
from .neptune import callbacks as neptune_cb
|
| 225 |
+
from .raytune import callbacks as tune_cb
|
| 226 |
+
from .tensorboard import callbacks as tb_cb
|
| 227 |
+
from .wb import callbacks as wb_cb
|
| 228 |
+
|
| 229 |
+
callbacks_list.extend([clear_cb, comet_cb, dvc_cb, mlflow_cb, neptune_cb, tune_cb, tb_cb, wb_cb])
|
| 230 |
+
|
| 231 |
+
# Add the callbacks to the callbacks dictionary
|
| 232 |
+
for callbacks in callbacks_list:
|
| 233 |
+
for k, v in callbacks.items():
|
| 234 |
+
if v not in instance.callbacks[k]:
|
| 235 |
+
instance.callbacks[k].append(v)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/clearml.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
|
| 4 |
+
|
| 5 |
+
try:
|
| 6 |
+
assert not TESTS_RUNNING # do not log pytest
|
| 7 |
+
assert SETTINGS["clearml"] is True # verify integration is enabled
|
| 8 |
+
import clearml
|
| 9 |
+
from clearml import Task
|
| 10 |
+
|
| 11 |
+
assert hasattr(clearml, "__version__") # verify package is not directory
|
| 12 |
+
|
| 13 |
+
except (ImportError, AssertionError):
|
| 14 |
+
clearml = None
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def _log_debug_samples(files, title: str = "Debug Samples") -> None:
|
| 18 |
+
"""Log files (images) as debug samples in the ClearML task.
|
| 19 |
+
|
| 20 |
+
Args:
|
| 21 |
+
files (list[Path]): A list of file paths in PosixPath format.
|
| 22 |
+
title (str): A title that groups together images with the same values.
|
| 23 |
+
"""
|
| 24 |
+
import re
|
| 25 |
+
|
| 26 |
+
if task := Task.current_task():
|
| 27 |
+
for f in files:
|
| 28 |
+
if f.exists():
|
| 29 |
+
it = re.search(r"_batch(\d+)", f.name)
|
| 30 |
+
iteration = int(it.groups()[0]) if it else 0
|
| 31 |
+
task.get_logger().report_image(
|
| 32 |
+
title=title, series=f.name.replace(it.group(), ""), local_path=str(f), iteration=iteration
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def _log_plot(title: str, plot_path: str) -> None:
|
| 37 |
+
"""Log an image as a plot in the plot section of ClearML.
|
| 38 |
+
|
| 39 |
+
Args:
|
| 40 |
+
title (str): The title of the plot.
|
| 41 |
+
plot_path (str | Path): The path to the saved image file.
|
| 42 |
+
"""
|
| 43 |
+
import matplotlib.image as mpimg
|
| 44 |
+
import matplotlib.pyplot as plt
|
| 45 |
+
|
| 46 |
+
img = mpimg.imread(plot_path)
|
| 47 |
+
fig = plt.figure()
|
| 48 |
+
ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect="auto", xticks=[], yticks=[]) # no ticks
|
| 49 |
+
ax.imshow(img)
|
| 50 |
+
|
| 51 |
+
Task.current_task().get_logger().report_matplotlib_figure(
|
| 52 |
+
title=title, series="", figure=fig, report_interactive=False
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def on_pretrain_routine_start(trainer) -> None:
|
| 57 |
+
"""Initialize and connect ClearML task at the start of pretraining routine."""
|
| 58 |
+
try:
|
| 59 |
+
if task := Task.current_task():
|
| 60 |
+
# WARNING: make sure the automatic pytorch and matplotlib bindings are disabled!
|
| 61 |
+
# We are logging these plots and model files manually in the integration
|
| 62 |
+
from clearml.binding.frameworks.pytorch_bind import PatchPyTorchModelIO
|
| 63 |
+
from clearml.binding.matplotlib_bind import PatchedMatplotlib
|
| 64 |
+
|
| 65 |
+
PatchPyTorchModelIO.update_current_task(None)
|
| 66 |
+
PatchedMatplotlib.update_current_task(None)
|
| 67 |
+
else:
|
| 68 |
+
task = Task.init(
|
| 69 |
+
project_name=str(trainer.args.project or "Ultralytics").lstrip("/") or "Ultralytics",
|
| 70 |
+
task_name=trainer.args.name,
|
| 71 |
+
tags=["Ultralytics"],
|
| 72 |
+
output_uri=True,
|
| 73 |
+
reuse_last_task_id=False,
|
| 74 |
+
auto_connect_frameworks={"pytorch": False, "matplotlib": False},
|
| 75 |
+
)
|
| 76 |
+
LOGGER.warning(
|
| 77 |
+
"ClearML Initialized a new task. If you want to run remotely, "
|
| 78 |
+
"please add clearml-init and connect your arguments before initializing YOLO."
|
| 79 |
+
)
|
| 80 |
+
task.connect(vars(trainer.args), name="General", ignore_remote_overrides=True)
|
| 81 |
+
except Exception as e:
|
| 82 |
+
LOGGER.warning(f"ClearML installed but not initialized correctly, not logging this run. {e}")
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def on_train_epoch_end(trainer) -> None:
|
| 86 |
+
"""Log debug samples for the first epoch and report current training progress."""
|
| 87 |
+
if task := Task.current_task():
|
| 88 |
+
# Log debug samples for first epoch only
|
| 89 |
+
if trainer.epoch == 1:
|
| 90 |
+
_log_debug_samples(sorted(trainer.save_dir.glob("train_batch*.jpg")), "Mosaic")
|
| 91 |
+
# Report the current training progress
|
| 92 |
+
for k, v in trainer.label_loss_items(trainer.tloss, prefix="train").items():
|
| 93 |
+
task.get_logger().report_scalar("train", k, v, iteration=trainer.epoch)
|
| 94 |
+
for k, v in trainer.lr.items():
|
| 95 |
+
task.get_logger().report_scalar("lr", k, v, iteration=trainer.epoch)
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def on_fit_epoch_end(trainer) -> None:
|
| 99 |
+
"""Report model information and metrics to logger at the end of an epoch."""
|
| 100 |
+
if task := Task.current_task():
|
| 101 |
+
# Report epoch time and validation metrics
|
| 102 |
+
task.get_logger().report_scalar(
|
| 103 |
+
title="Epoch Time", series="Epoch Time", value=trainer.epoch_time, iteration=trainer.epoch
|
| 104 |
+
)
|
| 105 |
+
for k, v in trainer.metrics.items():
|
| 106 |
+
title = k.split("/")[0]
|
| 107 |
+
task.get_logger().report_scalar(title, k, v, iteration=trainer.epoch)
|
| 108 |
+
if trainer.epoch == 0:
|
| 109 |
+
from ultralytics.utils.torch_utils import model_info_for_loggers
|
| 110 |
+
|
| 111 |
+
for k, v in model_info_for_loggers(trainer).items():
|
| 112 |
+
task.get_logger().report_single_value(k, v)
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def on_val_end(validator) -> None:
|
| 116 |
+
"""Log validation results including labels and predictions."""
|
| 117 |
+
if Task.current_task():
|
| 118 |
+
# Log validation labels and predictions
|
| 119 |
+
_log_debug_samples(sorted(validator.save_dir.glob("val*.jpg")), "Validation")
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def on_train_end(trainer) -> None:
|
| 123 |
+
"""Log final model and training results on training completion."""
|
| 124 |
+
if task := Task.current_task():
|
| 125 |
+
# Log final results, confusion matrix and PR plots
|
| 126 |
+
for f in [*trainer.plots.keys(), *trainer.validator.plots.keys()]:
|
| 127 |
+
if "batch" not in f.name:
|
| 128 |
+
_log_plot(title=f.stem, plot_path=f)
|
| 129 |
+
# Report final metrics
|
| 130 |
+
for k, v in trainer.validator.metrics.results_dict.items():
|
| 131 |
+
task.get_logger().report_single_value(k, v)
|
| 132 |
+
# Log the final model
|
| 133 |
+
task.update_output_model(model_path=str(trainer.best), model_name=trainer.args.name, auto_delete_file=False)
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
callbacks = (
|
| 137 |
+
{
|
| 138 |
+
"on_pretrain_routine_start": on_pretrain_routine_start,
|
| 139 |
+
"on_train_epoch_end": on_train_epoch_end,
|
| 140 |
+
"on_fit_epoch_end": on_fit_epoch_end,
|
| 141 |
+
"on_val_end": on_val_end,
|
| 142 |
+
"on_train_end": on_train_end,
|
| 143 |
+
}
|
| 144 |
+
if clearml
|
| 145 |
+
else {}
|
| 146 |
+
)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/comet.py
ADDED
|
@@ -0,0 +1,622 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
from collections.abc import Callable
|
| 6 |
+
from types import SimpleNamespace
|
| 7 |
+
from typing import Any
|
| 8 |
+
|
| 9 |
+
import cv2
|
| 10 |
+
import numpy as np
|
| 11 |
+
|
| 12 |
+
from ultralytics.utils import LOGGER, RANK, SETTINGS, TESTS_RUNNING, ops
|
| 13 |
+
from ultralytics.utils.metrics import ClassifyMetrics, DetMetrics, OBBMetrics, PoseMetrics, SegmentMetrics
|
| 14 |
+
|
| 15 |
+
try:
|
| 16 |
+
assert not TESTS_RUNNING # do not log pytest
|
| 17 |
+
assert SETTINGS["comet"] is True # verify integration is enabled
|
| 18 |
+
import comet_ml
|
| 19 |
+
|
| 20 |
+
assert hasattr(comet_ml, "__version__") # verify package is not directory
|
| 21 |
+
|
| 22 |
+
import os
|
| 23 |
+
from pathlib import Path
|
| 24 |
+
|
| 25 |
+
# Ensures certain logging functions only run for supported tasks
|
| 26 |
+
COMET_SUPPORTED_TASKS = ["detect", "segment"]
|
| 27 |
+
|
| 28 |
+
# Names of plots created by Ultralytics that are logged to Comet
|
| 29 |
+
CONFUSION_MATRIX_PLOT_NAMES = "confusion_matrix", "confusion_matrix_normalized"
|
| 30 |
+
EVALUATION_PLOT_NAMES = "F1_curve", "P_curve", "R_curve", "PR_curve"
|
| 31 |
+
LABEL_PLOT_NAMES = ["labels"]
|
| 32 |
+
SEGMENT_METRICS_PLOT_PREFIX = "Box", "Mask"
|
| 33 |
+
POSE_METRICS_PLOT_PREFIX = "Box", "Pose"
|
| 34 |
+
DETECTION_METRICS_PLOT_PREFIX = ["Box"]
|
| 35 |
+
RESULTS_TABLE_NAME = "results.csv"
|
| 36 |
+
ARGS_YAML_NAME = "args.yaml"
|
| 37 |
+
|
| 38 |
+
_comet_image_prediction_count = 0
|
| 39 |
+
|
| 40 |
+
except (ImportError, AssertionError):
|
| 41 |
+
comet_ml = None
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def _get_comet_mode() -> str:
|
| 45 |
+
"""Return the Comet mode from environment variables, defaulting to 'online'."""
|
| 46 |
+
comet_mode = os.getenv("COMET_MODE")
|
| 47 |
+
if comet_mode is not None:
|
| 48 |
+
LOGGER.warning(
|
| 49 |
+
"The COMET_MODE environment variable is deprecated. "
|
| 50 |
+
"Please use COMET_START_ONLINE to set the Comet experiment mode. "
|
| 51 |
+
"To start an offline Comet experiment, use 'export COMET_START_ONLINE=0'. "
|
| 52 |
+
"If COMET_START_ONLINE is not set or is set to '1', an online Comet experiment will be created."
|
| 53 |
+
)
|
| 54 |
+
return comet_mode
|
| 55 |
+
|
| 56 |
+
return "online"
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def _get_comet_model_name() -> str:
|
| 60 |
+
"""Return the Comet model name from environment variable or default to 'Ultralytics'."""
|
| 61 |
+
return os.getenv("COMET_MODEL_NAME", "Ultralytics")
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def _get_eval_batch_logging_interval() -> int:
|
| 65 |
+
"""Get the evaluation batch logging interval from environment variable or use default value 1."""
|
| 66 |
+
return int(os.getenv("COMET_EVAL_BATCH_LOGGING_INTERVAL", 1))
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def _get_max_image_predictions_to_log() -> int:
|
| 70 |
+
"""Get the maximum number of image predictions to log from environment variables."""
|
| 71 |
+
return int(os.getenv("COMET_MAX_IMAGE_PREDICTIONS", 100))
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def _scale_confidence_score(score: float) -> float:
|
| 75 |
+
"""Scale the confidence score by a factor specified in environment variable."""
|
| 76 |
+
scale = float(os.getenv("COMET_MAX_CONFIDENCE_SCORE", 100.0))
|
| 77 |
+
return score * scale
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def _should_log_confusion_matrix() -> bool:
|
| 81 |
+
"""Determine if the confusion matrix should be logged based on environment variable settings."""
|
| 82 |
+
return os.getenv("COMET_EVAL_LOG_CONFUSION_MATRIX", "false").lower() == "true"
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def _should_log_image_predictions() -> bool:
|
| 86 |
+
"""Determine whether to log image predictions based on environment variable."""
|
| 87 |
+
return os.getenv("COMET_EVAL_LOG_IMAGE_PREDICTIONS", "true").lower() == "true"
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def _resume_or_create_experiment(args: SimpleNamespace) -> None:
|
| 91 |
+
"""Resume CometML experiment or create a new experiment based on args.
|
| 92 |
+
|
| 93 |
+
Ensures that the experiment object is only created in a single process during distributed training.
|
| 94 |
+
|
| 95 |
+
Args:
|
| 96 |
+
args (SimpleNamespace): Training arguments containing project configuration and other parameters.
|
| 97 |
+
"""
|
| 98 |
+
if RANK not in {-1, 0}:
|
| 99 |
+
return
|
| 100 |
+
|
| 101 |
+
# Set environment variable (if not set by the user) to configure the Comet experiment's online mode under the hood.
|
| 102 |
+
# IF COMET_START_ONLINE is set by the user it will override COMET_MODE value.
|
| 103 |
+
if os.getenv("COMET_START_ONLINE") is None:
|
| 104 |
+
comet_mode = _get_comet_mode()
|
| 105 |
+
os.environ["COMET_START_ONLINE"] = "1" if comet_mode != "offline" else "0"
|
| 106 |
+
|
| 107 |
+
try:
|
| 108 |
+
_project_name = os.getenv("COMET_PROJECT_NAME", args.project)
|
| 109 |
+
experiment = comet_ml.start(project_name=_project_name)
|
| 110 |
+
experiment.log_parameters(vars(args))
|
| 111 |
+
experiment.log_others(
|
| 112 |
+
{
|
| 113 |
+
"eval_batch_logging_interval": _get_eval_batch_logging_interval(),
|
| 114 |
+
"log_confusion_matrix_on_eval": _should_log_confusion_matrix(),
|
| 115 |
+
"log_image_predictions": _should_log_image_predictions(),
|
| 116 |
+
"max_image_predictions": _get_max_image_predictions_to_log(),
|
| 117 |
+
}
|
| 118 |
+
)
|
| 119 |
+
experiment.log_other("Created from", "ultralytics")
|
| 120 |
+
|
| 121 |
+
except Exception as e:
|
| 122 |
+
LOGGER.warning(f"Comet installed but not initialized correctly, not logging this run. {e}")
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def _fetch_trainer_metadata(trainer) -> dict:
|
| 126 |
+
"""Return metadata for YOLO training including epoch and asset saving status.
|
| 127 |
+
|
| 128 |
+
Args:
|
| 129 |
+
trainer (ultralytics.engine.trainer.BaseTrainer): The YOLO trainer object containing training state and config.
|
| 130 |
+
|
| 131 |
+
Returns:
|
| 132 |
+
(dict): Dictionary containing current epoch, step, save assets flag, and final epoch flag.
|
| 133 |
+
"""
|
| 134 |
+
curr_epoch = trainer.epoch + 1
|
| 135 |
+
|
| 136 |
+
train_num_steps_per_epoch = len(trainer.train_loader.dataset) // trainer.batch_size
|
| 137 |
+
curr_step = curr_epoch * train_num_steps_per_epoch
|
| 138 |
+
final_epoch = curr_epoch == trainer.epochs
|
| 139 |
+
|
| 140 |
+
save = trainer.args.save
|
| 141 |
+
save_period = trainer.args.save_period
|
| 142 |
+
save_interval = curr_epoch % save_period == 0
|
| 143 |
+
save_assets = save and save_period > 0 and save_interval and not final_epoch
|
| 144 |
+
|
| 145 |
+
return dict(curr_epoch=curr_epoch, curr_step=curr_step, save_assets=save_assets, final_epoch=final_epoch)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def _scale_bounding_box_to_original_image_shape(
|
| 149 |
+
box, resized_image_shape, original_image_shape, ratio_pad
|
| 150 |
+
) -> list[float]:
|
| 151 |
+
"""Scale bounding box from resized image coordinates to original image coordinates.
|
| 152 |
+
|
| 153 |
+
YOLO resizes images during training and the label values are normalized based on this resized shape. This function
|
| 154 |
+
rescales the bounding box labels to the original image shape.
|
| 155 |
+
|
| 156 |
+
Args:
|
| 157 |
+
box (torch.Tensor): Bounding box in normalized xywh format.
|
| 158 |
+
resized_image_shape (tuple): Shape of the resized image (height, width).
|
| 159 |
+
original_image_shape (tuple): Shape of the original image (height, width).
|
| 160 |
+
ratio_pad (tuple): Ratio and padding information for scaling.
|
| 161 |
+
|
| 162 |
+
Returns:
|
| 163 |
+
(list[float]): Scaled bounding box coordinates in xywh format with top-left corner adjustment.
|
| 164 |
+
"""
|
| 165 |
+
resized_image_height, resized_image_width = resized_image_shape
|
| 166 |
+
|
| 167 |
+
# Convert normalized xywh format predictions to xyxy in resized scale format
|
| 168 |
+
box = ops.xywhn2xyxy(box, h=resized_image_height, w=resized_image_width)
|
| 169 |
+
# Scale box predictions from resized image scale back to original image scale
|
| 170 |
+
box = ops.scale_boxes(resized_image_shape, box, original_image_shape, ratio_pad)
|
| 171 |
+
# Convert bounding box format from xyxy to xywh for Comet logging
|
| 172 |
+
box = ops.xyxy2xywh(box)
|
| 173 |
+
# Adjust xy center to correspond top-left corner
|
| 174 |
+
box[:2] -= box[2:] / 2
|
| 175 |
+
box = box.tolist()
|
| 176 |
+
|
| 177 |
+
return box
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
def _format_ground_truth_annotations_for_detection(img_idx, image_path, batch, class_name_map=None) -> dict | None:
|
| 181 |
+
"""Format ground truth annotations for object detection.
|
| 182 |
+
|
| 183 |
+
This function processes ground truth annotations from a batch of images for object detection tasks. It extracts
|
| 184 |
+
bounding boxes, class labels, and other metadata for a specific image in the batch, and formats them for
|
| 185 |
+
visualization or evaluation.
|
| 186 |
+
|
| 187 |
+
Args:
|
| 188 |
+
img_idx (int): Index of the image in the batch to process.
|
| 189 |
+
image_path (str | Path): Path to the image file.
|
| 190 |
+
batch (dict): Batch dictionary containing detection data with keys:
|
| 191 |
+
- 'batch_idx': Tensor of batch indices
|
| 192 |
+
- 'bboxes': Tensor of bounding boxes in normalized xywh format
|
| 193 |
+
- 'cls': Tensor of class labels
|
| 194 |
+
- 'ori_shape': Original image shapes
|
| 195 |
+
- 'resized_shape': Resized image shapes
|
| 196 |
+
- 'ratio_pad': Ratio and padding information
|
| 197 |
+
class_name_map (dict, optional): Mapping from class indices to class names.
|
| 198 |
+
|
| 199 |
+
Returns:
|
| 200 |
+
(dict | None): Formatted ground truth annotations with keys 'name' and 'data', where 'data' is a list of
|
| 201 |
+
annotation dicts each containing 'boxes', 'label', and 'score' keys. Returns None if no bounding boxes are
|
| 202 |
+
found for the image.
|
| 203 |
+
"""
|
| 204 |
+
indices = batch["batch_idx"] == img_idx
|
| 205 |
+
bboxes = batch["bboxes"][indices]
|
| 206 |
+
if len(bboxes) == 0:
|
| 207 |
+
LOGGER.debug(f"Comet Image: {image_path} has no bounding boxes labels")
|
| 208 |
+
return None
|
| 209 |
+
|
| 210 |
+
cls_labels = batch["cls"][indices].squeeze(1).tolist()
|
| 211 |
+
if class_name_map:
|
| 212 |
+
cls_labels = [str(class_name_map[label]) for label in cls_labels]
|
| 213 |
+
|
| 214 |
+
original_image_shape = batch["ori_shape"][img_idx]
|
| 215 |
+
resized_image_shape = batch["resized_shape"][img_idx]
|
| 216 |
+
ratio_pad = batch["ratio_pad"][img_idx]
|
| 217 |
+
|
| 218 |
+
data = []
|
| 219 |
+
for box, label in zip(bboxes, cls_labels):
|
| 220 |
+
box = _scale_bounding_box_to_original_image_shape(box, resized_image_shape, original_image_shape, ratio_pad)
|
| 221 |
+
data.append(
|
| 222 |
+
{
|
| 223 |
+
"boxes": [box],
|
| 224 |
+
"label": f"gt_{label}",
|
| 225 |
+
"score": _scale_confidence_score(1.0),
|
| 226 |
+
}
|
| 227 |
+
)
|
| 228 |
+
|
| 229 |
+
return {"name": "ground_truth", "data": data}
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
def _format_prediction_annotations(image_path, metadata, class_label_map=None, class_map=None) -> dict | None:
|
| 233 |
+
"""Format YOLO predictions for object detection visualization.
|
| 234 |
+
|
| 235 |
+
Args:
|
| 236 |
+
image_path (Path): Path to the image file.
|
| 237 |
+
metadata (dict): Prediction metadata containing bounding boxes and class information.
|
| 238 |
+
class_label_map (dict, optional): Mapping from class indices to class names.
|
| 239 |
+
class_map (dict, optional): Additional class mapping for label conversion.
|
| 240 |
+
|
| 241 |
+
Returns:
|
| 242 |
+
(dict | None): Formatted prediction annotations or None if no predictions exist.
|
| 243 |
+
"""
|
| 244 |
+
stem = image_path.stem
|
| 245 |
+
image_id = int(stem) if stem.isnumeric() else stem
|
| 246 |
+
|
| 247 |
+
predictions = metadata.get(image_id)
|
| 248 |
+
if not predictions:
|
| 249 |
+
LOGGER.debug(f"Comet Image: {image_path} has no bounding boxes predictions")
|
| 250 |
+
return None
|
| 251 |
+
|
| 252 |
+
# apply the mapping that was used to map the predicted classes when the JSON was created
|
| 253 |
+
if class_label_map and class_map:
|
| 254 |
+
class_label_map = {class_map[k]: v for k, v in class_label_map.items()}
|
| 255 |
+
try:
|
| 256 |
+
# import faster_coco_eval utilities to decompress annotations for various tasks, e.g. segmentation
|
| 257 |
+
from faster_coco_eval.core.mask import decode
|
| 258 |
+
except ImportError:
|
| 259 |
+
decode = None
|
| 260 |
+
|
| 261 |
+
data = []
|
| 262 |
+
for prediction in predictions:
|
| 263 |
+
boxes = prediction["bbox"]
|
| 264 |
+
score = _scale_confidence_score(prediction["score"])
|
| 265 |
+
cls_label = prediction["category_id"]
|
| 266 |
+
if class_label_map:
|
| 267 |
+
cls_label = str(class_label_map[cls_label])
|
| 268 |
+
|
| 269 |
+
annotation_data = {"boxes": [boxes], "label": cls_label, "score": score}
|
| 270 |
+
|
| 271 |
+
if decode is not None:
|
| 272 |
+
# do segmentation processing only if we are able to decode it
|
| 273 |
+
segments = prediction.get("segmentation", None)
|
| 274 |
+
if segments is not None:
|
| 275 |
+
segments = _extract_segmentation_annotation(segments, decode)
|
| 276 |
+
if segments is not None:
|
| 277 |
+
annotation_data["points"] = segments
|
| 278 |
+
|
| 279 |
+
data.append(annotation_data)
|
| 280 |
+
|
| 281 |
+
return {"name": "prediction", "data": data}
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
def _extract_segmentation_annotation(segmentation_raw: str, decode: Callable) -> list[list[Any]] | None:
|
| 285 |
+
"""Extract segmentation annotation from compressed segmentations as list of polygons.
|
| 286 |
+
|
| 287 |
+
Args:
|
| 288 |
+
segmentation_raw (str): Raw segmentation data in compressed format.
|
| 289 |
+
decode (Callable): Function to decode the compressed segmentation data.
|
| 290 |
+
|
| 291 |
+
Returns:
|
| 292 |
+
(list[list[Any]] | None): List of polygon points or None if extraction fails.
|
| 293 |
+
"""
|
| 294 |
+
try:
|
| 295 |
+
mask = decode(segmentation_raw)
|
| 296 |
+
contours, _ = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
|
| 297 |
+
annotations = [np.array(polygon).squeeze() for polygon in contours if len(polygon) >= 3]
|
| 298 |
+
return [annotation.ravel().tolist() for annotation in annotations]
|
| 299 |
+
except Exception as e:
|
| 300 |
+
LOGGER.warning(f"Comet Failed to extract segmentation annotation: {e}")
|
| 301 |
+
return None
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
def _fetch_annotations(img_idx, image_path, batch, prediction_metadata_map, class_label_map, class_map) -> list | None:
|
| 305 |
+
"""Join the ground truth and prediction annotations if they exist.
|
| 306 |
+
|
| 307 |
+
Args:
|
| 308 |
+
img_idx (int): Index of the image in the batch.
|
| 309 |
+
image_path (Path): Path to the image file.
|
| 310 |
+
batch (dict): Batch data containing ground truth annotations.
|
| 311 |
+
prediction_metadata_map (dict): Map of prediction metadata by image ID.
|
| 312 |
+
class_label_map (dict): Mapping from class indices to class names.
|
| 313 |
+
class_map (dict): Additional class mapping for label conversion.
|
| 314 |
+
|
| 315 |
+
Returns:
|
| 316 |
+
(list | None): List of annotation dictionaries or None if no annotations exist.
|
| 317 |
+
"""
|
| 318 |
+
ground_truth_annotations = _format_ground_truth_annotations_for_detection(
|
| 319 |
+
img_idx, image_path, batch, class_label_map
|
| 320 |
+
)
|
| 321 |
+
prediction_annotations = _format_prediction_annotations(
|
| 322 |
+
image_path, prediction_metadata_map, class_label_map, class_map
|
| 323 |
+
)
|
| 324 |
+
|
| 325 |
+
annotations = [
|
| 326 |
+
annotation for annotation in [ground_truth_annotations, prediction_annotations] if annotation is not None
|
| 327 |
+
]
|
| 328 |
+
return [annotations] if annotations else None
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
def _create_prediction_metadata_map(model_predictions) -> dict:
|
| 332 |
+
"""Create metadata map for model predictions by grouping them based on image ID."""
|
| 333 |
+
pred_metadata_map = {}
|
| 334 |
+
for prediction in model_predictions:
|
| 335 |
+
pred_metadata_map.setdefault(prediction["image_id"], [])
|
| 336 |
+
pred_metadata_map[prediction["image_id"]].append(prediction)
|
| 337 |
+
|
| 338 |
+
return pred_metadata_map
|
| 339 |
+
|
| 340 |
+
|
| 341 |
+
def _log_confusion_matrix(experiment, trainer, curr_step, curr_epoch) -> None:
|
| 342 |
+
"""Log the confusion matrix to Comet experiment."""
|
| 343 |
+
conf_mat = trainer.validator.confusion_matrix.matrix
|
| 344 |
+
names = [*list(trainer.data["names"].values()), "background"]
|
| 345 |
+
experiment.log_confusion_matrix(
|
| 346 |
+
matrix=conf_mat, labels=names, max_categories=len(names), epoch=curr_epoch, step=curr_step
|
| 347 |
+
)
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
def _log_images(experiment, image_paths, curr_step: int | None, annotations=None) -> None:
|
| 351 |
+
"""Log images to the experiment with optional annotations.
|
| 352 |
+
|
| 353 |
+
This function logs images to a Comet ML experiment, optionally including annotation data for visualization such as
|
| 354 |
+
bounding boxes or segmentation masks.
|
| 355 |
+
|
| 356 |
+
Args:
|
| 357 |
+
experiment (comet_ml.CometExperiment): The Comet ML experiment to log images to.
|
| 358 |
+
image_paths (list[Path]): List of paths to images that will be logged.
|
| 359 |
+
curr_step (int | None): Current training step/iteration for tracking in the experiment timeline.
|
| 360 |
+
annotations (list[list[dict]], optional): Nested list of annotation dictionaries for each image. Each annotation
|
| 361 |
+
contains visualization data like bounding boxes, labels, and confidence scores.
|
| 362 |
+
"""
|
| 363 |
+
if annotations:
|
| 364 |
+
for image_path, annotation in zip(image_paths, annotations):
|
| 365 |
+
experiment.log_image(image_path, name=image_path.stem, step=curr_step, annotations=annotation)
|
| 366 |
+
|
| 367 |
+
else:
|
| 368 |
+
for image_path in image_paths:
|
| 369 |
+
experiment.log_image(image_path, name=image_path.stem, step=curr_step)
|
| 370 |
+
|
| 371 |
+
|
| 372 |
+
def _log_image_predictions(experiment, validator, curr_step) -> None:
|
| 373 |
+
"""Log image predictions to a Comet ML experiment during model validation.
|
| 374 |
+
|
| 375 |
+
This function processes validation data and formats both ground truth and prediction annotations for visualization
|
| 376 |
+
in the Comet dashboard. The function respects configured limits on the number of images to log.
|
| 377 |
+
|
| 378 |
+
Args:
|
| 379 |
+
experiment (comet_ml.CometExperiment): The Comet ML experiment to log to.
|
| 380 |
+
validator (BaseValidator): The validator instance containing validation data and predictions.
|
| 381 |
+
curr_step (int): The current training step for logging timeline.
|
| 382 |
+
|
| 383 |
+
Notes:
|
| 384 |
+
This function uses global state to track the number of logged predictions across calls.
|
| 385 |
+
It only logs predictions for supported tasks defined in COMET_SUPPORTED_TASKS.
|
| 386 |
+
The number of logged images is limited by the COMET_MAX_IMAGE_PREDICTIONS environment variable.
|
| 387 |
+
"""
|
| 388 |
+
global _comet_image_prediction_count
|
| 389 |
+
|
| 390 |
+
task = validator.args.task
|
| 391 |
+
if task not in COMET_SUPPORTED_TASKS:
|
| 392 |
+
return
|
| 393 |
+
|
| 394 |
+
jdict = validator.jdict
|
| 395 |
+
if not jdict:
|
| 396 |
+
return
|
| 397 |
+
|
| 398 |
+
predictions_metadata_map = _create_prediction_metadata_map(jdict)
|
| 399 |
+
dataloader = validator.dataloader
|
| 400 |
+
class_label_map = validator.names
|
| 401 |
+
class_map = getattr(validator, "class_map", None)
|
| 402 |
+
|
| 403 |
+
batch_logging_interval = _get_eval_batch_logging_interval()
|
| 404 |
+
max_image_predictions = _get_max_image_predictions_to_log()
|
| 405 |
+
|
| 406 |
+
for batch_idx, batch in enumerate(dataloader):
|
| 407 |
+
if (batch_idx + 1) % batch_logging_interval != 0:
|
| 408 |
+
continue
|
| 409 |
+
|
| 410 |
+
image_paths = batch["im_file"]
|
| 411 |
+
for img_idx, image_path in enumerate(image_paths):
|
| 412 |
+
if _comet_image_prediction_count >= max_image_predictions:
|
| 413 |
+
return
|
| 414 |
+
|
| 415 |
+
image_path = Path(image_path)
|
| 416 |
+
annotations = _fetch_annotations(
|
| 417 |
+
img_idx,
|
| 418 |
+
image_path,
|
| 419 |
+
batch,
|
| 420 |
+
predictions_metadata_map,
|
| 421 |
+
class_label_map,
|
| 422 |
+
class_map=class_map,
|
| 423 |
+
)
|
| 424 |
+
_log_images(
|
| 425 |
+
experiment,
|
| 426 |
+
[image_path],
|
| 427 |
+
curr_step,
|
| 428 |
+
annotations=annotations,
|
| 429 |
+
)
|
| 430 |
+
_comet_image_prediction_count += 1
|
| 431 |
+
|
| 432 |
+
|
| 433 |
+
def _log_plots(experiment, trainer) -> None:
|
| 434 |
+
"""Log evaluation plots and label plots for the experiment.
|
| 435 |
+
|
| 436 |
+
This function logs various evaluation plots and confusion matrices to the experiment tracking system. It handles
|
| 437 |
+
different types of metrics (SegmentMetrics, PoseMetrics, DetMetrics, OBBMetrics) and logs the appropriate plots for
|
| 438 |
+
each type.
|
| 439 |
+
|
| 440 |
+
Args:
|
| 441 |
+
experiment (comet_ml.CometExperiment): The Comet ML experiment to log plots to.
|
| 442 |
+
trainer (ultralytics.engine.trainer.BaseTrainer): The trainer object containing validation metrics and save
|
| 443 |
+
directory information.
|
| 444 |
+
|
| 445 |
+
Examples:
|
| 446 |
+
>>> from ultralytics.utils.callbacks.comet import _log_plots
|
| 447 |
+
>>> _log_plots(experiment, trainer)
|
| 448 |
+
"""
|
| 449 |
+
plot_filenames = None
|
| 450 |
+
if isinstance(trainer.validator.metrics, SegmentMetrics):
|
| 451 |
+
plot_filenames = [
|
| 452 |
+
trainer.save_dir / f"{prefix}{plots}.png"
|
| 453 |
+
for plots in EVALUATION_PLOT_NAMES
|
| 454 |
+
for prefix in SEGMENT_METRICS_PLOT_PREFIX
|
| 455 |
+
]
|
| 456 |
+
elif isinstance(trainer.validator.metrics, PoseMetrics):
|
| 457 |
+
plot_filenames = [
|
| 458 |
+
trainer.save_dir / f"{prefix}{plots}.png"
|
| 459 |
+
for plots in EVALUATION_PLOT_NAMES
|
| 460 |
+
for prefix in POSE_METRICS_PLOT_PREFIX
|
| 461 |
+
]
|
| 462 |
+
elif isinstance(trainer.validator.metrics, (DetMetrics, OBBMetrics)):
|
| 463 |
+
plot_filenames = [
|
| 464 |
+
trainer.save_dir / f"{prefix}{plots}.png"
|
| 465 |
+
for plots in EVALUATION_PLOT_NAMES
|
| 466 |
+
for prefix in DETECTION_METRICS_PLOT_PREFIX
|
| 467 |
+
]
|
| 468 |
+
|
| 469 |
+
if plot_filenames is not None:
|
| 470 |
+
_log_images(experiment, plot_filenames, None)
|
| 471 |
+
|
| 472 |
+
confusion_matrix_filenames = [trainer.save_dir / f"{plots}.png" for plots in CONFUSION_MATRIX_PLOT_NAMES]
|
| 473 |
+
_log_images(experiment, confusion_matrix_filenames, None)
|
| 474 |
+
|
| 475 |
+
if not isinstance(trainer.validator.metrics, ClassifyMetrics):
|
| 476 |
+
label_plot_filenames = [trainer.save_dir / f"{labels}.jpg" for labels in LABEL_PLOT_NAMES]
|
| 477 |
+
_log_images(experiment, label_plot_filenames, None)
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
def _log_model(experiment, trainer) -> None:
|
| 481 |
+
"""Log the best-trained model to Comet.ml."""
|
| 482 |
+
model_name = _get_comet_model_name()
|
| 483 |
+
experiment.log_model(model_name, file_or_folder=str(trainer.best), file_name="best.pt", overwrite=True)
|
| 484 |
+
|
| 485 |
+
|
| 486 |
+
def _log_image_batches(experiment, trainer, curr_step: int) -> None:
|
| 487 |
+
"""Log samples of image batches for train and validation."""
|
| 488 |
+
_log_images(experiment, trainer.save_dir.glob("train_batch*.jpg"), curr_step)
|
| 489 |
+
_log_images(experiment, trainer.save_dir.glob("val_batch*.jpg"), curr_step)
|
| 490 |
+
|
| 491 |
+
|
| 492 |
+
def _log_asset(experiment, asset_path) -> None:
|
| 493 |
+
"""Logs a specific asset file to the given experiment.
|
| 494 |
+
|
| 495 |
+
This function facilitates logging an asset, such as a file, to the provided
|
| 496 |
+
experiment. It enables integration with experiment tracking platforms.
|
| 497 |
+
|
| 498 |
+
Args:
|
| 499 |
+
experiment (comet_ml.CometExperiment): The experiment instance to which the asset will be logged.
|
| 500 |
+
asset_path (Path): The file path of the asset to log.
|
| 501 |
+
"""
|
| 502 |
+
experiment.log_asset(asset_path)
|
| 503 |
+
|
| 504 |
+
|
| 505 |
+
def _log_table(experiment, table_path) -> None:
|
| 506 |
+
"""Logs a table to the provided experiment.
|
| 507 |
+
|
| 508 |
+
This function is used to log a table file to the given experiment. The table is identified by its file path.
|
| 509 |
+
|
| 510 |
+
Args:
|
| 511 |
+
experiment (comet_ml.CometExperiment): The experiment object where the table file will be logged.
|
| 512 |
+
table_path (Path): The file path of the table to be logged.
|
| 513 |
+
"""
|
| 514 |
+
experiment.log_table(str(table_path))
|
| 515 |
+
|
| 516 |
+
|
| 517 |
+
def on_pretrain_routine_start(trainer) -> None:
|
| 518 |
+
"""Create or resume a CometML experiment at the start of a YOLO pre-training routine."""
|
| 519 |
+
_resume_or_create_experiment(trainer.args)
|
| 520 |
+
|
| 521 |
+
|
| 522 |
+
def on_train_epoch_end(trainer) -> None:
|
| 523 |
+
"""Log metrics and save batch images at the end of training epochs."""
|
| 524 |
+
experiment = comet_ml.get_running_experiment()
|
| 525 |
+
if not experiment:
|
| 526 |
+
return
|
| 527 |
+
|
| 528 |
+
metadata = _fetch_trainer_metadata(trainer)
|
| 529 |
+
curr_epoch = metadata["curr_epoch"]
|
| 530 |
+
curr_step = metadata["curr_step"]
|
| 531 |
+
|
| 532 |
+
experiment.log_metrics(trainer.label_loss_items(trainer.tloss, prefix="train"), step=curr_step, epoch=curr_epoch)
|
| 533 |
+
|
| 534 |
+
|
| 535 |
+
def on_fit_epoch_end(trainer) -> None:
|
| 536 |
+
"""Log model assets at the end of each epoch during training.
|
| 537 |
+
|
| 538 |
+
This function is called at the end of each training epoch to log metrics, learning rates, and model information to a
|
| 539 |
+
Comet ML experiment. It also logs model assets, confusion matrices, and image predictions based on configuration
|
| 540 |
+
settings.
|
| 541 |
+
|
| 542 |
+
The function retrieves the current Comet ML experiment and logs various training metrics. If it's the first epoch,
|
| 543 |
+
it also logs model information. On specified save intervals, it logs the model, confusion matrix (if enabled), and
|
| 544 |
+
image predictions (if enabled).
|
| 545 |
+
|
| 546 |
+
Args:
|
| 547 |
+
trainer (BaseTrainer): The YOLO trainer object containing training state, metrics, and configuration.
|
| 548 |
+
|
| 549 |
+
Examples:
|
| 550 |
+
>>> # Inside a training loop
|
| 551 |
+
>>> on_fit_epoch_end(trainer) # Log metrics and assets to Comet ML
|
| 552 |
+
"""
|
| 553 |
+
experiment = comet_ml.get_running_experiment()
|
| 554 |
+
if not experiment:
|
| 555 |
+
return
|
| 556 |
+
|
| 557 |
+
metadata = _fetch_trainer_metadata(trainer)
|
| 558 |
+
curr_epoch = metadata["curr_epoch"]
|
| 559 |
+
curr_step = metadata["curr_step"]
|
| 560 |
+
save_assets = metadata["save_assets"]
|
| 561 |
+
|
| 562 |
+
experiment.log_metrics(trainer.metrics, step=curr_step, epoch=curr_epoch)
|
| 563 |
+
experiment.log_metrics(trainer.lr, step=curr_step, epoch=curr_epoch)
|
| 564 |
+
if curr_epoch == 1:
|
| 565 |
+
from ultralytics.utils.torch_utils import model_info_for_loggers
|
| 566 |
+
|
| 567 |
+
experiment.log_metrics(model_info_for_loggers(trainer), step=curr_step, epoch=curr_epoch)
|
| 568 |
+
|
| 569 |
+
if not save_assets:
|
| 570 |
+
return
|
| 571 |
+
|
| 572 |
+
_log_model(experiment, trainer)
|
| 573 |
+
if _should_log_confusion_matrix():
|
| 574 |
+
_log_confusion_matrix(experiment, trainer, curr_step, curr_epoch)
|
| 575 |
+
if _should_log_image_predictions():
|
| 576 |
+
_log_image_predictions(experiment, trainer.validator, curr_step)
|
| 577 |
+
|
| 578 |
+
|
| 579 |
+
def on_train_end(trainer) -> None:
|
| 580 |
+
"""Perform operations at the end of training."""
|
| 581 |
+
experiment = comet_ml.get_running_experiment()
|
| 582 |
+
if not experiment:
|
| 583 |
+
return
|
| 584 |
+
|
| 585 |
+
metadata = _fetch_trainer_metadata(trainer)
|
| 586 |
+
curr_epoch = metadata["curr_epoch"]
|
| 587 |
+
curr_step = metadata["curr_step"]
|
| 588 |
+
plots = trainer.args.plots
|
| 589 |
+
|
| 590 |
+
_log_model(experiment, trainer)
|
| 591 |
+
if plots:
|
| 592 |
+
_log_plots(experiment, trainer)
|
| 593 |
+
|
| 594 |
+
_log_confusion_matrix(experiment, trainer, curr_step, curr_epoch)
|
| 595 |
+
_log_image_predictions(experiment, trainer.validator, curr_step)
|
| 596 |
+
_log_image_batches(experiment, trainer, curr_step)
|
| 597 |
+
# log results table
|
| 598 |
+
table_path = trainer.save_dir / RESULTS_TABLE_NAME
|
| 599 |
+
if table_path.exists():
|
| 600 |
+
_log_table(experiment, table_path)
|
| 601 |
+
|
| 602 |
+
# log arguments YAML
|
| 603 |
+
args_path = trainer.save_dir / ARGS_YAML_NAME
|
| 604 |
+
if args_path.exists():
|
| 605 |
+
_log_asset(experiment, args_path)
|
| 606 |
+
|
| 607 |
+
experiment.end()
|
| 608 |
+
|
| 609 |
+
global _comet_image_prediction_count
|
| 610 |
+
_comet_image_prediction_count = 0
|
| 611 |
+
|
| 612 |
+
|
| 613 |
+
callbacks = (
|
| 614 |
+
{
|
| 615 |
+
"on_pretrain_routine_start": on_pretrain_routine_start,
|
| 616 |
+
"on_train_epoch_end": on_train_epoch_end,
|
| 617 |
+
"on_fit_epoch_end": on_fit_epoch_end,
|
| 618 |
+
"on_train_end": on_train_end,
|
| 619 |
+
}
|
| 620 |
+
if comet_ml
|
| 621 |
+
else {}
|
| 622 |
+
)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/dvc.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, checks
|
| 6 |
+
|
| 7 |
+
try:
|
| 8 |
+
assert not TESTS_RUNNING # do not log pytest
|
| 9 |
+
assert SETTINGS["dvc"] is True # verify integration is enabled
|
| 10 |
+
import dvclive
|
| 11 |
+
|
| 12 |
+
assert checks.check_version("dvclive", "2.11.0", verbose=True)
|
| 13 |
+
|
| 14 |
+
import os
|
| 15 |
+
import re
|
| 16 |
+
|
| 17 |
+
# DVCLive logger instance
|
| 18 |
+
live = None
|
| 19 |
+
_processed_plots = {}
|
| 20 |
+
|
| 21 |
+
# `on_fit_epoch_end` is called on final validation (probably need to be fixed) for now this is the way we
|
| 22 |
+
# distinguish final evaluation of the best model vs last epoch validation
|
| 23 |
+
_training_epoch = False
|
| 24 |
+
|
| 25 |
+
except (ImportError, AssertionError, TypeError):
|
| 26 |
+
dvclive = None
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def _log_images(path: Path, prefix: str = "") -> None:
|
| 30 |
+
"""Log images at specified path with an optional prefix using DVCLive.
|
| 31 |
+
|
| 32 |
+
This function logs images found at the given path to DVCLive, organizing them by batch to enable slider
|
| 33 |
+
functionality in the UI. It processes image filenames to extract batch information and restructures the path
|
| 34 |
+
accordingly.
|
| 35 |
+
|
| 36 |
+
Args:
|
| 37 |
+
path (Path): Path to the image file to be logged.
|
| 38 |
+
prefix (str, optional): Optional prefix to add to the image name when logging.
|
| 39 |
+
|
| 40 |
+
Examples:
|
| 41 |
+
>>> from pathlib import Path
|
| 42 |
+
>>> _log_images(Path("runs/train/exp/val_batch0_pred.jpg"), prefix="validation")
|
| 43 |
+
"""
|
| 44 |
+
if live:
|
| 45 |
+
name = path.name
|
| 46 |
+
|
| 47 |
+
# Group images by batch to enable sliders in UI
|
| 48 |
+
if m := re.search(r"_batch(\d+)", name):
|
| 49 |
+
ni = m[1]
|
| 50 |
+
new_stem = re.sub(r"_batch(\d+)", "_batch", path.stem)
|
| 51 |
+
name = (Path(new_stem) / ni).with_suffix(path.suffix)
|
| 52 |
+
|
| 53 |
+
live.log_image(os.path.join(prefix, name), path)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def _log_plots(plots: dict, prefix: str = "") -> None:
|
| 57 |
+
"""Log plot images for training progress if they have not been previously processed.
|
| 58 |
+
|
| 59 |
+
Args:
|
| 60 |
+
plots (dict): Dictionary containing plot information with timestamps.
|
| 61 |
+
prefix (str, optional): Optional prefix to add to the logged image paths.
|
| 62 |
+
"""
|
| 63 |
+
for name, params in plots.items():
|
| 64 |
+
timestamp = params["timestamp"]
|
| 65 |
+
if _processed_plots.get(name) != timestamp:
|
| 66 |
+
_log_images(name, prefix)
|
| 67 |
+
_processed_plots[name] = timestamp
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _log_confusion_matrix(validator) -> None:
|
| 71 |
+
"""Log confusion matrix for a validator using DVCLive.
|
| 72 |
+
|
| 73 |
+
This function processes the confusion matrix from a validator object and logs it to DVCLive by converting the matrix
|
| 74 |
+
into lists of target and prediction labels.
|
| 75 |
+
|
| 76 |
+
Args:
|
| 77 |
+
validator (BaseValidator): The validator object containing the confusion matrix and class names. Must have
|
| 78 |
+
attributes confusion_matrix.matrix, confusion_matrix.task, and names.
|
| 79 |
+
"""
|
| 80 |
+
targets = []
|
| 81 |
+
preds = []
|
| 82 |
+
matrix = validator.confusion_matrix.matrix
|
| 83 |
+
names = list(validator.names.values())
|
| 84 |
+
if validator.confusion_matrix.task in {"detect", "obb"}:
|
| 85 |
+
names += ["background"]
|
| 86 |
+
|
| 87 |
+
for ti, pred in enumerate(matrix.T.astype(int)):
|
| 88 |
+
for pi, num in enumerate(pred):
|
| 89 |
+
targets.extend([names[ti]] * num)
|
| 90 |
+
preds.extend([names[pi]] * num)
|
| 91 |
+
|
| 92 |
+
live.log_sklearn_plot("confusion_matrix", targets, preds, name="cf.json", normalized=True)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def on_pretrain_routine_start(trainer) -> None:
|
| 96 |
+
"""Initialize DVCLive logger for training metadata during pre-training routine."""
|
| 97 |
+
try:
|
| 98 |
+
global live
|
| 99 |
+
live = dvclive.Live(save_dvc_exp=True, cache_images=True)
|
| 100 |
+
LOGGER.info("DVCLive is detected and auto logging is enabled (run 'yolo settings dvc=False' to disable).")
|
| 101 |
+
except Exception as e:
|
| 102 |
+
LOGGER.warning(f"DVCLive installed but not initialized correctly, not logging this run. {e}")
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def on_pretrain_routine_end(trainer) -> None:
|
| 106 |
+
"""Log plots related to the training process at the end of the pretraining routine."""
|
| 107 |
+
_log_plots(trainer.plots, "train")
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def on_train_start(trainer) -> None:
|
| 111 |
+
"""Log the training parameters if DVCLive logging is active."""
|
| 112 |
+
if live:
|
| 113 |
+
live.log_params(trainer.args)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def on_train_epoch_start(trainer) -> None:
|
| 117 |
+
"""Set the global variable _training_epoch value to True at the start of each training epoch."""
|
| 118 |
+
global _training_epoch
|
| 119 |
+
_training_epoch = True
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def on_fit_epoch_end(trainer) -> None:
|
| 123 |
+
"""Log training metrics, model info, and advance to next step at the end of each fit epoch.
|
| 124 |
+
|
| 125 |
+
This function is called at the end of each fit epoch during training. It logs various metrics including training
|
| 126 |
+
loss items, validation metrics, and learning rates. On the first epoch, it also logs model
|
| 127 |
+
information. Additionally, it logs training and validation plots and advances the DVCLive step counter.
|
| 128 |
+
|
| 129 |
+
Args:
|
| 130 |
+
trainer (BaseTrainer): The trainer object containing training state, metrics, and plots.
|
| 131 |
+
|
| 132 |
+
Notes:
|
| 133 |
+
This function only performs logging operations when DVCLive logging is active and during a training epoch.
|
| 134 |
+
The global variable _training_epoch is used to track whether the current epoch is a training epoch.
|
| 135 |
+
"""
|
| 136 |
+
global _training_epoch
|
| 137 |
+
if live and _training_epoch:
|
| 138 |
+
all_metrics = {**trainer.label_loss_items(trainer.tloss, prefix="train"), **trainer.metrics, **trainer.lr}
|
| 139 |
+
for metric, value in all_metrics.items():
|
| 140 |
+
live.log_metric(metric, value)
|
| 141 |
+
|
| 142 |
+
if trainer.epoch == 0:
|
| 143 |
+
from ultralytics.utils.torch_utils import model_info_for_loggers
|
| 144 |
+
|
| 145 |
+
for metric, value in model_info_for_loggers(trainer).items():
|
| 146 |
+
live.log_metric(metric, value, plot=False)
|
| 147 |
+
|
| 148 |
+
_log_plots(trainer.plots, "train")
|
| 149 |
+
_log_plots(trainer.validator.plots, "val")
|
| 150 |
+
|
| 151 |
+
live.next_step()
|
| 152 |
+
_training_epoch = False
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
def on_train_end(trainer) -> None:
|
| 156 |
+
"""Log best metrics, plots, and confusion matrix at the end of training.
|
| 157 |
+
|
| 158 |
+
This function is called at the conclusion of the training process to log final metrics, visualizations, and model
|
| 159 |
+
artifacts if DVCLive logging is active. It captures the best model performance metrics, training plots, validation
|
| 160 |
+
plots, and confusion matrix for later analysis.
|
| 161 |
+
|
| 162 |
+
Args:
|
| 163 |
+
trainer (BaseTrainer): The trainer object containing training state, metrics, and validation results.
|
| 164 |
+
|
| 165 |
+
Examples:
|
| 166 |
+
>>> # Inside a custom training loop
|
| 167 |
+
>>> from ultralytics.utils.callbacks.dvc import on_train_end
|
| 168 |
+
>>> on_train_end(trainer) # Log final metrics and artifacts
|
| 169 |
+
"""
|
| 170 |
+
if live:
|
| 171 |
+
# At the end log the best metrics. It runs validator on the best model internally.
|
| 172 |
+
all_metrics = {**trainer.label_loss_items(trainer.tloss, prefix="train"), **trainer.metrics, **trainer.lr}
|
| 173 |
+
for metric, value in all_metrics.items():
|
| 174 |
+
live.log_metric(metric, value, plot=False)
|
| 175 |
+
|
| 176 |
+
_log_plots(trainer.plots, "val")
|
| 177 |
+
_log_plots(trainer.validator.plots, "val")
|
| 178 |
+
_log_confusion_matrix(trainer.validator)
|
| 179 |
+
|
| 180 |
+
if trainer.best.exists():
|
| 181 |
+
live.log_artifact(trainer.best, copy=True, type="model")
|
| 182 |
+
|
| 183 |
+
live.end()
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
callbacks = (
|
| 187 |
+
{
|
| 188 |
+
"on_pretrain_routine_start": on_pretrain_routine_start,
|
| 189 |
+
"on_pretrain_routine_end": on_pretrain_routine_end,
|
| 190 |
+
"on_train_start": on_train_start,
|
| 191 |
+
"on_train_epoch_start": on_train_epoch_start,
|
| 192 |
+
"on_fit_epoch_end": on_fit_epoch_end,
|
| 193 |
+
"on_train_end": on_train_end,
|
| 194 |
+
}
|
| 195 |
+
if dvclive
|
| 196 |
+
else {}
|
| 197 |
+
)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/hub.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
from time import time
|
| 5 |
+
|
| 6 |
+
from ultralytics.hub import HUB_WEB_ROOT, PREFIX, HUBTrainingSession
|
| 7 |
+
from ultralytics.utils import LOGGER, RANK, SETTINGS
|
| 8 |
+
from ultralytics.utils.events import events
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def on_pretrain_routine_start(trainer):
|
| 12 |
+
"""Create a remote Ultralytics HUB session to log local model training."""
|
| 13 |
+
if RANK in {-1, 0} and SETTINGS["hub"] is True and SETTINGS["api_key"] and trainer.hub_session is None:
|
| 14 |
+
trainer.hub_session = HUBTrainingSession.create_session(trainer.args.model, trainer.args)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def on_pretrain_routine_end(trainer):
|
| 18 |
+
"""Initialize timers for upload rate limiting before training begins."""
|
| 19 |
+
if session := getattr(trainer, "hub_session", None):
|
| 20 |
+
# Start timer for upload rate limit
|
| 21 |
+
session.timers = {"metrics": time(), "ckpt": time()} # start timer for session rate limiting
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def on_fit_epoch_end(trainer):
|
| 25 |
+
"""Upload training progress metrics to Ultralytics HUB at the end of each epoch."""
|
| 26 |
+
if session := getattr(trainer, "hub_session", None):
|
| 27 |
+
# Upload metrics after validation ends
|
| 28 |
+
all_plots = {
|
| 29 |
+
**trainer.label_loss_items(trainer.tloss, prefix="train"),
|
| 30 |
+
**trainer.metrics,
|
| 31 |
+
}
|
| 32 |
+
if trainer.epoch == 0:
|
| 33 |
+
from ultralytics.utils.torch_utils import model_info_for_loggers
|
| 34 |
+
|
| 35 |
+
all_plots = {**all_plots, **model_info_for_loggers(trainer)}
|
| 36 |
+
|
| 37 |
+
session.metrics_queue[trainer.epoch] = json.dumps(all_plots)
|
| 38 |
+
|
| 39 |
+
# If any metrics failed to upload previously, add them to the queue to attempt uploading again
|
| 40 |
+
if session.metrics_upload_failed_queue:
|
| 41 |
+
session.metrics_queue.update(session.metrics_upload_failed_queue)
|
| 42 |
+
|
| 43 |
+
if time() - session.timers["metrics"] > session.rate_limits["metrics"]:
|
| 44 |
+
session.upload_metrics()
|
| 45 |
+
session.timers["metrics"] = time() # reset timer
|
| 46 |
+
session.metrics_queue = {} # reset queue
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def on_model_save(trainer):
|
| 50 |
+
"""Upload model checkpoints to Ultralytics HUB with rate limiting."""
|
| 51 |
+
if session := getattr(trainer, "hub_session", None):
|
| 52 |
+
# Upload checkpoints with rate limiting
|
| 53 |
+
is_best = trainer.best_fitness == trainer.fitness
|
| 54 |
+
if time() - session.timers["ckpt"] > session.rate_limits["ckpt"]:
|
| 55 |
+
LOGGER.info(f"{PREFIX}Uploading checkpoint {HUB_WEB_ROOT}/models/{session.model.id}")
|
| 56 |
+
session.upload_model(trainer.epoch, trainer.last, is_best)
|
| 57 |
+
session.timers["ckpt"] = time() # reset timer
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def on_train_end(trainer):
|
| 61 |
+
"""Upload final model and metrics to Ultralytics HUB at the end of training."""
|
| 62 |
+
if session := getattr(trainer, "hub_session", None):
|
| 63 |
+
# Upload final model and metrics with exponential backoff
|
| 64 |
+
LOGGER.info(f"{PREFIX}Syncing final model...")
|
| 65 |
+
session.upload_model(
|
| 66 |
+
trainer.epoch,
|
| 67 |
+
trainer.best,
|
| 68 |
+
map=trainer.metrics.get("metrics/mAP50-95(B)", 0),
|
| 69 |
+
final=True,
|
| 70 |
+
)
|
| 71 |
+
session.alive = False # stop heartbeats
|
| 72 |
+
LOGGER.info(f"{PREFIX}Done ✅\n{PREFIX}View model at {session.model_url} 🚀")
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def on_train_start(trainer):
|
| 76 |
+
"""Run events on train start."""
|
| 77 |
+
events(trainer.args, trainer.device)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def on_val_start(validator):
|
| 81 |
+
"""Run events on validation start."""
|
| 82 |
+
if not validator.training:
|
| 83 |
+
events(validator.args, validator.device)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def on_predict_start(predictor):
|
| 87 |
+
"""Run events on predict start."""
|
| 88 |
+
backend = getattr(getattr(predictor, "model", None), "backend", None)
|
| 89 |
+
events(predictor.args, predictor.device, backend=backend)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def on_export_start(exporter):
|
| 93 |
+
"""Run events on export start."""
|
| 94 |
+
events(exporter.args, exporter.device)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
callbacks = (
|
| 98 |
+
{
|
| 99 |
+
"on_pretrain_routine_start": on_pretrain_routine_start,
|
| 100 |
+
"on_pretrain_routine_end": on_pretrain_routine_end,
|
| 101 |
+
"on_fit_epoch_end": on_fit_epoch_end,
|
| 102 |
+
"on_model_save": on_model_save,
|
| 103 |
+
"on_train_end": on_train_end,
|
| 104 |
+
"on_train_start": on_train_start,
|
| 105 |
+
"on_val_start": on_val_start,
|
| 106 |
+
"on_predict_start": on_predict_start,
|
| 107 |
+
"on_export_start": on_export_start,
|
| 108 |
+
}
|
| 109 |
+
if SETTINGS["hub"] is True
|
| 110 |
+
else {}
|
| 111 |
+
)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/mlflow.py
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
"""
|
| 3 |
+
MLflow Logging for Ultralytics YOLO.
|
| 4 |
+
|
| 5 |
+
This module enables MLflow logging for Ultralytics YOLO. It logs metrics, parameters, and model artifacts.
|
| 6 |
+
For setting up, a tracking URI should be specified. The logging can be customized using environment variables.
|
| 7 |
+
|
| 8 |
+
Commands:
|
| 9 |
+
1. To set a project name:
|
| 10 |
+
`export MLFLOW_EXPERIMENT_NAME=<your_experiment_name>` or use the project=<project> argument
|
| 11 |
+
|
| 12 |
+
2. To set a run name:
|
| 13 |
+
`export MLFLOW_RUN=<your_run_name>` or use the name=<name> argument
|
| 14 |
+
|
| 15 |
+
3. To start a local MLflow server:
|
| 16 |
+
mlflow server --backend-store-uri runs/mlflow
|
| 17 |
+
It will by default start a local server at http://127.0.0.1:5000.
|
| 18 |
+
To specify a different URI, set the MLFLOW_TRACKING_URI environment variable.
|
| 19 |
+
|
| 20 |
+
4. To kill all running MLflow server instances:
|
| 21 |
+
ps aux | grep 'mlflow' | grep -v 'grep' | awk '{print $2}' | xargs kill -9
|
| 22 |
+
"""
|
| 23 |
+
|
| 24 |
+
import os
|
| 25 |
+
from pathlib import Path
|
| 26 |
+
|
| 27 |
+
from ultralytics.utils import LOGGER, RUNS_DIR, SETTINGS, TESTS_RUNNING, colorstr
|
| 28 |
+
|
| 29 |
+
PREFIX = colorstr("MLflow: ")
|
| 30 |
+
|
| 31 |
+
try:
|
| 32 |
+
import mlflow
|
| 33 |
+
|
| 34 |
+
assert hasattr(mlflow, "__version__") # verify package is not a local directory
|
| 35 |
+
except (ImportError, AssertionError):
|
| 36 |
+
mlflow = None
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def sanitize_dict(x: dict) -> dict:
|
| 40 |
+
"""Sanitize dictionary keys by removing parentheses and converting values to floats."""
|
| 41 |
+
return {k.replace("(", "").replace(")", ""): float(v) for k, v in x.items()}
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def on_pretrain_routine_end(trainer):
|
| 45 |
+
"""Log training parameters to MLflow at the end of the pretraining routine.
|
| 46 |
+
|
| 47 |
+
This function sets up MLflow logging based on environment variables and trainer arguments. It sets the tracking URI,
|
| 48 |
+
experiment name, and run name, then starts the MLflow run if not already active. It finally logs the parameters from
|
| 49 |
+
the trainer.
|
| 50 |
+
|
| 51 |
+
Args:
|
| 52 |
+
trainer (ultralytics.engine.trainer.BaseTrainer): The training object with arguments and parameters to log.
|
| 53 |
+
|
| 54 |
+
Notes:
|
| 55 |
+
MLFLOW_TRACKING_URI: The URI for MLflow tracking. If not set, defaults to 'runs/mlflow'.
|
| 56 |
+
MLFLOW_EXPERIMENT_NAME: The name of the MLflow experiment. If not set, defaults to trainer.args.project.
|
| 57 |
+
MLFLOW_RUN: The name of the MLflow run. If not set, defaults to trainer.args.name.
|
| 58 |
+
MLFLOW_KEEP_RUN_ACTIVE: Boolean indicating whether to keep the MLflow run active after training ends.
|
| 59 |
+
"""
|
| 60 |
+
# Resolve enablement at call time (not import time) so test/training order can never permanently disable MLflow:
|
| 61 |
+
# `add_integration_callbacks` imports this module on the first training, which may run with mlflow off.
|
| 62 |
+
if not mlflow or SETTINGS["mlflow"] is not True:
|
| 63 |
+
return
|
| 64 |
+
if TESTS_RUNNING and "test_mlflow" not in os.environ.get("PYTEST_CURRENT_TEST", ""):
|
| 65 |
+
return # do not log during unrelated pytest tests
|
| 66 |
+
|
| 67 |
+
uri = os.environ.get("MLFLOW_TRACKING_URI") or str(RUNS_DIR / "mlflow")
|
| 68 |
+
LOGGER.debug(f"{PREFIX} tracking uri: {uri}")
|
| 69 |
+
|
| 70 |
+
# Set experiment and run names
|
| 71 |
+
experiment_name = os.environ.get("MLFLOW_EXPERIMENT_NAME") or trainer.args.project or "/Shared/Ultralytics"
|
| 72 |
+
run_name = os.environ.get("MLFLOW_RUN") or trainer.args.name
|
| 73 |
+
|
| 74 |
+
trainer._mlflow_active = False
|
| 75 |
+
trainer._mlflow_started_run = False
|
| 76 |
+
try:
|
| 77 |
+
mlflow.set_tracking_uri(uri)
|
| 78 |
+
mlflow.set_experiment(experiment_name)
|
| 79 |
+
mlflow.autolog()
|
| 80 |
+
active_run = mlflow.active_run()
|
| 81 |
+
if active_run is None:
|
| 82 |
+
active_run = mlflow.start_run(run_name=run_name)
|
| 83 |
+
trainer._mlflow_started_run = True
|
| 84 |
+
LOGGER.info(f"{PREFIX}logging run_id({active_run.info.run_id}) to {uri}")
|
| 85 |
+
if Path(uri).is_dir():
|
| 86 |
+
LOGGER.info(f"{PREFIX}view at http://127.0.0.1:5000 with 'mlflow server --backend-store-uri {uri}'")
|
| 87 |
+
LOGGER.info(f"{PREFIX}disable with 'yolo settings mlflow=False'")
|
| 88 |
+
mlflow.log_params(dict(trainer.args))
|
| 89 |
+
trainer._mlflow_active = True
|
| 90 |
+
except Exception as e:
|
| 91 |
+
LOGGER.warning(f"{PREFIX}Failed to initialize: {e}")
|
| 92 |
+
LOGGER.warning(f"{PREFIX}Not tracking this run")
|
| 93 |
+
if trainer._mlflow_started_run:
|
| 94 |
+
try:
|
| 95 |
+
mlflow.end_run()
|
| 96 |
+
except Exception:
|
| 97 |
+
pass
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def _log_metrics(trainer, metrics):
|
| 101 |
+
"""Log metrics to MLflow, disabling tracking for this run on failure so it never crashes training."""
|
| 102 |
+
try:
|
| 103 |
+
mlflow.log_metrics(metrics=metrics, step=trainer.epoch)
|
| 104 |
+
except Exception as e:
|
| 105 |
+
LOGGER.warning(f"{PREFIX}metric logging failed, disabling tracking for this run: {e}")
|
| 106 |
+
trainer._mlflow_active = False
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def on_train_epoch_end(trainer):
|
| 110 |
+
"""Log training metrics at the end of each train epoch to MLflow."""
|
| 111 |
+
if mlflow and getattr(trainer, "_mlflow_active", False):
|
| 112 |
+
_log_metrics(
|
| 113 |
+
trainer,
|
| 114 |
+
{
|
| 115 |
+
**sanitize_dict(trainer.lr),
|
| 116 |
+
**sanitize_dict(trainer.label_loss_items(trainer.tloss, prefix="train")),
|
| 117 |
+
},
|
| 118 |
+
)
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def on_fit_epoch_end(trainer):
|
| 122 |
+
"""Log training metrics at the end of each fit epoch to MLflow."""
|
| 123 |
+
if mlflow and getattr(trainer, "_mlflow_active", False):
|
| 124 |
+
_log_metrics(trainer, sanitize_dict(trainer.metrics))
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def on_train_end(trainer):
|
| 128 |
+
"""Log model artifacts at the end of training and close any run this callback opened."""
|
| 129 |
+
if not mlflow:
|
| 130 |
+
return
|
| 131 |
+
if getattr(trainer, "_mlflow_active", False):
|
| 132 |
+
try:
|
| 133 |
+
mlflow.log_artifact(str(trainer.best.parent)) # log save_dir/weights directory with best.pt and last.pt
|
| 134 |
+
for f in trainer.save_dir.glob("*"): # log all other files in save_dir
|
| 135 |
+
if f.suffix in {".png", ".jpg", ".csv", ".pt", ".yaml"}:
|
| 136 |
+
mlflow.log_artifact(str(f))
|
| 137 |
+
LOGGER.info(
|
| 138 |
+
f"{PREFIX}results logged to {mlflow.get_tracking_uri()}\n{PREFIX}disable with 'yolo settings mlflow=False'"
|
| 139 |
+
)
|
| 140 |
+
except Exception as e:
|
| 141 |
+
LOGGER.warning(f"{PREFIX}failed to log artifacts: {e}")
|
| 142 |
+
if getattr(trainer, "_mlflow_started_run", False): # only close a run we created
|
| 143 |
+
if os.environ.get("MLFLOW_KEEP_RUN_ACTIVE", "False").lower() == "true":
|
| 144 |
+
LOGGER.info(f"{PREFIX}mlflow run still alive, remember to close it using mlflow.end_run()")
|
| 145 |
+
else:
|
| 146 |
+
try:
|
| 147 |
+
mlflow.end_run()
|
| 148 |
+
LOGGER.debug(f"{PREFIX}mlflow run ended")
|
| 149 |
+
except Exception:
|
| 150 |
+
pass
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
callbacks = (
|
| 154 |
+
{
|
| 155 |
+
"on_pretrain_routine_end": on_pretrain_routine_end,
|
| 156 |
+
"on_train_epoch_end": on_train_epoch_end,
|
| 157 |
+
"on_fit_epoch_end": on_fit_epoch_end,
|
| 158 |
+
"on_train_end": on_train_end,
|
| 159 |
+
}
|
| 160 |
+
if mlflow
|
| 161 |
+
else {}
|
| 162 |
+
)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/neptune.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
|
| 4 |
+
|
| 5 |
+
try:
|
| 6 |
+
assert not TESTS_RUNNING # do not log pytest
|
| 7 |
+
assert SETTINGS["neptune"] is True # verify integration is enabled
|
| 8 |
+
|
| 9 |
+
import neptune
|
| 10 |
+
from neptune.types import File
|
| 11 |
+
|
| 12 |
+
assert hasattr(neptune, "__version__")
|
| 13 |
+
|
| 14 |
+
run = None # NeptuneAI experiment logger instance
|
| 15 |
+
|
| 16 |
+
except (ImportError, AssertionError):
|
| 17 |
+
neptune = None
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def _log_scalars(scalars: dict, step: int = 0) -> None:
|
| 21 |
+
"""Log scalars to the NeptuneAI experiment logger.
|
| 22 |
+
|
| 23 |
+
Args:
|
| 24 |
+
scalars (dict): Dictionary of scalar values to log to NeptuneAI.
|
| 25 |
+
step (int, optional): The current step or iteration number for logging.
|
| 26 |
+
|
| 27 |
+
Examples:
|
| 28 |
+
>>> metrics = {"mAP": 0.85, "loss": 0.32}
|
| 29 |
+
>>> _log_scalars(metrics, step=100)
|
| 30 |
+
"""
|
| 31 |
+
if run:
|
| 32 |
+
for k, v in scalars.items():
|
| 33 |
+
run[k].append(value=v, step=step)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def _log_images(imgs_dict: dict, group: str = "") -> None:
|
| 37 |
+
"""Log images to the NeptuneAI experiment logger.
|
| 38 |
+
|
| 39 |
+
This function logs image data to Neptune.ai when a valid Neptune run is active. Images are organized under the
|
| 40 |
+
specified group name.
|
| 41 |
+
|
| 42 |
+
Args:
|
| 43 |
+
imgs_dict (dict): Dictionary of images to log, with keys as image names and values as image data.
|
| 44 |
+
group (str, optional): Group name to organize images under in the Neptune UI.
|
| 45 |
+
|
| 46 |
+
Examples:
|
| 47 |
+
>>> # Log validation images
|
| 48 |
+
>>> _log_images({"val_batch": img_tensor}, group="validation")
|
| 49 |
+
"""
|
| 50 |
+
if run:
|
| 51 |
+
for k, v in imgs_dict.items():
|
| 52 |
+
run[f"{group}/{k}"].upload(File(v))
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def _log_plot(title: str, plot_path: str) -> None:
|
| 56 |
+
"""Log plots to the NeptuneAI experiment logger."""
|
| 57 |
+
import matplotlib.image as mpimg
|
| 58 |
+
import matplotlib.pyplot as plt
|
| 59 |
+
|
| 60 |
+
img = mpimg.imread(plot_path)
|
| 61 |
+
fig = plt.figure()
|
| 62 |
+
ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect="auto", xticks=[], yticks=[]) # no ticks
|
| 63 |
+
ax.imshow(img)
|
| 64 |
+
run[f"Plots/{title}"].upload(fig)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def on_pretrain_routine_start(trainer) -> None:
|
| 68 |
+
"""Initialize NeptuneAI run and log hyperparameters before training starts."""
|
| 69 |
+
try:
|
| 70 |
+
global run
|
| 71 |
+
run = neptune.init_run(
|
| 72 |
+
project=trainer.args.project or "Ultralytics",
|
| 73 |
+
name=trainer.args.name,
|
| 74 |
+
tags=["Ultralytics"],
|
| 75 |
+
)
|
| 76 |
+
run["Configuration/Hyperparameters"] = {k: "" if v is None else v for k, v in vars(trainer.args).items()}
|
| 77 |
+
except Exception as e:
|
| 78 |
+
LOGGER.warning(f"NeptuneAI installed but not initialized correctly, not logging this run. {e}")
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def on_train_epoch_end(trainer) -> None:
|
| 82 |
+
"""Log training metrics and learning rate at the end of each training epoch."""
|
| 83 |
+
_log_scalars(trainer.label_loss_items(trainer.tloss, prefix="train"), trainer.epoch + 1)
|
| 84 |
+
_log_scalars(trainer.lr, trainer.epoch + 1)
|
| 85 |
+
if trainer.epoch == 1:
|
| 86 |
+
_log_images({f.stem: str(f) for f in trainer.save_dir.glob("train_batch*.jpg")}, "Mosaic")
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def on_fit_epoch_end(trainer) -> None:
|
| 90 |
+
"""Log model info and validation metrics at the end of each fit epoch."""
|
| 91 |
+
if run and trainer.epoch == 0:
|
| 92 |
+
from ultralytics.utils.torch_utils import model_info_for_loggers
|
| 93 |
+
|
| 94 |
+
run["Configuration/Model"] = model_info_for_loggers(trainer)
|
| 95 |
+
_log_scalars(trainer.metrics, trainer.epoch + 1)
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def on_val_end(validator) -> None:
|
| 99 |
+
"""Log validation images at the end of validation."""
|
| 100 |
+
if run:
|
| 101 |
+
# Log val_labels and val_pred
|
| 102 |
+
_log_images({f.stem: str(f) for f in validator.save_dir.glob("val*.jpg")}, "Validation")
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def on_train_end(trainer) -> None:
|
| 106 |
+
"""Log final results, plots, and model weights at the end of training."""
|
| 107 |
+
if run:
|
| 108 |
+
# Log final results, CM matrix + PR plots
|
| 109 |
+
for f in [*trainer.plots.keys(), *trainer.validator.plots.keys()]:
|
| 110 |
+
if "batch" not in f.name:
|
| 111 |
+
_log_plot(title=f.stem, plot_path=f)
|
| 112 |
+
# Log the final model
|
| 113 |
+
run[f"weights/{trainer.args.name or trainer.args.task}/{trainer.best.name}"].upload(File(str(trainer.best)))
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
callbacks = (
|
| 117 |
+
{
|
| 118 |
+
"on_pretrain_routine_start": on_pretrain_routine_start,
|
| 119 |
+
"on_train_epoch_end": on_train_epoch_end,
|
| 120 |
+
"on_fit_epoch_end": on_fit_epoch_end,
|
| 121 |
+
"on_val_end": on_val_end,
|
| 122 |
+
"on_train_end": on_train_end,
|
| 123 |
+
}
|
| 124 |
+
if neptune
|
| 125 |
+
else {}
|
| 126 |
+
)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/platform.py
ADDED
|
@@ -0,0 +1,553 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import platform
|
| 5 |
+
import re
|
| 6 |
+
import socket
|
| 7 |
+
import sys
|
| 8 |
+
from concurrent.futures import ThreadPoolExecutor
|
| 9 |
+
from math import isfinite
|
| 10 |
+
from pathlib import Path
|
| 11 |
+
from time import sleep, time
|
| 12 |
+
|
| 13 |
+
from ultralytics.utils import (
|
| 14 |
+
ENVIRONMENT,
|
| 15 |
+
GIT,
|
| 16 |
+
LOGGER,
|
| 17 |
+
PLATFORM_URL,
|
| 18 |
+
PYTHON_VERSION,
|
| 19 |
+
RANK,
|
| 20 |
+
SETTINGS,
|
| 21 |
+
TESTS_RUNNING,
|
| 22 |
+
Retry,
|
| 23 |
+
colorstr,
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
PREFIX = colorstr("Platform: ")
|
| 27 |
+
PLATFORM_API_URL = f"{PLATFORM_URL}/api/webhooks"
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def slugify(text):
|
| 31 |
+
"""Convert text to URL-safe slug (e.g., 'My Project 1' -> 'my-project-1')."""
|
| 32 |
+
if not text:
|
| 33 |
+
return text
|
| 34 |
+
return re.sub(r"-+", "-", re.sub(r"[^a-z0-9\s-]", "", str(text).lower()).replace(" ", "-")).strip("-")[:128]
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
try:
|
| 38 |
+
assert not TESTS_RUNNING # do not log pytest
|
| 39 |
+
assert SETTINGS.get("platform", False) is True or os.getenv("ULTRALYTICS_API_KEY") or SETTINGS.get("api_key")
|
| 40 |
+
_api_key = os.getenv("ULTRALYTICS_API_KEY") or SETTINGS.get("api_key")
|
| 41 |
+
assert _api_key # verify API key is present
|
| 42 |
+
|
| 43 |
+
import requests
|
| 44 |
+
|
| 45 |
+
from ultralytics.utils.logger import ConsoleLogger, SystemLogger
|
| 46 |
+
from ultralytics.utils.torch_utils import model_info_for_loggers
|
| 47 |
+
|
| 48 |
+
_executor = ThreadPoolExecutor(max_workers=10) # Bounded thread pool for async operations
|
| 49 |
+
|
| 50 |
+
except (AssertionError, ImportError):
|
| 51 |
+
_api_key = None
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def resolve_platform_uri(uri, hard=True):
|
| 55 |
+
"""Resolve ul:// URIs to signed URLs by authenticating with Ultralytics Platform.
|
| 56 |
+
|
| 57 |
+
Formats:
|
| 58 |
+
ul://username/datasets/slug -> Returns signed URL to NDJSON file
|
| 59 |
+
ul://username/project/model -> Returns signed URL to .pt file
|
| 60 |
+
|
| 61 |
+
Args:
|
| 62 |
+
uri (str): Platform URI starting with "ul://".
|
| 63 |
+
hard (bool): Whether to raise an error if resolution fails.
|
| 64 |
+
|
| 65 |
+
Returns:
|
| 66 |
+
(str | None): Signed URL on success, None if not found and hard=False.
|
| 67 |
+
|
| 68 |
+
Raises:
|
| 69 |
+
ValueError: If API key is missing/invalid or URI format is wrong.
|
| 70 |
+
PermissionError: If access is denied.
|
| 71 |
+
RuntimeError: If resource is not ready (e.g., dataset still processing).
|
| 72 |
+
FileNotFoundError: If resource not found and hard=True.
|
| 73 |
+
ConnectionError: If network request fails and hard=True.
|
| 74 |
+
"""
|
| 75 |
+
import requests
|
| 76 |
+
|
| 77 |
+
path = uri[5:] # Remove "ul://"
|
| 78 |
+
parts = path.split("/")
|
| 79 |
+
|
| 80 |
+
api_key = os.getenv("ULTRALYTICS_API_KEY") or SETTINGS.get("api_key")
|
| 81 |
+
if not api_key:
|
| 82 |
+
raise ValueError(f"ULTRALYTICS_API_KEY required for '{uri}'. Get key at {PLATFORM_URL}/settings")
|
| 83 |
+
|
| 84 |
+
base = PLATFORM_API_URL
|
| 85 |
+
headers = {"Authorization": f"Bearer {api_key}"}
|
| 86 |
+
|
| 87 |
+
# ul://username/datasets/slug
|
| 88 |
+
if len(parts) == 3 and parts[1] == "datasets":
|
| 89 |
+
username, _, slug = parts
|
| 90 |
+
url = f"{base}/datasets/{username}/{slug}/export"
|
| 91 |
+
|
| 92 |
+
# ul://username/project/model
|
| 93 |
+
elif len(parts) == 3:
|
| 94 |
+
username, project, model = parts
|
| 95 |
+
url = f"{base}/models/{username}/{project}/{model}/download"
|
| 96 |
+
|
| 97 |
+
else:
|
| 98 |
+
raise ValueError(f"Invalid platform URI: {uri}. Use ul://user/datasets/name or ul://user/project/model")
|
| 99 |
+
|
| 100 |
+
# (connect_timeout, read_timeout) — short connect so retries are fast, long read for server-side generation
|
| 101 |
+
timeout = (10, 3600) if "/datasets/" in url else (10, 90)
|
| 102 |
+
|
| 103 |
+
try:
|
| 104 |
+
for attempt in range(5):
|
| 105 |
+
try:
|
| 106 |
+
r = requests.head(url, headers=headers, allow_redirects=False, timeout=timeout)
|
| 107 |
+
if r.status_code in {408, 429} or r.status_code >= 500:
|
| 108 |
+
raise requests.exceptions.HTTPError(f"HTTP {r.status_code}", response=r)
|
| 109 |
+
break
|
| 110 |
+
except (
|
| 111 |
+
requests.exceptions.ConnectionError,
|
| 112 |
+
requests.exceptions.ReadTimeout,
|
| 113 |
+
requests.exceptions.HTTPError,
|
| 114 |
+
) as e:
|
| 115 |
+
if attempt >= 4:
|
| 116 |
+
raise
|
| 117 |
+
delay = 2 * (2**attempt) # 2s, 4s, 8s, 16s backoff
|
| 118 |
+
LOGGER.warning(f"Retry {attempt + 1}/5 for {uri} in {delay}s: {e}")
|
| 119 |
+
sleep(delay)
|
| 120 |
+
except Exception as e:
|
| 121 |
+
if hard:
|
| 122 |
+
raise ConnectionError(f"Failed to resolve {uri}: {e}") from e
|
| 123 |
+
LOGGER.warning(f"Failed to resolve {uri}: {e}")
|
| 124 |
+
return None
|
| 125 |
+
|
| 126 |
+
# Handle redirect responses (301, 302, 303, 307, 308)
|
| 127 |
+
if 300 <= r.status_code < 400 and "location" in r.headers:
|
| 128 |
+
return r.headers["location"] # Return signed URL
|
| 129 |
+
|
| 130 |
+
# Handle error responses
|
| 131 |
+
if r.status_code == 401:
|
| 132 |
+
raise ValueError(f"Invalid ULTRALYTICS_API_KEY for '{uri}'")
|
| 133 |
+
if r.status_code == 403:
|
| 134 |
+
raise PermissionError(f"Access denied for '{uri}'. Check dataset/model visibility settings.")
|
| 135 |
+
if r.status_code == 404:
|
| 136 |
+
if hard:
|
| 137 |
+
raise FileNotFoundError(f"Not found on platform: {uri}")
|
| 138 |
+
LOGGER.warning(f"Not found on platform: {uri}")
|
| 139 |
+
return None
|
| 140 |
+
if r.status_code == 409:
|
| 141 |
+
raise RuntimeError(f"Resource not ready: {uri}. Dataset may still be processing.")
|
| 142 |
+
|
| 143 |
+
# Unexpected response
|
| 144 |
+
r.raise_for_status()
|
| 145 |
+
raise RuntimeError(f"Unexpected response from platform for '{uri}': {r.status_code}")
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def _interp_plot(plot, n=101):
|
| 149 |
+
"""Interpolate plot curve data to n points to reduce storage size."""
|
| 150 |
+
import numpy as np
|
| 151 |
+
|
| 152 |
+
if not plot.get("x") or not plot.get("y"):
|
| 153 |
+
return plot # No interpolation needed (e.g., confusion_matrix)
|
| 154 |
+
|
| 155 |
+
x, y = np.array(plot["x"]), np.array(plot["y"])
|
| 156 |
+
if len(x) <= n:
|
| 157 |
+
return plot # Already small enough
|
| 158 |
+
|
| 159 |
+
# New x values (101 points gives clean 0.01 increments: 0, 0.01, 0.02, ..., 1.0)
|
| 160 |
+
x_new = np.linspace(x[0], x[-1], n)
|
| 161 |
+
|
| 162 |
+
# Interpolate y values (handle both 1D and 2D arrays)
|
| 163 |
+
if y.ndim == 1:
|
| 164 |
+
y_new = np.interp(x_new, x, y)
|
| 165 |
+
else:
|
| 166 |
+
y_new = np.array([np.interp(x_new, x, yi) for yi in y])
|
| 167 |
+
|
| 168 |
+
# Also interpolate ap if present (for PR curves)
|
| 169 |
+
result = {**plot, "x": x_new.tolist(), "y": y_new.tolist()}
|
| 170 |
+
if "ap" in plot:
|
| 171 |
+
result["ap"] = plot["ap"] # Keep AP values as-is (per-class scalars)
|
| 172 |
+
|
| 173 |
+
return result
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
def _sanitize_json_value(value):
|
| 177 |
+
"""Replace non-finite floats in payloads with None so requests JSON encoding succeeds."""
|
| 178 |
+
if isinstance(value, dict):
|
| 179 |
+
return {k: _sanitize_json_value(v) for k, v in value.items()}
|
| 180 |
+
if isinstance(value, (list, tuple)):
|
| 181 |
+
return [_sanitize_json_value(v) for v in value]
|
| 182 |
+
if isinstance(value, float):
|
| 183 |
+
return value if isfinite(value) else None # avoid "Out of range float values are not JSON compliant" warnings
|
| 184 |
+
return value
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def _send(event, data, project, name, model_id=None, retry=2):
|
| 188 |
+
"""Send event to Platform endpoint with retry logic."""
|
| 189 |
+
payload = {"event": event, "project": project, "name": name, "data": _sanitize_json_value(data)}
|
| 190 |
+
if model_id:
|
| 191 |
+
payload["modelId"] = model_id
|
| 192 |
+
|
| 193 |
+
@Retry(times=retry, delay=1)
|
| 194 |
+
def post():
|
| 195 |
+
r = requests.post(
|
| 196 |
+
f"{PLATFORM_API_URL}/training/metrics",
|
| 197 |
+
json=payload,
|
| 198 |
+
headers={"Authorization": f"Bearer {_api_key}"},
|
| 199 |
+
timeout=30,
|
| 200 |
+
)
|
| 201 |
+
if 400 <= r.status_code < 500 and r.status_code not in {408, 429}:
|
| 202 |
+
try:
|
| 203 |
+
msg = r.json().get("error", r.reason)
|
| 204 |
+
except Exception:
|
| 205 |
+
msg = r.reason
|
| 206 |
+
LOGGER.warning(f"{PREFIX}{msg}")
|
| 207 |
+
return None # Don't retry client errors (except 408 timeout, 429 rate limit)
|
| 208 |
+
r.raise_for_status()
|
| 209 |
+
return r.json()
|
| 210 |
+
|
| 211 |
+
try:
|
| 212 |
+
return post()
|
| 213 |
+
except Exception as e:
|
| 214 |
+
LOGGER.debug(f"{PREFIX}Failed to send {event}: {e}")
|
| 215 |
+
return None
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
def _send_async(event, data, project, name, model_id=None):
|
| 219 |
+
"""Send event asynchronously using bounded thread pool."""
|
| 220 |
+
_executor.submit(_send, event, data, project, name, model_id)
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
def _handle_control_response(trainer, ctx, response):
|
| 224 |
+
"""Apply centralized stop signals returned by Platform webhook responses.
|
| 225 |
+
|
| 226 |
+
Notes:
|
| 227 |
+
``ctx["cancelled"]`` is the durable cancellation signal. During startup, trainer setup later resets
|
| 228 |
+
``trainer.stop``, so early stop requests still rely on ``on_pretrain_routine_end()`` to reapply the flag after
|
| 229 |
+
setup completes.
|
| 230 |
+
"""
|
| 231 |
+
if response and response.get("cancelled"):
|
| 232 |
+
ctx["cancelled"] = True
|
| 233 |
+
trainer.stop = True
|
| 234 |
+
LOGGER.info(f"{PREFIX}Training cancelled from Platform ⚠️")
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
def _upload_model(model_path, project, name, progress=False, retry=1, model_id=None):
|
| 238 |
+
"""Upload model checkpoint to Platform via signed URL."""
|
| 239 |
+
from ultralytics.utils.uploads import safe_upload
|
| 240 |
+
|
| 241 |
+
model_path = Path(model_path)
|
| 242 |
+
if not model_path.exists():
|
| 243 |
+
LOGGER.warning(f"{PREFIX}Model file not found: {model_path}")
|
| 244 |
+
return None
|
| 245 |
+
|
| 246 |
+
# Get signed upload URL from Platform (server sanitizes filename for storage safety)
|
| 247 |
+
@Retry(times=3, delay=2)
|
| 248 |
+
def get_signed_url():
|
| 249 |
+
payload = {"project": project, "name": name, "filename": model_path.name}
|
| 250 |
+
if model_id:
|
| 251 |
+
payload["modelId"] = model_id # Direct lookup avoids slug mismatch from auto-increment
|
| 252 |
+
r = requests.post(
|
| 253 |
+
f"{PLATFORM_API_URL}/models/upload",
|
| 254 |
+
json=payload,
|
| 255 |
+
headers={"Authorization": f"Bearer {_api_key}"},
|
| 256 |
+
timeout=30,
|
| 257 |
+
)
|
| 258 |
+
r.raise_for_status()
|
| 259 |
+
return r.json()
|
| 260 |
+
|
| 261 |
+
try:
|
| 262 |
+
data = get_signed_url()
|
| 263 |
+
except Exception as e:
|
| 264 |
+
LOGGER.warning(f"{PREFIX}Failed to get upload URL: {e}")
|
| 265 |
+
return None
|
| 266 |
+
|
| 267 |
+
# Upload to GCS using safe_upload with retry logic and optional progress bar
|
| 268 |
+
if safe_upload(file=model_path, url=data["uploadUrl"], retry=retry, progress=progress):
|
| 269 |
+
return data.get("gcsPath")
|
| 270 |
+
return None
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
def _upload_model_async(model_path, project, name, model_id=None):
|
| 274 |
+
"""Upload model asynchronously using bounded thread pool."""
|
| 275 |
+
_executor.submit(_upload_model, model_path, project, name, model_id=model_id)
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
def _get_environment_info():
|
| 279 |
+
"""Collect comprehensive environment info using existing ultralytics utilities."""
|
| 280 |
+
import shutil
|
| 281 |
+
|
| 282 |
+
import psutil
|
| 283 |
+
import torch
|
| 284 |
+
|
| 285 |
+
from ultralytics import __version__
|
| 286 |
+
from ultralytics.utils.torch_utils import get_cpu_info, get_gpu_info
|
| 287 |
+
|
| 288 |
+
# Get RAM and disk totals
|
| 289 |
+
memory = psutil.virtual_memory()
|
| 290 |
+
disk_usage = shutil.disk_usage("/")
|
| 291 |
+
|
| 292 |
+
env = {
|
| 293 |
+
"ultralyticsVersion": __version__,
|
| 294 |
+
"hostname": socket.gethostname(),
|
| 295 |
+
"os": platform.platform(),
|
| 296 |
+
"environment": ENVIRONMENT,
|
| 297 |
+
"pythonVersion": PYTHON_VERSION,
|
| 298 |
+
"pythonExecutable": sys.executable,
|
| 299 |
+
"cpuCount": os.cpu_count() or 0,
|
| 300 |
+
"cpu": get_cpu_info(),
|
| 301 |
+
"command": " ".join(sys.argv),
|
| 302 |
+
"totalRamGb": round(memory.total / (1 << 30), 1), # Total RAM in GB
|
| 303 |
+
"totalDiskGb": round(disk_usage.total / (1 << 30), 1), # Total disk in GB
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
# Git info using cached GIT singleton (no subprocess calls)
|
| 307 |
+
try:
|
| 308 |
+
if GIT.is_repo:
|
| 309 |
+
if GIT.origin:
|
| 310 |
+
env["gitRepository"] = GIT.origin
|
| 311 |
+
if GIT.branch:
|
| 312 |
+
env["gitBranch"] = GIT.branch
|
| 313 |
+
if GIT.commit:
|
| 314 |
+
env["gitCommit"] = GIT.commit[:12] # Short hash
|
| 315 |
+
if GIT.message:
|
| 316 |
+
env["gitCommitMessage"] = GIT.message
|
| 317 |
+
except Exception:
|
| 318 |
+
pass
|
| 319 |
+
|
| 320 |
+
# GPU info
|
| 321 |
+
try:
|
| 322 |
+
if torch.cuda.is_available():
|
| 323 |
+
env["gpuCount"] = torch.cuda.device_count()
|
| 324 |
+
env["gpuType"] = get_gpu_info(0) if torch.cuda.device_count() > 0 else None
|
| 325 |
+
except Exception:
|
| 326 |
+
pass
|
| 327 |
+
|
| 328 |
+
return env
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
def _get_project_name(trainer):
|
| 332 |
+
"""Get slugified project and name from trainer args."""
|
| 333 |
+
raw = str(trainer.args.project)
|
| 334 |
+
parts = raw.split("/", 1)
|
| 335 |
+
project = f"{parts[0]}/{slugify(parts[1])}" if len(parts) == 2 else slugify(raw)
|
| 336 |
+
return project, slugify(str(trainer.args.name or "train"))
|
| 337 |
+
|
| 338 |
+
|
| 339 |
+
def on_pretrain_routine_start(trainer):
|
| 340 |
+
"""Initialize Platform logging at training start."""
|
| 341 |
+
if RANK not in {-1, 0} or not trainer.args.project:
|
| 342 |
+
return
|
| 343 |
+
|
| 344 |
+
project, name = _get_project_name(trainer)
|
| 345 |
+
LOGGER.info(f"{PREFIX}Streaming training metrics to Platform")
|
| 346 |
+
|
| 347 |
+
# Single dict for all platform callback state (like trainer.hub_session for HUB callbacks)
|
| 348 |
+
ctx = {"model_id": None, "last_upload": time(), "cancelled": False, "console_logger": None, "system_logger": None}
|
| 349 |
+
trainer.platform = ctx
|
| 350 |
+
|
| 351 |
+
# Create callback to send console output to Platform
|
| 352 |
+
def send_console_output(content, line_count, chunk_id):
|
| 353 |
+
"""Send batched console output to Platform webhook."""
|
| 354 |
+
_send_async(
|
| 355 |
+
"console_output",
|
| 356 |
+
{"chunkId": chunk_id, "content": content, "lineCount": line_count},
|
| 357 |
+
project,
|
| 358 |
+
name,
|
| 359 |
+
ctx["model_id"],
|
| 360 |
+
)
|
| 361 |
+
|
| 362 |
+
# Start console capture with batching (5 lines or 5 seconds)
|
| 363 |
+
ctx["console_logger"] = ConsoleLogger(batch_size=5, flush_interval=5.0, on_flush=send_console_output)
|
| 364 |
+
ctx["console_logger"].start_capture()
|
| 365 |
+
|
| 366 |
+
# Collect environment info (W&B-style metadata)
|
| 367 |
+
environment = _get_environment_info()
|
| 368 |
+
|
| 369 |
+
# Build trainArgs - callback runs before get_dataset() so args.data is still original (e.g., ul:// URIs)
|
| 370 |
+
# Note: model_info is sent later in on_fit_epoch_end (epoch 0) when the model is actually loaded
|
| 371 |
+
train_args = {k: str(v) for k, v in vars(trainer.args).items()}
|
| 372 |
+
|
| 373 |
+
# Send synchronously to get modelId for subsequent webhooks (critical, more retries)
|
| 374 |
+
response = _send(
|
| 375 |
+
"training_started",
|
| 376 |
+
{
|
| 377 |
+
"trainArgs": train_args,
|
| 378 |
+
"epochs": trainer.epochs,
|
| 379 |
+
"device": str(trainer.device),
|
| 380 |
+
"environment": environment,
|
| 381 |
+
},
|
| 382 |
+
project,
|
| 383 |
+
name,
|
| 384 |
+
retry=4,
|
| 385 |
+
)
|
| 386 |
+
if response and response.get("modelId"):
|
| 387 |
+
ctx["model_id"] = response["modelId"]
|
| 388 |
+
# Server returns actual slug (may differ from requested name due to auto-increment, e.g. "train" → "train-2")
|
| 389 |
+
if response.get("modelSlug"):
|
| 390 |
+
ctx["model_slug"] = response["modelSlug"]
|
| 391 |
+
url = f"{PLATFORM_URL}/{project}/{ctx['model_slug']}"
|
| 392 |
+
LOGGER.info(f"{PREFIX}View model at {url}")
|
| 393 |
+
# Note: trainer.stop is set in on_pretrain_routine_end (after _setup_train resets it)
|
| 394 |
+
_handle_control_response(trainer, ctx, response)
|
| 395 |
+
else:
|
| 396 |
+
LOGGER.warning(f"{PREFIX}Training will not be tracked on Platform")
|
| 397 |
+
trainer.platform = None # Disable further callbacks
|
| 398 |
+
|
| 399 |
+
|
| 400 |
+
def on_pretrain_routine_end(trainer):
|
| 401 |
+
"""Apply pre-start cancellation after _setup_train resets trainer.stop."""
|
| 402 |
+
ctx = getattr(trainer, "platform", None)
|
| 403 |
+
if ctx and ctx["cancelled"]:
|
| 404 |
+
LOGGER.info(f"{PREFIX}Training cancelled from Platform before starting ✅")
|
| 405 |
+
trainer.stop = True
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
def on_fit_epoch_end(trainer):
|
| 409 |
+
"""Log training and system metrics at epoch end."""
|
| 410 |
+
ctx = getattr(trainer, "platform", None)
|
| 411 |
+
if not ctx or RANK not in {-1, 0} or not trainer.args.project:
|
| 412 |
+
return
|
| 413 |
+
|
| 414 |
+
project, name = _get_project_name(trainer)
|
| 415 |
+
metrics = {**trainer.label_loss_items(trainer.tloss, prefix="train"), **trainer.metrics}
|
| 416 |
+
|
| 417 |
+
if trainer.optimizer and trainer.optimizer.param_groups:
|
| 418 |
+
metrics["lr"] = trainer.optimizer.param_groups[0]["lr"]
|
| 419 |
+
|
| 420 |
+
# Extract model info at epoch 0 (sent as separate field, not in metrics)
|
| 421 |
+
model_info = None
|
| 422 |
+
if trainer.epoch == 0:
|
| 423 |
+
try:
|
| 424 |
+
info = model_info_for_loggers(trainer)
|
| 425 |
+
model_info = {
|
| 426 |
+
"parameters": info.get("model/parameters", 0),
|
| 427 |
+
"gflops": info.get("model/GFLOPs", 0),
|
| 428 |
+
"speedMs": info.get("model/speed_PyTorch(ms)", 0),
|
| 429 |
+
}
|
| 430 |
+
except Exception:
|
| 431 |
+
pass
|
| 432 |
+
|
| 433 |
+
# Get system metrics (cache SystemLogger in platform context for efficiency)
|
| 434 |
+
system = {}
|
| 435 |
+
try:
|
| 436 |
+
if not ctx["system_logger"]:
|
| 437 |
+
ctx["system_logger"] = SystemLogger(all_drives=True)
|
| 438 |
+
system = ctx["system_logger"].get_metrics(rates=True)
|
| 439 |
+
except Exception:
|
| 440 |
+
pass
|
| 441 |
+
|
| 442 |
+
payload = {
|
| 443 |
+
"epoch": trainer.epoch,
|
| 444 |
+
"metrics": metrics,
|
| 445 |
+
"system": system,
|
| 446 |
+
"fitness": trainer.fitness,
|
| 447 |
+
"best_fitness": trainer.best_fitness,
|
| 448 |
+
}
|
| 449 |
+
if model_info:
|
| 450 |
+
payload["modelInfo"] = model_info
|
| 451 |
+
|
| 452 |
+
def _send_and_check_cancel():
|
| 453 |
+
"""Send epoch_end and check response for cancellation (runs in background thread)."""
|
| 454 |
+
response = _send("epoch_end", payload, project, name, ctx["model_id"], retry=1)
|
| 455 |
+
_handle_control_response(trainer, ctx, response)
|
| 456 |
+
|
| 457 |
+
_executor.submit(_send_and_check_cancel)
|
| 458 |
+
|
| 459 |
+
|
| 460 |
+
def on_model_save(trainer):
|
| 461 |
+
"""Upload model checkpoint (rate limited to every 15 min)."""
|
| 462 |
+
ctx = getattr(trainer, "platform", None)
|
| 463 |
+
if not ctx or RANK not in {-1, 0} or not trainer.args.project:
|
| 464 |
+
return
|
| 465 |
+
|
| 466 |
+
# Rate limit to every 15 minutes (900 seconds)
|
| 467 |
+
if time() - ctx["last_upload"] < 900:
|
| 468 |
+
return
|
| 469 |
+
|
| 470 |
+
model_path = trainer.best if trainer.best and Path(trainer.best).exists() else trainer.last
|
| 471 |
+
if not model_path:
|
| 472 |
+
return
|
| 473 |
+
|
| 474 |
+
project, name = _get_project_name(trainer)
|
| 475 |
+
_upload_model_async(model_path, project, name, model_id=ctx["model_id"])
|
| 476 |
+
ctx["last_upload"] = time()
|
| 477 |
+
|
| 478 |
+
|
| 479 |
+
def on_train_end(trainer):
|
| 480 |
+
"""Log final results, upload best model, and send validation plot data."""
|
| 481 |
+
ctx = getattr(trainer, "platform", None)
|
| 482 |
+
if not ctx or RANK not in {-1, 0} or not trainer.args.project:
|
| 483 |
+
return
|
| 484 |
+
|
| 485 |
+
project, name = _get_project_name(trainer)
|
| 486 |
+
|
| 487 |
+
if ctx["cancelled"]:
|
| 488 |
+
LOGGER.info(f"{PREFIX}Uploading partial results for cancelled training")
|
| 489 |
+
|
| 490 |
+
# Stop console capture
|
| 491 |
+
if ctx["console_logger"]:
|
| 492 |
+
ctx["console_logger"].stop_capture()
|
| 493 |
+
ctx["console_logger"] = None
|
| 494 |
+
|
| 495 |
+
# Upload best model (blocking with progress bar to ensure it completes)
|
| 496 |
+
gcs_path = None
|
| 497 |
+
model_size = None
|
| 498 |
+
if trainer.best and Path(trainer.best).exists():
|
| 499 |
+
model_size = Path(trainer.best).stat().st_size
|
| 500 |
+
gcs_path = _upload_model(trainer.best, project, name, progress=True, retry=3, model_id=ctx["model_id"])
|
| 501 |
+
if not gcs_path:
|
| 502 |
+
LOGGER.warning(f"{PREFIX}Model will not be available for download on Platform (upload failed)")
|
| 503 |
+
|
| 504 |
+
# Collect plots from trainer and validator, deduplicating by type
|
| 505 |
+
plots_by_type = {}
|
| 506 |
+
for info in getattr(trainer, "plots", {}).values():
|
| 507 |
+
if info.get("data") and info["data"].get("type"):
|
| 508 |
+
plots_by_type[info["data"]["type"]] = info["data"]
|
| 509 |
+
for info in getattr(getattr(trainer, "validator", None), "plots", {}).values():
|
| 510 |
+
if info.get("data") and info["data"].get("type"):
|
| 511 |
+
plots_by_type.setdefault(info["data"]["type"], info["data"]) # Don't overwrite trainer plots
|
| 512 |
+
plots = [_interp_plot(p) for p in plots_by_type.values()] # Interpolate curves to reduce size
|
| 513 |
+
|
| 514 |
+
# Get class names
|
| 515 |
+
names = getattr(getattr(trainer, "validator", None), "names", None) or (trainer.data or {}).get("names")
|
| 516 |
+
class_names = list(names.values()) if isinstance(names, dict) else list(names) if names else None
|
| 517 |
+
|
| 518 |
+
# stopper.best_epoch is 1-indexed; -1 aligns with the 0-indexed `epoch` field
|
| 519 |
+
best_epoch = max(0, getattr(getattr(trainer, "stopper", None), "best_epoch", trainer.epoch + 1) - 1)
|
| 520 |
+
|
| 521 |
+
_send(
|
| 522 |
+
"training_complete",
|
| 523 |
+
{
|
| 524 |
+
"results": {
|
| 525 |
+
"metrics": {**trainer.metrics, "fitness": trainer.fitness},
|
| 526 |
+
"bestEpoch": best_epoch,
|
| 527 |
+
"bestFitness": trainer.best_fitness,
|
| 528 |
+
"modelPath": gcs_path, # Only send GCS path, not local path
|
| 529 |
+
"modelSize": model_size,
|
| 530 |
+
},
|
| 531 |
+
"classNames": class_names,
|
| 532 |
+
"plots": plots,
|
| 533 |
+
},
|
| 534 |
+
project,
|
| 535 |
+
name,
|
| 536 |
+
ctx["model_id"],
|
| 537 |
+
retry=4, # Critical, more retries
|
| 538 |
+
)
|
| 539 |
+
url = f"{PLATFORM_URL}/{project}/{ctx.get('model_slug', name)}"
|
| 540 |
+
LOGGER.info(f"{PREFIX}View results at {url}")
|
| 541 |
+
|
| 542 |
+
|
| 543 |
+
callbacks = (
|
| 544 |
+
{
|
| 545 |
+
"on_pretrain_routine_start": on_pretrain_routine_start,
|
| 546 |
+
"on_pretrain_routine_end": on_pretrain_routine_end,
|
| 547 |
+
"on_fit_epoch_end": on_fit_epoch_end,
|
| 548 |
+
"on_model_save": on_model_save,
|
| 549 |
+
"on_train_end": on_train_end,
|
| 550 |
+
}
|
| 551 |
+
if _api_key
|
| 552 |
+
else {}
|
| 553 |
+
)
|
.venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/raytune.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
| 2 |
+
|
| 3 |
+
from ultralytics.utils import SETTINGS
|
| 4 |
+
|
| 5 |
+
try:
|
| 6 |
+
assert SETTINGS["raytune"] is True # verify integration is enabled
|
| 7 |
+
import ray
|
| 8 |
+
from ray import tune
|
| 9 |
+
from ray.air import session
|
| 10 |
+
|
| 11 |
+
except (ImportError, AssertionError):
|
| 12 |
+
tune = None
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def on_fit_epoch_end(trainer):
|
| 16 |
+
"""Report training metrics to Ray Tune at epoch end when a Ray session is active.
|
| 17 |
+
|
| 18 |
+
Captures metrics from the trainer object and sends them to Ray Tune with the current epoch number, enabling
|
| 19 |
+
hyperparameter tuning optimization. Only executes when within an active Ray Tune session.
|
| 20 |
+
|
| 21 |
+
Args:
|
| 22 |
+
trainer (ultralytics.engine.trainer.BaseTrainer): The Ultralytics trainer object containing metrics and epochs.
|
| 23 |
+
|
| 24 |
+
Examples:
|
| 25 |
+
>>> # Called automatically by the Ultralytics training loop
|
| 26 |
+
>>> on_fit_epoch_end(trainer)
|
| 27 |
+
|
| 28 |
+
References:
|
| 29 |
+
Ray Tune docs: https://docs.ray.io/en/latest/tune/index.html
|
| 30 |
+
"""
|
| 31 |
+
if ray.train._internal.session.get_session(): # check if Ray Tune session is active
|
| 32 |
+
metrics = trainer.metrics
|
| 33 |
+
session.report({**metrics, **{"epoch": trainer.epoch + 1}})
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
callbacks = (
|
| 37 |
+
{
|
| 38 |
+
"on_fit_epoch_end": on_fit_epoch_end,
|
| 39 |
+
}
|
| 40 |
+
if tune
|
| 41 |
+
else {}
|
| 42 |
+
)
|