ultralytics 8.0.139__tar.gz → 8.0.141__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ultralytics might be problematic. Click here for more details.

Files changed (176) hide show
  1. {ultralytics-8.0.139 → ultralytics-8.0.141}/CONTRIBUTING.md +1 -1
  2. {ultralytics-8.0.139/ultralytics.egg-info → ultralytics-8.0.141}/PKG-INFO +5 -5
  3. {ultralytics-8.0.139 → ultralytics-8.0.141}/README.md +4 -4
  4. {ultralytics-8.0.139 → ultralytics-8.0.141}/README.zh-CN.md +4 -4
  5. {ultralytics-8.0.139 → ultralytics-8.0.141}/tests/test_python.py +1 -1
  6. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/__init__.py +3 -2
  7. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/__init__.py +48 -35
  8. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/engine/exporter.py +18 -13
  9. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/hub/auth.py +2 -2
  10. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/tasks.py +3 -1
  11. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/__init__.py +90 -47
  12. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/clearml.py +2 -1
  13. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/comet.py +2 -1
  14. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/dvc.py +2 -1
  15. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/hub.py +2 -2
  16. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/mlflow.py +2 -1
  17. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/neptune.py +2 -1
  18. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/raytune.py +4 -0
  19. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/tensorboard.py +5 -2
  20. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/wb.py +3 -2
  21. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/downloads.py +1 -1
  22. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/files.py +53 -0
  23. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/torch_utils.py +5 -2
  24. {ultralytics-8.0.139 → ultralytics-8.0.141/ultralytics.egg-info}/PKG-INFO +5 -5
  25. {ultralytics-8.0.139 → ultralytics-8.0.141}/LICENSE +0 -0
  26. {ultralytics-8.0.139 → ultralytics-8.0.141}/MANIFEST.in +0 -0
  27. {ultralytics-8.0.139 → ultralytics-8.0.141}/requirements.txt +0 -0
  28. {ultralytics-8.0.139 → ultralytics-8.0.141}/setup.cfg +0 -0
  29. {ultralytics-8.0.139 → ultralytics-8.0.141}/setup.py +0 -0
  30. {ultralytics-8.0.139 → ultralytics-8.0.141}/tests/test_cli.py +0 -0
  31. {ultralytics-8.0.139 → ultralytics-8.0.141}/tests/test_engine.py +0 -0
  32. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/assets/bus.jpg +0 -0
  33. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/assets/zidane.jpg +0 -0
  34. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/Argoverse.yaml +0 -0
  35. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/GlobalWheat2020.yaml +0 -0
  36. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/ImageNet.yaml +0 -0
  37. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/Objects365.yaml +0 -0
  38. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/SKU-110K.yaml +0 -0
  39. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/VOC.yaml +0 -0
  40. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/VisDrone.yaml +0 -0
  41. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/coco-pose.yaml +0 -0
  42. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/coco.yaml +0 -0
  43. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/coco128-seg.yaml +0 -0
  44. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/coco128.yaml +0 -0
  45. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/coco8-pose.yaml +0 -0
  46. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/coco8-seg.yaml +0 -0
  47. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/coco8.yaml +0 -0
  48. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/datasets/xView.yaml +0 -0
  49. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/default.yaml +0 -0
  50. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +0 -0
  51. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +0 -0
  52. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v3/yolov3-spp.yaml +0 -0
  53. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v3/yolov3-tiny.yaml +0 -0
  54. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v3/yolov3.yaml +0 -0
  55. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v5/yolov5-p6.yaml +0 -0
  56. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v5/yolov5.yaml +0 -0
  57. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v6/yolov6.yaml +0 -0
  58. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v8/yolov8-cls.yaml +0 -0
  59. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v8/yolov8-p2.yaml +0 -0
  60. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v8/yolov8-p6.yaml +0 -0
  61. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +0 -0
  62. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v8/yolov8-pose.yaml +0 -0
  63. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +0 -0
  64. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v8/yolov8-seg.yaml +0 -0
  65. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/models/v8/yolov8.yaml +0 -0
  66. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/trackers/botsort.yaml +0 -0
  67. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/cfg/trackers/bytetrack.yaml +0 -0
  68. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/__init__.py +0 -0
  69. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/annotator.py +0 -0
  70. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/augment.py +0 -0
  71. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/base.py +0 -0
  72. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/build.py +0 -0
  73. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/converter.py +0 -0
  74. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/dataloaders/__init__.py +0 -0
  75. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/dataset.py +0 -0
  76. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/loaders.py +0 -0
  77. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/data/utils.py +0 -0
  78. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/engine/__init__.py +0 -0
  79. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/engine/model.py +0 -0
  80. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/engine/predictor.py +0 -0
  81. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/engine/results.py +0 -0
  82. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/engine/trainer.py +0 -0
  83. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/engine/validator.py +0 -0
  84. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/hub/__init__.py +0 -0
  85. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/hub/session.py +0 -0
  86. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/hub/utils.py +0 -0
  87. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/__init__.py +0 -0
  88. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/fastsam/__init__.py +0 -0
  89. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/fastsam/model.py +0 -0
  90. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/fastsam/predict.py +0 -0
  91. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/fastsam/prompt.py +0 -0
  92. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/fastsam/utils.py +0 -0
  93. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/fastsam/val.py +0 -0
  94. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/nas/__init__.py +0 -0
  95. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/nas/model.py +0 -0
  96. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/nas/predict.py +0 -0
  97. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/nas/val.py +0 -0
  98. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/rtdetr/__init__.py +0 -0
  99. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/rtdetr/model.py +0 -0
  100. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/rtdetr/predict.py +0 -0
  101. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/rtdetr/train.py +0 -0
  102. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/rtdetr/val.py +0 -0
  103. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/__init__.py +0 -0
  104. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/amg.py +0 -0
  105. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/build.py +0 -0
  106. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/model.py +0 -0
  107. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/modules/__init__.py +0 -0
  108. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/modules/decoders.py +0 -0
  109. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/modules/encoders.py +0 -0
  110. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/modules/sam.py +0 -0
  111. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/modules/tiny_encoder.py +0 -0
  112. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/modules/transformer.py +0 -0
  113. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/sam/predict.py +0 -0
  114. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/utils/__init__.py +0 -0
  115. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/utils/loss.py +0 -0
  116. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/utils/ops.py +0 -0
  117. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/__init__.py +0 -0
  118. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/classify/__init__.py +0 -0
  119. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/classify/predict.py +0 -0
  120. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/classify/train.py +0 -0
  121. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/classify/val.py +0 -0
  122. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/detect/__init__.py +0 -0
  123. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/detect/predict.py +0 -0
  124. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/detect/train.py +0 -0
  125. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/detect/val.py +0 -0
  126. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/pose/__init__.py +0 -0
  127. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/pose/predict.py +0 -0
  128. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/pose/train.py +0 -0
  129. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/pose/val.py +0 -0
  130. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/segment/__init__.py +0 -0
  131. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/segment/predict.py +0 -0
  132. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/segment/train.py +0 -0
  133. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/models/yolo/segment/val.py +0 -0
  134. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/__init__.py +0 -0
  135. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/autobackend.py +0 -0
  136. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/modules/__init__.py +0 -0
  137. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/modules/block.py +0 -0
  138. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/modules/conv.py +0 -0
  139. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/modules/head.py +0 -0
  140. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/modules/transformer.py +0 -0
  141. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/nn/modules/utils.py +0 -0
  142. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/__init__.py +0 -0
  143. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/basetrack.py +0 -0
  144. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/bot_sort.py +0 -0
  145. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/byte_tracker.py +0 -0
  146. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/track.py +0 -0
  147. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/utils/__init__.py +0 -0
  148. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/utils/gmc.py +0 -0
  149. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/utils/kalman_filter.py +0 -0
  150. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/trackers/utils/matching.py +0 -0
  151. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/autobatch.py +0 -0
  152. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/benchmarks.py +0 -0
  153. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/__init__.py +0 -0
  154. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/callbacks/base.py +0 -0
  155. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/checks.py +0 -0
  156. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/dist.py +0 -0
  157. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/errors.py +0 -0
  158. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/instance.py +0 -0
  159. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/loss.py +0 -0
  160. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/metrics.py +0 -0
  161. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/ops.py +0 -0
  162. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/patches.py +0 -0
  163. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/plotting.py +0 -0
  164. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/tal.py +0 -0
  165. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/utils/tuner.py +0 -0
  166. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/yolo/__init__.py +0 -0
  167. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/yolo/cfg/__init__.py +0 -0
  168. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/yolo/data/__init__.py +0 -0
  169. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/yolo/engine/__init__.py +0 -0
  170. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/yolo/utils/__init__.py +0 -0
  171. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics/yolo/v8/__init__.py +0 -0
  172. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics.egg-info/SOURCES.txt +0 -0
  173. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics.egg-info/dependency_links.txt +0 -0
  174. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics.egg-info/entry_points.txt +0 -0
  175. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics.egg-info/requires.txt +0 -0
  176. {ultralytics-8.0.139 → ultralytics-8.0.141}/ultralytics.egg-info/top_level.txt +0 -0
@@ -65,7 +65,7 @@ Here is an example:
65
65
 
66
66
  ```python
67
67
  """
68
- What the function does. Performs NMS on given detection predictions.
68
+ What the function does. Performs NMS on given detection predictions.
69
69
 
70
70
  Args:
71
71
  arg1: The description of the 1st argument
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ultralytics
3
- Version: 8.0.139
3
+ Version: 8.0.141
4
4
  Summary: Ultralytics YOLOv8 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
5
5
  Home-page: https://github.com/ultralytics/ultralytics
6
6
  Author: Ultralytics
@@ -270,14 +270,14 @@ We love your input! YOLOv5 and YOLOv8 would not be possible without help from ou
270
270
 
271
271
  ## <div align="center">License</div>
272
272
 
273
- YOLOv8 is available under two different licenses:
273
+ Ultralytics offers two licensing options to accommodate diverse use cases:
274
274
 
275
- - **AGPL-3.0 License**: See [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) file for details.
276
- - **Enterprise License**: Provides greater flexibility for commercial product development without the open-source requirements of AGPL-3.0. Typical use cases are embedding Ultralytics software and AI models in commercial products and applications. Request an Enterprise License at [Ultralytics Licensing](https://ultralytics.com/license).
275
+ - **AGPL-3.0 License**: This [OSI-approved](https://opensource.org/licenses/) open-source license is ideal for students and enthusiasts, promoting open collaboration and knowledge sharing. See the [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) file for more details.
276
+ - **Enterprise License**: Designed for commercial use, this license permits seamless integration of Ultralytics software and AI models into commercial goods and services, bypassing the open-source requirements of AGPL-3.0. If your scenario involves embedding our solutions into a commercial offering, reach out through [Ultralytics Licensing](https://ultralytics.com/license).
277
277
 
278
278
  ## <div align="center">Contact</div>
279
279
 
280
- For YOLOv8 bug reports and feature requests please visit [GitHub Issues](https://github.com/ultralytics/ultralytics/issues), and join our [Discord](https://discord.gg/2wNGbc6g9X) community for questions and discussions!
280
+ For Ultralytics bug reports and feature requests please visit [GitHub Issues](https://github.com/ultralytics/ultralytics/issues), and join our [Discord](https://discord.gg/2wNGbc6g9X) community for questions and discussions!
281
281
 
282
282
  <br>
283
283
  <div align="center">
@@ -234,14 +234,14 @@ We love your input! YOLOv5 and YOLOv8 would not be possible without help from ou
234
234
 
235
235
  ## <div align="center">License</div>
236
236
 
237
- YOLOv8 is available under two different licenses:
237
+ Ultralytics offers two licensing options to accommodate diverse use cases:
238
238
 
239
- - **AGPL-3.0 License**: See [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) file for details.
240
- - **Enterprise License**: Provides greater flexibility for commercial product development without the open-source requirements of AGPL-3.0. Typical use cases are embedding Ultralytics software and AI models in commercial products and applications. Request an Enterprise License at [Ultralytics Licensing](https://ultralytics.com/license).
239
+ - **AGPL-3.0 License**: This [OSI-approved](https://opensource.org/licenses/) open-source license is ideal for students and enthusiasts, promoting open collaboration and knowledge sharing. See the [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) file for more details.
240
+ - **Enterprise License**: Designed for commercial use, this license permits seamless integration of Ultralytics software and AI models into commercial goods and services, bypassing the open-source requirements of AGPL-3.0. If your scenario involves embedding our solutions into a commercial offering, reach out through [Ultralytics Licensing](https://ultralytics.com/license).
241
241
 
242
242
  ## <div align="center">Contact</div>
243
243
 
244
- For YOLOv8 bug reports and feature requests please visit [GitHub Issues](https://github.com/ultralytics/ultralytics/issues), and join our [Discord](https://discord.gg/2wNGbc6g9X) community for questions and discussions!
244
+ For Ultralytics bug reports and feature requests please visit [GitHub Issues](https://github.com/ultralytics/ultralytics/issues), and join our [Discord](https://discord.gg/2wNGbc6g9X) community for questions and discussions!
245
245
 
246
246
  <br>
247
247
  <div align="center">
@@ -233,14 +233,14 @@ success = model.export(format="onnx") # 将模型导出为 ONNX 格式
233
233
 
234
234
  ## <div align="center">许可证</div>
235
235
 
236
- YOLOv8 提供两种不同的许可证:
236
+ Ultralytics 提供两种许可证选项以适应各种使用场景:
237
237
 
238
- - **AGPL-3.0 许可证**:详细信息请参阅 [LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) 文件。
239
- - **企业许可证**:为商业产品开发提供更大的灵活性,无需遵循 AGPL-3.0 的开源要求。典型的用例是将 Ultralytics 软件和 AI 模型嵌入商业产品和应用中。在 [Ultralytics 授权](https://ultralytics.com/license) 处申请企业许可证。
238
+ - **AGPL-3.0 许可证**:这个[OSI 批准](https://opensource.org/licenses/)的开源许可证非常适合学生和爱好者,可以推动开放的协作和知识分享。请查看[LICENSE](https://github.com/ultralytics/ultralytics/blob/main/LICENSE) 文件以了解更多细节。
239
+ - **企业许可证**:专为商业用途设计,该许可证允许将 Ultralytics 的软件和 AI 模型无缝集成到商业产品和服务中,从而绕过 AGPL-3.0 的开源要求。如果您的场景涉及将我们的解决方案嵌入到商业产品中,请通过 [Ultralytics Licensing](https://ultralytics.com/license)与我们联系。
240
240
 
241
241
  ## <div align="center">联系方式</div>
242
242
 
243
- 对于 YOLOv8 的错误报告和功能请求,请访问 [GitHub Issues](https://github.com/ultralytics/ultralytics/issues),并加入我们的 [Discord](https://discord.gg/2wNGbc6g9X) 社区进行问题和讨论!
243
+ 对于 Ultralytics 的错误报告和功能请求,请访问 [GitHub Issues](https://github.com/ultralytics/ultralytics/issues),并加入我们的 [Discord](https://discord.gg/2wNGbc6g9X) 社区进行问题和讨论!
244
244
 
245
245
  <br>
246
246
  <div align="center">
@@ -12,7 +12,7 @@ from ultralytics import RTDETR, YOLO
12
12
  from ultralytics.data.build import load_inference_source
13
13
  from ultralytics.utils import LINUX, ONLINE, ROOT, SETTINGS
14
14
 
15
- MODEL = Path(SETTINGS['weights_dir']) / 'yolov8n.pt'
15
+ MODEL = Path(SETTINGS['weights_dir']) / 'path with spaces' / 'yolov8n.pt' # test spaces in path
16
16
  CFG = 'yolov8n.yaml'
17
17
  SOURCE = ROOT / 'assets/bus.jpg'
18
18
  SOURCE_GREYSCALE = Path(f'{SOURCE.parent / SOURCE.stem}_greyscale.jpg')
@@ -1,13 +1,14 @@
1
1
  # Ultralytics YOLO 🚀, AGPL-3.0 license
2
2
 
3
- __version__ = '8.0.139'
3
+ __version__ = '8.0.141'
4
4
 
5
5
  from ultralytics.engine.model import YOLO
6
6
  from ultralytics.hub import start
7
7
  from ultralytics.models import RTDETR, SAM
8
8
  from ultralytics.models.fastsam import FastSAM
9
9
  from ultralytics.models.nas import NAS
10
+ from ultralytics.utils import SETTINGS as settings
10
11
  from ultralytics.utils.checks import check_yolo as checks
11
12
  from ultralytics.utils.downloads import download
12
13
 
13
- __all__ = '__version__', 'YOLO', 'NAS', 'SAM', 'FastSAM', 'RTDETR', 'checks', 'download', 'start' # allow simpler import
14
+ __all__ = '__version__', 'YOLO', 'NAS', 'SAM', 'FastSAM', 'RTDETR', 'checks', 'download', 'start', 'settings' # allow simpler import
@@ -9,9 +9,9 @@ from pathlib import Path
9
9
  from types import SimpleNamespace
10
10
  from typing import Dict, List, Union
11
11
 
12
- from ultralytics.utils import (DEFAULT_CFG, DEFAULT_CFG_DICT, DEFAULT_CFG_PATH, LOGGER, ROOT, USER_CONFIG_DIR,
13
- IterableSimpleNamespace, __version__, checks, colorstr, deprecation_warn, get_settings,
14
- yaml_load, yaml_print)
12
+ from ultralytics.utils import (DEFAULT_CFG, DEFAULT_CFG_DICT, DEFAULT_CFG_PATH, LOGGER, ROOT, SETTINGS, SETTINGS_YAML,
13
+ IterableSimpleNamespace, __version__, checks, colorstr, deprecation_warn, yaml_load,
14
+ yaml_print)
15
15
 
16
16
  # Define valid tasks and modes
17
17
  MODES = 'train', 'val', 'predict', 'export', 'track', 'benchmark'
@@ -28,7 +28,6 @@ TASK2METRIC = {
28
28
  'classify': 'metrics/accuracy_top1',
29
29
  'pose': 'metrics/mAP50-95(P)'}
30
30
 
31
-
32
31
  CLI_HELP_MSG = \
33
32
  f"""
34
33
  Arguments received: {str(['yolo'] + sys.argv[1:])}. Ultralytics 'yolo' commands use the following syntax:
@@ -111,7 +110,7 @@ def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, ove
111
110
  # Merge overrides
112
111
  if overrides:
113
112
  overrides = cfg2dict(overrides)
114
- check_cfg_mismatch(cfg, overrides)
113
+ check_dict_alignment(cfg, overrides)
115
114
  cfg = {**cfg, **overrides} # merge cfg and overrides dicts (prefer overrides)
116
115
 
117
116
  # Special handling for numeric project/name
@@ -147,9 +146,7 @@ def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, ove
147
146
 
148
147
 
149
148
  def _handle_deprecation(custom):
150
- """
151
- Hardcoded function to handle deprecated config keys
152
- """
149
+ """Hardcoded function to handle deprecated config keys"""
153
150
 
154
151
  for key in custom.copy().keys():
155
152
  if key == 'hide_labels':
@@ -165,7 +162,7 @@ def _handle_deprecation(custom):
165
162
  return custom
166
163
 
167
164
 
168
- def check_cfg_mismatch(base: Dict, custom: Dict, e=None):
165
+ def check_dict_alignment(base: Dict, custom: Dict, e=None):
169
166
  """
170
167
  This function checks for any mismatched keys between a custom configuration list and a base configuration list.
171
168
  If any mismatched keys are found, the function prints out similar keys from the base list and exits the program.
@@ -175,13 +172,13 @@ def check_cfg_mismatch(base: Dict, custom: Dict, e=None):
175
172
  base (dict): a dictionary of base configuration options
176
173
  """
177
174
  custom = _handle_deprecation(custom)
178
- base, custom = (set(x.keys()) for x in (base, custom))
179
- mismatched = [x for x in custom if x not in base]
175
+ base_keys, custom_keys = (set(x.keys()) for x in (base, custom))
176
+ mismatched = [k for k in custom_keys if k not in base_keys]
180
177
  if mismatched:
181
178
  string = ''
182
179
  for x in mismatched:
183
- matches = get_close_matches(x, base) # key list
184
- matches = [f'{k}={DEFAULT_CFG_DICT[k]}' if DEFAULT_CFG_DICT.get(k) is not None else k for k in matches]
180
+ matches = get_close_matches(x, base_keys) # key list
181
+ matches = [f'{k}={base[k]}' if base.get(k) is not None else k for k in matches]
185
182
  match_str = f'Similar arguments are i.e. {matches}.' if matches else ''
186
183
  string += f"'{colorstr('red', 'bold', x)}' is not a valid YOLO argument. {match_str}\n"
187
184
  raise SyntaxError(string + CLI_HELP_MSG) from e
@@ -251,12 +248,39 @@ def handle_yolo_settings(args: List[str]) -> None:
251
248
  Example:
252
249
  python my_script.py yolo settings reset
253
250
  """
254
- path = USER_CONFIG_DIR / 'settings.yaml' # get SETTINGS YAML file path
255
- if any(args) and args[0] == 'reset':
256
- path.unlink() # delete the settings file
257
- get_settings() # create new settings
258
- LOGGER.info('Settings reset successfully') # inform the user that settings have been reset
259
- yaml_print(path) # print the current settings
251
+ if any(args):
252
+ if args[0] == 'reset':
253
+ SETTINGS_YAML.unlink() # delete the settings file
254
+ SETTINGS.reset() # create new settings
255
+ LOGGER.info('Settings reset successfully') # inform the user that settings have been reset
256
+ else:
257
+ new = dict(parse_key_value_pair(a) for a in args)
258
+ check_dict_alignment(SETTINGS, new)
259
+ SETTINGS.update(new)
260
+
261
+ yaml_print(SETTINGS_YAML) # print the current settings
262
+
263
+
264
+ def parse_key_value_pair(pair):
265
+ """Parse one 'key=value' pair and return key and value."""
266
+ re.sub(r' *= *', '=', pair) # remove spaces around equals sign
267
+ k, v = pair.split('=', 1) # split on first '=' sign
268
+ assert v, f"missing '{k}' value"
269
+ return k, smart_value(v)
270
+
271
+
272
+ def smart_value(v):
273
+ """Convert a string to an underlying type such as int, float, bool, etc."""
274
+ if v.lower() == 'none':
275
+ return None
276
+ elif v.lower() == 'true':
277
+ return True
278
+ elif v.lower() == 'false':
279
+ return False
280
+ else:
281
+ with contextlib.suppress(Exception):
282
+ return eval(v)
283
+ return v
260
284
 
261
285
 
262
286
  def entrypoint(debug=''):
@@ -305,25 +329,14 @@ def entrypoint(debug=''):
305
329
  a = a[:-1]
306
330
  if '=' in a:
307
331
  try:
308
- re.sub(r' *= *', '=', a) # remove spaces around equals sign
309
- k, v = a.split('=', 1) # split on first '=' sign
310
- assert v, f"missing '{k}' value"
332
+ k, v = parse_key_value_pair(a)
311
333
  if k == 'cfg': # custom.yaml passed
312
334
  LOGGER.info(f'Overriding {DEFAULT_CFG_PATH} with {v}')
313
335
  overrides = {k: val for k, val in yaml_load(checks.check_yaml(v)).items() if k != 'cfg'}
314
336
  else:
315
- if v.lower() == 'none':
316
- v = None
317
- elif v.lower() == 'true':
318
- v = True
319
- elif v.lower() == 'false':
320
- v = False
321
- else:
322
- with contextlib.suppress(Exception):
323
- v = eval(v)
324
337
  overrides[k] = v
325
338
  except (NameError, SyntaxError, ValueError, AssertionError) as e:
326
- check_cfg_mismatch(full_args_dict, {a: ''}, e)
339
+ check_dict_alignment(full_args_dict, {a: ''}, e)
327
340
 
328
341
  elif a in TASKS:
329
342
  overrides['task'] = a
@@ -338,13 +351,13 @@ def entrypoint(debug=''):
338
351
  raise SyntaxError(f"'{colorstr('red', 'bold', a)}' is a valid YOLO argument but is missing an '=' sign "
339
352
  f"to set its value, i.e. try '{a}={DEFAULT_CFG_DICT[a]}'\n{CLI_HELP_MSG}")
340
353
  else:
341
- check_cfg_mismatch(full_args_dict, {a: ''})
354
+ check_dict_alignment(full_args_dict, {a: ''})
342
355
 
343
356
  # Check keys
344
- check_cfg_mismatch(full_args_dict, overrides)
357
+ check_dict_alignment(full_args_dict, overrides)
345
358
 
346
359
  # Mode
347
- mode = overrides.get('mode', None)
360
+ mode = overrides.get('mode')
348
361
  if mode is None:
349
362
  mode = DEFAULT_CFG.mode or 'predict'
350
363
  LOGGER.warning(f"WARNING ⚠️ 'mode' is missing. Valid modes are {MODES}. Using default 'mode={mode}'.")
@@ -68,7 +68,7 @@ from ultralytics.utils import (ARM64, DEFAULT_CFG, LINUX, LOGGER, MACOS, ROOT, W
68
68
  colorstr, get_default_args, yaml_save)
69
69
  from ultralytics.utils.checks import check_imgsz, check_requirements, check_version
70
70
  from ultralytics.utils.downloads import attempt_download_asset, get_github_assets
71
- from ultralytics.utils.files import file_size
71
+ from ultralytics.utils.files import file_size, spaces_in_path
72
72
  from ultralytics.utils.ops import Profile
73
73
  from ultralytics.utils.torch_utils import get_latest_opset, select_device, smart_inference_mode
74
74
 
@@ -112,7 +112,7 @@ def try_export(inner_func):
112
112
  try:
113
113
  with Profile() as dt:
114
114
  f, model = inner_func(*args, **kwargs)
115
- LOGGER.info(f'{prefix} export success ✅ {dt.t:.1f}s, saved as {f} ({file_size(f):.1f} MB)')
115
+ LOGGER.info(f"{prefix} export success ✅ {dt.t:.1f}s, saved as '{f}' ({file_size(f):.1f} MB)")
116
116
  return f, model
117
117
  except Exception as e:
118
118
  LOGGER.info(f'{prefix} export failure ❌ {dt.t:.1f}s: {e}')
@@ -230,7 +230,7 @@ class Exporter:
230
230
  if model.task == 'pose':
231
231
  self.metadata['kpt_shape'] = model.model[-1].kpt_shape
232
232
 
233
- LOGGER.info(f"\n{colorstr('PyTorch:')} starting from {file} with input shape {tuple(im.shape)} BCHW and "
233
+ LOGGER.info(f"\n{colorstr('PyTorch:')} starting from '{file}' with input shape {tuple(im.shape)} BCHW and "
234
234
  f'output shape(s) {self.output_shape} ({file_size(file):.1f} MB)')
235
235
 
236
236
  # Exports
@@ -340,7 +340,7 @@ class Exporter:
340
340
  import onnxsim
341
341
 
342
342
  LOGGER.info(f'{prefix} simplifying with onnxsim {onnxsim.__version__}...')
343
- # subprocess.run(f'onnxsim {f} {f}', shell=True)
343
+ # subprocess.run(f'onnxsim "{f}" "{f}"', shell=True)
344
344
  model_onnx, check = onnxsim.simplify(model_onnx)
345
345
  assert check, 'Simplified ONNX model could not be validated'
346
346
  except Exception as e:
@@ -410,7 +410,7 @@ class Exporter:
410
410
 
411
411
  LOGGER.info(f'\n{prefix} starting export with ncnn {ncnn.__version__}...')
412
412
  f = Path(str(self.file).replace(self.file.suffix, f'_ncnn_model{os.sep}'))
413
- f_ts = str(self.file.with_suffix('.torchscript'))
413
+ f_ts = self.file.with_suffix('.torchscript')
414
414
 
415
415
  pnnx_filename = 'pnnx.exe' if WINDOWS else 'pnnx'
416
416
  if Path(pnnx_filename).is_file():
@@ -434,7 +434,7 @@ class Exporter:
434
434
 
435
435
  cmd = [
436
436
  str(pnnx),
437
- f_ts,
437
+ str(f_ts),
438
438
  f'pnnxparam={f / "model.pnnx.param"}',
439
439
  f'pnnxbin={f / "model.pnnx.bin"}',
440
440
  f'pnnxpy={f / "model_pnnx.py"}',
@@ -586,8 +586,8 @@ class Exporter:
586
586
 
587
587
  # Export to TF
588
588
  int8 = '-oiqt -qt per-tensor' if self.args.int8 else ''
589
- cmd = f'onnx2tf -i {f_onnx} -o {f} -nuo --non_verbose {int8}'
590
- LOGGER.info(f"\n{prefix} running '{cmd.strip()}'")
589
+ cmd = f'onnx2tf -i "{f_onnx}" -o "{f}" -nuo --non_verbose {int8}'
590
+ LOGGER.info(f"\n{prefix} running '{cmd}'")
591
591
  subprocess.run(cmd, shell=True)
592
592
  yaml_save(f / 'metadata.yaml', self.metadata) # add metadata.yaml
593
593
 
@@ -659,9 +659,9 @@ class Exporter:
659
659
  LOGGER.info(f'\n{prefix} starting export with Edge TPU compiler {ver}...')
660
660
  f = str(tflite_model).replace('.tflite', '_edgetpu.tflite') # Edge TPU model
661
661
 
662
- cmd = f'edgetpu_compiler -s -d -k 10 --out_dir {Path(f).parent} {tflite_model}'
662
+ cmd = f'edgetpu_compiler -s -d -k 10 --out_dir "{Path(f).parent}" "{tflite_model}"'
663
663
  LOGGER.info(f"{prefix} running '{cmd}'")
664
- subprocess.run(cmd.split(), check=True)
664
+ subprocess.run(cmd, shell=True)
665
665
  self._add_tflite_metadata(f)
666
666
  return f, None
667
667
 
@@ -674,7 +674,7 @@ class Exporter:
674
674
 
675
675
  LOGGER.info(f'\n{prefix} starting export with tensorflowjs {tfjs.__version__}...')
676
676
  f = str(self.file).replace(self.file.suffix, '_web_model') # js dir
677
- f_pb = self.file.with_suffix('.pb') # *.pb path
677
+ f_pb = str(self.file.with_suffix('.pb')) # *.pb path
678
678
 
679
679
  gd = tf.Graph().as_graph_def() # TF GraphDef
680
680
  with open(f_pb, 'rb') as file:
@@ -682,8 +682,13 @@ class Exporter:
682
682
  outputs = ','.join(gd_outputs(gd))
683
683
  LOGGER.info(f'\n{prefix} output node names: {outputs}')
684
684
 
685
- cmd = f'tensorflowjs_converter --input_format=tf_frozen_model --output_node_names={outputs} {f_pb} {f}'
686
- subprocess.run(cmd.split(), check=True)
685
+ with spaces_in_path(f_pb) as fpb_, spaces_in_path(f) as f_: # exporter can not handle spaces in path
686
+ cmd = f'tensorflowjs_converter --input_format=tf_frozen_model --output_node_names={outputs} "{fpb_}" "{f_}"'
687
+ LOGGER.info(f"{prefix} running '{cmd}'")
688
+ subprocess.run(cmd, shell=True)
689
+
690
+ if ' ' in str(f):
691
+ LOGGER.warning(f"{prefix} WARNING ⚠️ your model may not work correctly with spaces in path '{f}'.")
687
692
 
688
693
  # f_json = Path(f) / 'model.json' # *.json path
689
694
  # with open(f_json, 'w') as j: # sort JSON Identity_* in ascending order
@@ -3,7 +3,7 @@
3
3
  import requests
4
4
 
5
5
  from ultralytics.hub.utils import HUB_API_ROOT, PREFIX, request_with_credentials
6
- from ultralytics.utils import LOGGER, SETTINGS, emojis, is_colab, set_settings
6
+ from ultralytics.utils import LOGGER, SETTINGS, emojis, is_colab
7
7
 
8
8
  API_KEY_URL = 'https://hub.ultralytics.com/settings?tab=api+keys'
9
9
 
@@ -45,7 +45,7 @@ class Auth:
45
45
 
46
46
  # Update SETTINGS with the new API key after successful authentication
47
47
  if success:
48
- set_settings({'api_key': self.api_key})
48
+ SETTINGS.update({'api_key': self.api_key})
49
49
  # Log that the new login was successful
50
50
  if verbose:
51
51
  LOGGER.info(f'{PREFIX}New authentication successful ✅')
@@ -699,10 +699,12 @@ def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)
699
699
  args = [ch[f]]
700
700
  elif m is Concat:
701
701
  c2 = sum(ch[x] for x in f)
702
- elif m in (Detect, Segment, Pose, RTDETRDecoder):
702
+ elif m in (Detect, Segment, Pose):
703
703
  args.append([ch[x] for x in f])
704
704
  if m is Segment:
705
705
  args[2] = make_divisible(min(args[2], max_channels) * width, 8)
706
+ elif m is RTDETRDecoder: # special case, channels arg must be passed in index 1
707
+ args.insert(1, [ch[x] for x in f])
706
708
  else:
707
709
  c2 = ch[f]
708
710
 
@@ -713,62 +713,105 @@ def set_sentry():
713
713
  logging.getLogger(logger).setLevel(logging.CRITICAL)
714
714
 
715
715
 
716
- def get_settings(file=SETTINGS_YAML, version='0.0.3'):
716
+ def update_dict_recursive(d, u):
717
717
  """
718
- Loads a global Ultralytics settings YAML file or creates one with default values if it does not exist.
718
+ Recursively updates the dictionary `d` with the key-value pairs from the dictionary `u` without overwriting
719
+ entire sub-dictionaries. Note that function recursion is intended and not a problem, as this allows for updating
720
+ nested dictionaries at any arbitrary depth.
719
721
 
720
722
  Args:
721
- file (Path): Path to the Ultralytics settings YAML file. Defaults to 'settings.yaml' in the USER_CONFIG_DIR.
722
- version (str): Settings version. If min settings version not met, new default settings will be saved.
723
+ d (dict): The dictionary to be updated.
724
+ u (dict): The dictionary to update `d` with.
723
725
 
724
726
  Returns:
725
- (dict): Dictionary of settings key-value pairs.
727
+ (dict): The recursively updated dictionary.
726
728
  """
727
- import hashlib
729
+ for k, v in u.items():
730
+ d[k] = update_dict_recursive(d.get(k, {}), v) if isinstance(v, dict) else v
731
+ return d
728
732
 
729
- from ultralytics.utils.checks import check_version
730
- from ultralytics.utils.torch_utils import torch_distributed_zero_first
731
733
 
732
- git_dir = get_git_dir()
733
- root = git_dir or Path()
734
- datasets_root = (root.parent if git_dir and is_dir_writeable(root.parent) else root).resolve()
735
- defaults = {
736
- 'datasets_dir': str(datasets_root / 'datasets'), # default datasets directory.
737
- 'weights_dir': str(root / 'weights'), # default weights directory.
738
- 'runs_dir': str(root / 'runs'), # default runs directory.
739
- 'uuid': hashlib.sha256(str(uuid.getnode()).encode()).hexdigest(), # SHA-256 anonymized UUID hash
740
- 'sync': True, # sync analytics to help with YOLO development
741
- 'api_key': '', # Ultralytics HUB API key (https://hub.ultralytics.com/)
742
- 'settings_version': version} # Ultralytics settings version
743
-
744
- with torch_distributed_zero_first(RANK):
745
- if not file.exists():
746
- yaml_save(file, defaults)
747
- settings = yaml_load(file)
748
-
749
- # Check that settings keys and types match defaults
750
- correct = \
751
- settings \
752
- and settings.keys() == defaults.keys() \
753
- and all(type(a) == type(b) for a, b in zip(settings.values(), defaults.values())) \
754
- and check_version(settings['settings_version'], version)
755
- if not correct:
756
- LOGGER.warning('WARNING ⚠️ Ultralytics settings reset to defaults. This is normal and may be due to a '
757
- 'recent ultralytics package update, but may have overwritten previous settings. '
758
- f"\nView and update settings with 'yolo settings' or at '{file}'")
759
- settings = defaults # merge **defaults with **settings (prefer **settings)
760
- yaml_save(file, settings) # save updated defaults
761
-
762
- return settings
734
+ class SettingsManager(dict):
735
+ """
736
+ Manages Ultralytics settings stored in a YAML file.
763
737
 
738
+ Args:
739
+ file (str | Path): Path to the Ultralytics settings YAML file. Default is USER_CONFIG_DIR / 'settings.yaml'.
740
+ version (str): Settings version. In case of local version mismatch, new default settings will be saved.
741
+ """
742
+
743
+ def __init__(self, file=SETTINGS_YAML, version='0.0.4'):
744
+ import copy
745
+ import hashlib
746
+
747
+ from ultralytics.utils.checks import check_version
748
+ from ultralytics.utils.torch_utils import torch_distributed_zero_first
749
+
750
+ git_dir = get_git_dir()
751
+ root = git_dir or Path()
752
+ datasets_root = (root.parent if git_dir and is_dir_writeable(root.parent) else root).resolve()
753
+
754
+ self.file = Path(file)
755
+ self.version = version
756
+ self.defaults = {
757
+ 'settings_version': version,
758
+ 'datasets_dir': str(datasets_root / 'datasets'),
759
+ 'weights_dir': str(root / 'weights'),
760
+ 'runs_dir': str(root / 'runs'),
761
+ 'uuid': hashlib.sha256(str(uuid.getnode()).encode()).hexdigest(),
762
+ 'sync': True,
763
+ 'api_key': '',
764
+ 'clearml': True, # integrations
765
+ 'comet': True,
766
+ 'dvc': True,
767
+ 'hub': True,
768
+ 'mlflow': True,
769
+ 'neptune': True,
770
+ 'raytune': True,
771
+ 'tensorboard': True,
772
+ 'wandb': True}
773
+
774
+ super().__init__(copy.deepcopy(self.defaults))
775
+
776
+ with torch_distributed_zero_first(RANK):
777
+ if not self.file.exists():
778
+ self.save()
779
+
780
+ self.load()
781
+ correct_keys = self.keys() == self.defaults.keys()
782
+ correct_types = all(type(a) == type(b) for a, b in zip(self.values(), self.defaults.values()))
783
+ correct_version = check_version(self['settings_version'], self.version)
784
+ if not (correct_keys and correct_types and correct_version):
785
+ LOGGER.warning(
786
+ 'WARNING ⚠️ Ultralytics settings reset to default values. This may be due to a possible problem '
787
+ 'with your settings or a recent ultralytics package update. '
788
+ f"\nView settings with 'yolo settings' or at '{self.file}'"
789
+ "\nUpdate settings with 'yolo settings key=value', i.e. 'yolo settings runs_dir=path/to/dir'.")
790
+ self.reset()
791
+
792
+ def load(self):
793
+ """Loads settings from the YAML file."""
794
+ self.update(yaml_load(self.file))
795
+
796
+ def save(self):
797
+ """Saves the current settings to the YAML file."""
798
+ yaml_save(self.file, dict(self))
799
+
800
+ def update(self, *args, **kwargs):
801
+ """Updates a setting value in the current settings and saves the settings."""
802
+ new = dict(*args, **kwargs)
803
+ if any(isinstance(v, dict) for v in new.values()):
804
+ update_dict_recursive(self, new)
805
+ else:
806
+ # super().update(*args, **kwargs)
807
+ super().update(new)
808
+ self.save()
764
809
 
765
- def set_settings(kwargs, file=SETTINGS_YAML):
766
- """
767
- Function that runs on a first-time ultralytics package installation to set up global settings and create necessary
768
- directories.
769
- """
770
- SETTINGS.update(kwargs)
771
- yaml_save(file, SETTINGS)
810
+ def reset(self):
811
+ """Resets the settings to default and saves them."""
812
+ self.clear()
813
+ self.update(self.defaults)
814
+ self.save()
772
815
 
773
816
 
774
817
  def deprecation_warn(arg, new_arg, version=None):
@@ -794,7 +837,7 @@ def url2file(url):
794
837
 
795
838
  # Check first-install steps
796
839
  PREFIX = colorstr('Ultralytics: ')
797
- SETTINGS = get_settings()
840
+ SETTINGS = SettingsManager() # initialize settings
798
841
  DATASETS_DIR = Path(SETTINGS['datasets_dir']) # global datasets directory
799
842
  ENVIRONMENT = 'Colab' if is_colab() else 'Kaggle' if is_kaggle() else 'Jupyter' if is_jupyter() else \
800
843
  'Docker' if is_docker() else platform.system()
@@ -5,7 +5,7 @@ import re
5
5
  import matplotlib.image as mpimg
6
6
  import matplotlib.pyplot as plt
7
7
 
8
- from ultralytics.utils import LOGGER, TESTS_RUNNING
8
+ from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
9
9
  from ultralytics.utils.torch_utils import model_info_for_loggers
10
10
 
11
11
  try:
@@ -16,6 +16,7 @@ try:
16
16
 
17
17
  assert hasattr(clearml, '__version__') # verify package is not directory
18
18
  assert not TESTS_RUNNING # do not log pytest
19
+ assert SETTINGS['clearml'] is True # verify integration is enabled
19
20
  except (ImportError, AssertionError):
20
21
  clearml = None
21
22
 
@@ -3,7 +3,7 @@
3
3
  import os
4
4
  from pathlib import Path
5
5
 
6
- from ultralytics.utils import LOGGER, RANK, TESTS_RUNNING, ops
6
+ from ultralytics.utils import LOGGER, RANK, SETTINGS, TESTS_RUNNING, ops
7
7
  from ultralytics.utils.torch_utils import model_info_for_loggers
8
8
 
9
9
  try:
@@ -11,6 +11,7 @@ try:
11
11
 
12
12
  assert not TESTS_RUNNING # do not log pytest
13
13
  assert hasattr(comet_ml, '__version__') # verify package is not directory
14
+ assert SETTINGS['comet'] is True # verify integration is enabled
14
15
  except (ImportError, AssertionError):
15
16
  comet_ml = None
16
17
 
@@ -3,7 +3,7 @@ import os
3
3
 
4
4
  import pkg_resources as pkg
5
5
 
6
- from ultralytics.utils import LOGGER, TESTS_RUNNING
6
+ from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
7
7
  from ultralytics.utils.torch_utils import model_info_for_loggers
8
8
 
9
9
  try:
@@ -12,6 +12,7 @@ try:
12
12
  import dvclive
13
13
 
14
14
  assert not TESTS_RUNNING # do not log pytest
15
+ assert SETTINGS['dvc'] is True # verify integration is enabled
15
16
 
16
17
  ver = version('dvclive')
17
18
  if pkg.parse_version(ver) < pkg.parse_version('2.11.0'):
@@ -4,7 +4,7 @@ import json
4
4
  from time import time
5
5
 
6
6
  from ultralytics.hub.utils import PREFIX, events
7
- from ultralytics.utils import LOGGER
7
+ from ultralytics.utils import LOGGER, SETTINGS
8
8
  from ultralytics.utils.torch_utils import model_info_for_loggers
9
9
 
10
10
 
@@ -84,4 +84,4 @@ callbacks = {
84
84
  'on_train_start': on_train_start,
85
85
  'on_val_start': on_val_start,
86
86
  'on_predict_start': on_predict_start,
87
- 'on_export_start': on_export_start}
87
+ 'on_export_start': on_export_start} if SETTINGS['hub'] is True else {} # verify enabled
@@ -4,13 +4,14 @@ import os
4
4
  import re
5
5
  from pathlib import Path
6
6
 
7
- from ultralytics.utils import LOGGER, TESTS_RUNNING, colorstr
7
+ from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, colorstr
8
8
 
9
9
  try:
10
10
  import mlflow
11
11
 
12
12
  assert not TESTS_RUNNING # do not log pytest
13
13
  assert hasattr(mlflow, '__version__') # verify package is not directory
14
+ assert SETTINGS['mlflow'] is True # verify integration is enabled
14
15
  except (ImportError, AssertionError):
15
16
  mlflow = None
16
17