emreyoleridev commited on
Commit
7d1212d
·
verified ·
1 Parent(s): 822186c

Upload folder using huggingface_hub (part 24)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +3 -0
  2. .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/INSTALLER +1 -0
  3. .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/METADATA +398 -0
  4. .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/RECORD +604 -0
  5. .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/REQUESTED +0 -0
  6. .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/WHEEL +5 -0
  7. .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/entry_points.txt +3 -0
  8. .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/licenses/LICENSE +661 -0
  9. .venv/lib/python3.14/site-packages/ultralytics-8.4.83.dist-info/top_level.txt +1 -0
  10. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/files.cpython-314.pyc +0 -0
  11. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/git.cpython-314.pyc +0 -0
  12. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/instance.cpython-314.pyc +0 -0
  13. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/logger.cpython-314.pyc +0 -0
  14. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/loss.cpython-314.pyc +0 -0
  15. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/metrics.cpython-314.pyc +3 -0
  16. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/nms.cpython-314.pyc +0 -0
  17. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/ops.cpython-314.pyc +0 -0
  18. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/patches.cpython-314.pyc +0 -0
  19. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/plotting.cpython-314.pyc +0 -0
  20. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tal.cpython-314.pyc +0 -0
  21. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/torch_utils.cpython-314.pyc +0 -0
  22. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tqdm.cpython-314.pyc +0 -0
  23. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/triton.cpython-314.pyc +0 -0
  24. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/tuner.cpython-314.pyc +0 -0
  25. .venv/lib/python3.14/site-packages/ultralytics/utils/__pycache__/uploads.cpython-314.pyc +0 -0
  26. .venv/lib/python3.14/site-packages/ultralytics/utils/autobatch.py +131 -0
  27. .venv/lib/python3.14/site-packages/ultralytics/utils/autodevice.py +207 -0
  28. .venv/lib/python3.14/site-packages/ultralytics/utils/benchmarks.py +618 -0
  29. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__init__.py +5 -0
  30. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/__init__.cpython-314.pyc +0 -0
  31. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/base.cpython-314.pyc +0 -0
  32. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/clearml.cpython-314.pyc +0 -0
  33. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/comet.cpython-314.pyc +0 -0
  34. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/dvc.cpython-314.pyc +0 -0
  35. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/hub.cpython-314.pyc +0 -0
  36. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/mlflow.cpython-314.pyc +0 -0
  37. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/neptune.cpython-314.pyc +0 -0
  38. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/platform.cpython-314.pyc +0 -0
  39. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/raytune.cpython-314.pyc +0 -0
  40. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/tensorboard.cpython-314.pyc +0 -0
  41. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/__pycache__/wb.cpython-314.pyc +0 -0
  42. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/base.py +235 -0
  43. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/clearml.py +146 -0
  44. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/comet.py +622 -0
  45. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/dvc.py +197 -0
  46. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/hub.py +111 -0
  47. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/mlflow.py +162 -0
  48. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/neptune.py +126 -0
  49. .venv/lib/python3.14/site-packages/ultralytics/utils/callbacks/platform.py +553 -0
  50. .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&amp;utm_medium=badge&amp;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
+ [![PyPI - Version](https://img.shields.io/pypi/v/ultralytics?logo=pypi&logoColor=white)](https://pypi.org/project/ultralytics/) [![Ultralytics Downloads](https://static.pepy.tech/badge/ultralytics)](https://clickpy.clickhouse.com/dashboard/ultralytics) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ultralytics?logo=python&logoColor=gold)](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
+ [![Conda Version](https://img.shields.io/conda/vn/conda-forge/ultralytics?logo=condaforge)](https://anaconda.org/conda-forge/ultralytics) [![Docker Image Version](https://img.shields.io/docker/v/ultralytics/ultralytics?sort=semver&logo=docker)](https://hub.docker.com/r/ultralytics/ultralytics) [![Ultralytics Docker Pulls](https://img.shields.io/docker/pulls/ultralytics/ultralytics?logo=docker)](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 &times; 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 &times; 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 &times; 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 &times; 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 &times; 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
+ [![Ultralytics open-source contributors](https://raw.githubusercontent.com/ultralytics/assets/main/im/image-contributors.png)](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
+ )