ultralytics 8.1.29__py3-none-any.whl → 8.3.62__py3-none-any.whl

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.
Files changed (247) hide show
  1. tests/__init__.py +22 -0
  2. tests/conftest.py +83 -0
  3. tests/test_cli.py +122 -0
  4. tests/test_cuda.py +155 -0
  5. tests/test_engine.py +131 -0
  6. tests/test_exports.py +216 -0
  7. tests/test_integrations.py +150 -0
  8. tests/test_python.py +615 -0
  9. tests/test_solutions.py +94 -0
  10. ultralytics/__init__.py +11 -8
  11. ultralytics/cfg/__init__.py +569 -131
  12. ultralytics/cfg/datasets/Argoverse.yaml +2 -1
  13. ultralytics/cfg/datasets/DOTAv1.5.yaml +3 -2
  14. ultralytics/cfg/datasets/DOTAv1.yaml +3 -2
  15. ultralytics/cfg/datasets/GlobalWheat2020.yaml +3 -2
  16. ultralytics/cfg/datasets/ImageNet.yaml +2 -1
  17. ultralytics/cfg/datasets/Objects365.yaml +5 -4
  18. ultralytics/cfg/datasets/SKU-110K.yaml +2 -1
  19. ultralytics/cfg/datasets/VOC.yaml +3 -2
  20. ultralytics/cfg/datasets/VisDrone.yaml +6 -5
  21. ultralytics/cfg/datasets/african-wildlife.yaml +25 -0
  22. ultralytics/cfg/datasets/brain-tumor.yaml +23 -0
  23. ultralytics/cfg/datasets/carparts-seg.yaml +3 -2
  24. ultralytics/cfg/datasets/coco-pose.yaml +7 -6
  25. ultralytics/cfg/datasets/coco.yaml +3 -2
  26. ultralytics/cfg/datasets/coco128-seg.yaml +4 -3
  27. ultralytics/cfg/datasets/coco128.yaml +4 -3
  28. ultralytics/cfg/datasets/coco8-pose.yaml +3 -2
  29. ultralytics/cfg/datasets/coco8-seg.yaml +3 -2
  30. ultralytics/cfg/datasets/coco8.yaml +3 -2
  31. ultralytics/cfg/datasets/crack-seg.yaml +3 -2
  32. ultralytics/cfg/datasets/dog-pose.yaml +24 -0
  33. ultralytics/cfg/datasets/dota8.yaml +3 -2
  34. ultralytics/cfg/datasets/hand-keypoints.yaml +26 -0
  35. ultralytics/cfg/datasets/lvis.yaml +1236 -0
  36. ultralytics/cfg/datasets/medical-pills.yaml +22 -0
  37. ultralytics/cfg/datasets/open-images-v7.yaml +2 -1
  38. ultralytics/cfg/datasets/package-seg.yaml +5 -4
  39. ultralytics/cfg/datasets/signature.yaml +21 -0
  40. ultralytics/cfg/datasets/tiger-pose.yaml +3 -2
  41. ultralytics/cfg/datasets/xView.yaml +2 -1
  42. ultralytics/cfg/default.yaml +14 -11
  43. ultralytics/cfg/models/11/yolo11-cls-resnet18.yaml +24 -0
  44. ultralytics/cfg/models/11/yolo11-cls.yaml +33 -0
  45. ultralytics/cfg/models/11/yolo11-obb.yaml +50 -0
  46. ultralytics/cfg/models/11/yolo11-pose.yaml +51 -0
  47. ultralytics/cfg/models/11/yolo11-seg.yaml +50 -0
  48. ultralytics/cfg/models/11/yolo11.yaml +50 -0
  49. ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +5 -2
  50. ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +5 -2
  51. ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +5 -2
  52. ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +5 -2
  53. ultralytics/cfg/models/v10/yolov10b.yaml +45 -0
  54. ultralytics/cfg/models/v10/yolov10l.yaml +45 -0
  55. ultralytics/cfg/models/v10/yolov10m.yaml +45 -0
  56. ultralytics/cfg/models/v10/yolov10n.yaml +45 -0
  57. ultralytics/cfg/models/v10/yolov10s.yaml +45 -0
  58. ultralytics/cfg/models/v10/yolov10x.yaml +45 -0
  59. ultralytics/cfg/models/v3/yolov3-spp.yaml +5 -2
  60. ultralytics/cfg/models/v3/yolov3-tiny.yaml +5 -2
  61. ultralytics/cfg/models/v3/yolov3.yaml +5 -2
  62. ultralytics/cfg/models/v5/yolov5-p6.yaml +5 -2
  63. ultralytics/cfg/models/v5/yolov5.yaml +5 -2
  64. ultralytics/cfg/models/v6/yolov6.yaml +5 -2
  65. ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +5 -2
  66. ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +5 -2
  67. ultralytics/cfg/models/v8/yolov8-cls.yaml +5 -2
  68. ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +6 -2
  69. ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +6 -2
  70. ultralytics/cfg/models/v8/yolov8-ghost.yaml +5 -2
  71. ultralytics/cfg/models/v8/yolov8-obb.yaml +5 -2
  72. ultralytics/cfg/models/v8/yolov8-p2.yaml +5 -2
  73. ultralytics/cfg/models/v8/yolov8-p6.yaml +10 -7
  74. ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +5 -2
  75. ultralytics/cfg/models/v8/yolov8-pose.yaml +5 -2
  76. ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +5 -2
  77. ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +5 -2
  78. ultralytics/cfg/models/v8/yolov8-seg.yaml +5 -2
  79. ultralytics/cfg/models/v8/yolov8-world.yaml +5 -2
  80. ultralytics/cfg/models/v8/yolov8-worldv2.yaml +5 -2
  81. ultralytics/cfg/models/v8/yolov8.yaml +5 -2
  82. ultralytics/cfg/models/v9/yolov9c-seg.yaml +41 -0
  83. ultralytics/cfg/models/v9/yolov9c.yaml +30 -25
  84. ultralytics/cfg/models/v9/yolov9e-seg.yaml +64 -0
  85. ultralytics/cfg/models/v9/yolov9e.yaml +46 -42
  86. ultralytics/cfg/models/v9/yolov9m.yaml +41 -0
  87. ultralytics/cfg/models/v9/yolov9s.yaml +41 -0
  88. ultralytics/cfg/models/v9/yolov9t.yaml +41 -0
  89. ultralytics/cfg/solutions/default.yaml +24 -0
  90. ultralytics/cfg/trackers/botsort.yaml +8 -5
  91. ultralytics/cfg/trackers/bytetrack.yaml +8 -5
  92. ultralytics/data/__init__.py +14 -3
  93. ultralytics/data/annotator.py +37 -15
  94. ultralytics/data/augment.py +1783 -289
  95. ultralytics/data/base.py +62 -27
  96. ultralytics/data/build.py +36 -8
  97. ultralytics/data/converter.py +196 -36
  98. ultralytics/data/dataset.py +233 -94
  99. ultralytics/data/loaders.py +199 -96
  100. ultralytics/data/split_dota.py +39 -29
  101. ultralytics/data/utils.py +110 -40
  102. ultralytics/engine/__init__.py +1 -1
  103. ultralytics/engine/exporter.py +569 -242
  104. ultralytics/engine/model.py +604 -252
  105. ultralytics/engine/predictor.py +22 -11
  106. ultralytics/engine/results.py +1228 -218
  107. ultralytics/engine/trainer.py +190 -129
  108. ultralytics/engine/tuner.py +18 -18
  109. ultralytics/engine/validator.py +18 -15
  110. ultralytics/hub/__init__.py +31 -13
  111. ultralytics/hub/auth.py +11 -7
  112. ultralytics/hub/google/__init__.py +159 -0
  113. ultralytics/hub/session.py +128 -94
  114. ultralytics/hub/utils.py +20 -21
  115. ultralytics/models/__init__.py +4 -2
  116. ultralytics/models/fastsam/__init__.py +2 -3
  117. ultralytics/models/fastsam/model.py +26 -4
  118. ultralytics/models/fastsam/predict.py +127 -63
  119. ultralytics/models/fastsam/utils.py +1 -44
  120. ultralytics/models/fastsam/val.py +1 -1
  121. ultralytics/models/nas/__init__.py +1 -1
  122. ultralytics/models/nas/model.py +21 -10
  123. ultralytics/models/nas/predict.py +3 -6
  124. ultralytics/models/nas/val.py +4 -4
  125. ultralytics/models/rtdetr/__init__.py +1 -1
  126. ultralytics/models/rtdetr/model.py +1 -1
  127. ultralytics/models/rtdetr/predict.py +6 -8
  128. ultralytics/models/rtdetr/train.py +6 -2
  129. ultralytics/models/rtdetr/val.py +3 -3
  130. ultralytics/models/sam/__init__.py +3 -3
  131. ultralytics/models/sam/amg.py +29 -23
  132. ultralytics/models/sam/build.py +211 -13
  133. ultralytics/models/sam/model.py +91 -30
  134. ultralytics/models/sam/modules/__init__.py +1 -1
  135. ultralytics/models/sam/modules/blocks.py +1129 -0
  136. ultralytics/models/sam/modules/decoders.py +381 -53
  137. ultralytics/models/sam/modules/encoders.py +515 -324
  138. ultralytics/models/sam/modules/memory_attention.py +237 -0
  139. ultralytics/models/sam/modules/sam.py +969 -21
  140. ultralytics/models/sam/modules/tiny_encoder.py +425 -154
  141. ultralytics/models/sam/modules/transformer.py +159 -60
  142. ultralytics/models/sam/modules/utils.py +293 -0
  143. ultralytics/models/sam/predict.py +1263 -132
  144. ultralytics/models/utils/__init__.py +1 -1
  145. ultralytics/models/utils/loss.py +36 -24
  146. ultralytics/models/utils/ops.py +3 -7
  147. ultralytics/models/yolo/__init__.py +3 -3
  148. ultralytics/models/yolo/classify/__init__.py +1 -1
  149. ultralytics/models/yolo/classify/predict.py +7 -8
  150. ultralytics/models/yolo/classify/train.py +17 -22
  151. ultralytics/models/yolo/classify/val.py +8 -4
  152. ultralytics/models/yolo/detect/__init__.py +1 -1
  153. ultralytics/models/yolo/detect/predict.py +3 -5
  154. ultralytics/models/yolo/detect/train.py +11 -4
  155. ultralytics/models/yolo/detect/val.py +90 -52
  156. ultralytics/models/yolo/model.py +14 -9
  157. ultralytics/models/yolo/obb/__init__.py +1 -1
  158. ultralytics/models/yolo/obb/predict.py +2 -2
  159. ultralytics/models/yolo/obb/train.py +5 -3
  160. ultralytics/models/yolo/obb/val.py +41 -23
  161. ultralytics/models/yolo/pose/__init__.py +1 -1
  162. ultralytics/models/yolo/pose/predict.py +3 -5
  163. ultralytics/models/yolo/pose/train.py +2 -2
  164. ultralytics/models/yolo/pose/val.py +51 -17
  165. ultralytics/models/yolo/segment/__init__.py +1 -1
  166. ultralytics/models/yolo/segment/predict.py +3 -5
  167. ultralytics/models/yolo/segment/train.py +2 -2
  168. ultralytics/models/yolo/segment/val.py +60 -19
  169. ultralytics/models/yolo/world/__init__.py +5 -0
  170. ultralytics/models/yolo/world/train.py +92 -0
  171. ultralytics/models/yolo/world/train_world.py +109 -0
  172. ultralytics/nn/__init__.py +1 -1
  173. ultralytics/nn/autobackend.py +228 -93
  174. ultralytics/nn/modules/__init__.py +39 -14
  175. ultralytics/nn/modules/activation.py +21 -0
  176. ultralytics/nn/modules/block.py +526 -66
  177. ultralytics/nn/modules/conv.py +24 -7
  178. ultralytics/nn/modules/head.py +177 -34
  179. ultralytics/nn/modules/transformer.py +6 -5
  180. ultralytics/nn/modules/utils.py +1 -2
  181. ultralytics/nn/tasks.py +225 -77
  182. ultralytics/solutions/__init__.py +30 -1
  183. ultralytics/solutions/ai_gym.py +96 -143
  184. ultralytics/solutions/analytics.py +247 -0
  185. ultralytics/solutions/distance_calculation.py +78 -135
  186. ultralytics/solutions/heatmap.py +93 -247
  187. ultralytics/solutions/object_counter.py +184 -259
  188. ultralytics/solutions/parking_management.py +246 -0
  189. ultralytics/solutions/queue_management.py +112 -0
  190. ultralytics/solutions/region_counter.py +116 -0
  191. ultralytics/solutions/security_alarm.py +144 -0
  192. ultralytics/solutions/solutions.py +178 -0
  193. ultralytics/solutions/speed_estimation.py +86 -174
  194. ultralytics/solutions/streamlit_inference.py +190 -0
  195. ultralytics/solutions/trackzone.py +68 -0
  196. ultralytics/trackers/__init__.py +1 -1
  197. ultralytics/trackers/basetrack.py +32 -13
  198. ultralytics/trackers/bot_sort.py +61 -28
  199. ultralytics/trackers/byte_tracker.py +83 -51
  200. ultralytics/trackers/track.py +21 -6
  201. ultralytics/trackers/utils/__init__.py +1 -1
  202. ultralytics/trackers/utils/gmc.py +62 -48
  203. ultralytics/trackers/utils/kalman_filter.py +166 -35
  204. ultralytics/trackers/utils/matching.py +40 -21
  205. ultralytics/utils/__init__.py +511 -239
  206. ultralytics/utils/autobatch.py +40 -22
  207. ultralytics/utils/benchmarks.py +266 -85
  208. ultralytics/utils/callbacks/__init__.py +1 -1
  209. ultralytics/utils/callbacks/base.py +1 -3
  210. ultralytics/utils/callbacks/clearml.py +7 -6
  211. ultralytics/utils/callbacks/comet.py +39 -17
  212. ultralytics/utils/callbacks/dvc.py +1 -1
  213. ultralytics/utils/callbacks/hub.py +16 -16
  214. ultralytics/utils/callbacks/mlflow.py +28 -24
  215. ultralytics/utils/callbacks/neptune.py +6 -2
  216. ultralytics/utils/callbacks/raytune.py +3 -4
  217. ultralytics/utils/callbacks/tensorboard.py +18 -18
  218. ultralytics/utils/callbacks/wb.py +27 -20
  219. ultralytics/utils/checks.py +160 -100
  220. ultralytics/utils/dist.py +2 -1
  221. ultralytics/utils/downloads.py +40 -34
  222. ultralytics/utils/errors.py +1 -1
  223. ultralytics/utils/files.py +72 -38
  224. ultralytics/utils/instance.py +41 -19
  225. ultralytics/utils/loss.py +83 -55
  226. ultralytics/utils/metrics.py +61 -56
  227. ultralytics/utils/ops.py +94 -89
  228. ultralytics/utils/patches.py +30 -14
  229. ultralytics/utils/plotting.py +600 -269
  230. ultralytics/utils/tal.py +67 -26
  231. ultralytics/utils/torch_utils.py +302 -102
  232. ultralytics/utils/triton.py +2 -1
  233. ultralytics/utils/tuner.py +21 -12
  234. ultralytics-8.3.62.dist-info/METADATA +370 -0
  235. ultralytics-8.3.62.dist-info/RECORD +241 -0
  236. {ultralytics-8.1.29.dist-info → ultralytics-8.3.62.dist-info}/WHEEL +1 -1
  237. ultralytics/data/explorer/__init__.py +0 -5
  238. ultralytics/data/explorer/explorer.py +0 -472
  239. ultralytics/data/explorer/gui/__init__.py +0 -1
  240. ultralytics/data/explorer/gui/dash.py +0 -268
  241. ultralytics/data/explorer/utils.py +0 -166
  242. ultralytics/models/fastsam/prompt.py +0 -357
  243. ultralytics-8.1.29.dist-info/METADATA +0 -373
  244. ultralytics-8.1.29.dist-info/RECORD +0 -197
  245. {ultralytics-8.1.29.dist-info → ultralytics-8.3.62.dist-info}/LICENSE +0 -0
  246. {ultralytics-8.1.29.dist-info → ultralytics-8.3.62.dist-info}/entry_points.txt +0 -0
  247. {ultralytics-8.1.29.dist-info → ultralytics-8.3.62.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,5 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
- import contextlib
4
3
  import glob
5
4
  import inspect
6
5
  import math
@@ -18,16 +17,24 @@ import cv2
18
17
  import numpy as np
19
18
  import requests
20
19
  import torch
21
- from matplotlib import font_manager
22
20
 
23
21
  from ultralytics.utils import (
24
22
  ASSETS,
25
23
  AUTOINSTALL,
24
+ IS_COLAB,
25
+ IS_GIT_DIR,
26
+ IS_KAGGLE,
27
+ IS_PIP_PACKAGE,
26
28
  LINUX,
27
29
  LOGGER,
30
+ MACOS,
28
31
  ONLINE,
32
+ PYTHON_VERSION,
29
33
  ROOT,
34
+ TORCHVISION_VERSION,
30
35
  USER_CONFIG_DIR,
36
+ WINDOWS,
37
+ Retry,
31
38
  SimpleNamespace,
32
39
  ThreadingLocked,
33
40
  TryExcept,
@@ -35,18 +42,10 @@ from ultralytics.utils import (
35
42
  colorstr,
36
43
  downloads,
37
44
  emojis,
38
- is_colab,
39
- is_docker,
40
45
  is_github_action_running,
41
- is_jupyter,
42
- is_kaggle,
43
- is_online,
44
- is_pip_package,
45
46
  url2file,
46
47
  )
47
48
 
48
- PYTHON_VERSION = platform.python_version()
49
-
50
49
 
51
50
  def parse_requirements(file_path=ROOT.parent / "requirements.txt", package=""):
52
51
  """
@@ -63,10 +62,9 @@ def parse_requirements(file_path=ROOT.parent / "requirements.txt", package=""):
63
62
  ```python
64
63
  from ultralytics.utils.checks import parse_requirements
65
64
 
66
- parse_requirements(package='ultralytics')
65
+ parse_requirements(package="ultralytics")
67
66
  ```
68
67
  """
69
-
70
68
  if package:
71
69
  requires = [x for x in metadata.distribution(package).requires if "extra == " not in x]
72
70
  else:
@@ -77,8 +75,7 @@ def parse_requirements(file_path=ROOT.parent / "requirements.txt", package=""):
77
75
  line = line.strip()
78
76
  if line and not line.startswith("#"):
79
77
  line = line.split("#")[0].strip() # ignore inline comments
80
- match = re.match(r"([a-zA-Z0-9-_]+)\s*([<>!=~]+.*)?", line)
81
- if match:
78
+ if match := re.match(r"([a-zA-Z0-9-_]+)\s*([<>!=~]+.*)?", line):
82
79
  requirements.append(SimpleNamespace(name=match[1], specifier=match[2].strip() if match[2] else ""))
83
80
 
84
81
  return requirements
@@ -142,6 +139,8 @@ def check_imgsz(imgsz, stride=32, min_dim=1, max_dim=2, floor=0):
142
139
  imgsz = [imgsz]
143
140
  elif isinstance(imgsz, (list, tuple)):
144
141
  imgsz = list(imgsz)
142
+ elif isinstance(imgsz, str): # i.e. '640' or '[640,640]'
143
+ imgsz = [int(imgsz)] if imgsz.isnumeric() else eval(imgsz)
145
144
  else:
146
145
  raise TypeError(
147
146
  f"'imgsz={imgsz}' is of invalid type {type(imgsz).__name__}. "
@@ -196,16 +195,16 @@ def check_version(
196
195
  Example:
197
196
  ```python
198
197
  # Check if current version is exactly 22.04
199
- check_version(current='22.04', required='==22.04')
198
+ check_version(current="22.04", required="==22.04")
200
199
 
201
200
  # Check if current version is greater than or equal to 22.04
202
- check_version(current='22.10', required='22.04') # assumes '>=' inequality if none passed
201
+ check_version(current="22.10", required="22.04") # assumes '>=' inequality if none passed
203
202
 
204
203
  # Check if current version is less than or equal to 22.04
205
- check_version(current='22.04', required='<=22.04')
204
+ check_version(current="22.04", required="<=22.04")
206
205
 
207
206
  # Check if current version is between 20.04 (inclusive) and 22.04 (exclusive)
208
- check_version(current='21.10', required='>20.04,<22.04')
207
+ check_version(current="21.10", required=">20.04,<22.04")
209
208
  ```
210
209
  """
211
210
  if not current: # if current is '' or None
@@ -224,18 +223,27 @@ def check_version(
224
223
  if not required: # if required is '' or None
225
224
  return True
226
225
 
226
+ if "sys_platform" in required and ( # i.e. required='<2.4.0,>=1.8.0; sys_platform == "win32"'
227
+ (WINDOWS and "win32" not in required)
228
+ or (LINUX and "linux" not in required)
229
+ or (MACOS and "macos" not in required and "darwin" not in required)
230
+ ):
231
+ return True
232
+
227
233
  op = ""
228
234
  version = ""
229
235
  result = True
230
236
  c = parse_version(current) # '1.2.3' -> (1, 2, 3)
231
237
  for r in required.strip(",").split(","):
232
238
  op, version = re.match(r"([^0-9]*)([\d.]+)", r).groups() # split '>=22.04' -> ('>=', '22.04')
239
+ if not op:
240
+ op = ">=" # assume >= if no op passed
233
241
  v = parse_version(version) # '1.2.3' -> (1, 2, 3)
234
242
  if op == "==" and c != v:
235
243
  result = False
236
244
  elif op == "!=" and c == v:
237
245
  result = False
238
- elif op in (">=", "") and not (c >= v): # if no constraint passed assume '>=required'
246
+ elif op == ">=" and not (c >= v):
239
247
  result = False
240
248
  elif op == "<=" and not (c <= v):
241
249
  result = False
@@ -256,17 +264,19 @@ def check_latest_pypi_version(package_name="ultralytics"):
256
264
  """
257
265
  Returns the latest version of a PyPI package without downloading or installing it.
258
266
 
259
- Parameters:
267
+ Args:
260
268
  package_name (str): The name of the package to find the latest version for.
261
269
 
262
270
  Returns:
263
271
  (str): The latest version of the package.
264
272
  """
265
- with contextlib.suppress(Exception):
273
+ try:
266
274
  requests.packages.urllib3.disable_warnings() # Disable the InsecureRequestWarning
267
275
  response = requests.get(f"https://pypi.org/pypi/{package_name}/json", timeout=3)
268
276
  if response.status_code == 200:
269
277
  return response.json()["info"]["version"]
278
+ except Exception:
279
+ return None
270
280
 
271
281
 
272
282
  def check_pip_update_available():
@@ -276,8 +286,8 @@ def check_pip_update_available():
276
286
  Returns:
277
287
  (bool): True if an update is available, False otherwise.
278
288
  """
279
- if ONLINE and is_pip_package():
280
- with contextlib.suppress(Exception):
289
+ if ONLINE and IS_PIP_PACKAGE:
290
+ try:
281
291
  from ultralytics import __version__
282
292
 
283
293
  latest = check_latest_pypi_version()
@@ -287,6 +297,8 @@ def check_pip_update_available():
287
297
  f"Update with 'pip install -U ultralytics'"
288
298
  )
289
299
  return True
300
+ except Exception:
301
+ pass
290
302
  return False
291
303
 
292
304
 
@@ -301,9 +313,10 @@ def check_font(font="Arial.ttf"):
301
313
  Returns:
302
314
  file (Path): Resolved font file path.
303
315
  """
304
- name = Path(font).name
316
+ from matplotlib import font_manager
305
317
 
306
318
  # Check USER_CONFIG_DIR
319
+ name = Path(font).name
307
320
  file = USER_CONFIG_DIR / name
308
321
  if file.exists():
309
322
  return file
@@ -314,23 +327,25 @@ def check_font(font="Arial.ttf"):
314
327
  return matches[0]
315
328
 
316
329
  # Download to USER_CONFIG_DIR if missing
317
- url = f"https://ultralytics.com/assets/{name}"
318
- if downloads.is_url(url):
330
+ url = f"https://github.com/ultralytics/assets/releases/download/v0.0.0/{name}"
331
+ if downloads.is_url(url, check=True):
319
332
  downloads.safe_download(url=url, file=file)
320
333
  return file
321
334
 
322
335
 
323
- def check_python(minimum: str = "3.8.0") -> bool:
336
+ def check_python(minimum: str = "3.8.0", hard: bool = True, verbose: bool = False) -> bool:
324
337
  """
325
338
  Check current python version against the required minimum version.
326
339
 
327
340
  Args:
328
341
  minimum (str): Required minimum version of python.
342
+ hard (bool, optional): If True, raise an AssertionError if the requirement is not met.
343
+ verbose (bool, optional): If True, print warning message if requirement is not met.
329
344
 
330
345
  Returns:
331
346
  (bool): Whether the installed Python version meets the minimum constraints.
332
347
  """
333
- return check_version(PYTHON_VERSION, minimum, name="Python ", hard=True)
348
+ return check_version(PYTHON_VERSION, minimum, name="Python", hard=hard, verbose=verbose)
334
349
 
335
350
 
336
351
  @TryExcept()
@@ -350,19 +365,16 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
350
365
  from ultralytics.utils.checks import check_requirements
351
366
 
352
367
  # Check a requirements.txt file
353
- check_requirements('path/to/requirements.txt')
368
+ check_requirements("path/to/requirements.txt")
354
369
 
355
370
  # Check a single package
356
- check_requirements('ultralytics>=8.0.0')
371
+ check_requirements("ultralytics>=8.0.0")
357
372
 
358
373
  # Check multiple packages
359
- check_requirements(['numpy', 'ultralytics>=8.0.0'])
374
+ check_requirements(["numpy", "ultralytics>=8.0.0"])
360
375
  ```
361
376
  """
362
-
363
377
  prefix = colorstr("red", "bold", "requirements:")
364
- check_python() # check python version
365
- check_torchvision() # check torch-torchvision compatibility
366
378
  if isinstance(requirements, Path): # requirements.txt file
367
379
  file = requirements.resolve()
368
380
  assert file.exists(), f"{prefix} {file} not found, check failed."
@@ -380,6 +392,11 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
380
392
  except (AssertionError, metadata.PackageNotFoundError):
381
393
  pkgs.append(r)
382
394
 
395
+ @Retry(times=2, delay=1)
396
+ def attempt_install(packages, commands):
397
+ """Attempt pip install command with retries on failure."""
398
+ return subprocess.check_output(f"pip install --no-cache-dir {packages} {commands}", shell=True).decode()
399
+
383
400
  s = " ".join(f'"{x}"' for x in pkgs) # console string
384
401
  if s:
385
402
  if install and AUTOINSTALL: # check environment variable
@@ -387,8 +404,8 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
387
404
  LOGGER.info(f"{prefix} Ultralytics requirement{'s' * (n > 1)} {pkgs} not found, attempting AutoUpdate...")
388
405
  try:
389
406
  t = time.time()
390
- assert is_online(), "AutoUpdate skipped (offline)"
391
- LOGGER.info(subprocess.check_output(f"pip install --no-cache {s} {cmds}", shell=True).decode())
407
+ assert ONLINE, "AutoUpdate skipped (offline)"
408
+ LOGGER.info(attempt_install(s, cmds))
392
409
  dt = time.time() - t
393
410
  LOGGER.info(
394
411
  f"{prefix} AutoUpdate success ✅ {dt:.1f}s, installed {n} package{'s' * (n > 1)}: {pkgs}\n"
@@ -414,18 +431,23 @@ def check_torchvision():
414
431
  The compatibility table is a dictionary where the keys are PyTorch versions and the values are lists of compatible
415
432
  Torchvision versions.
416
433
  """
417
-
418
- import torchvision
419
-
420
434
  # Compatibility table
421
- compatibility_table = {"2.0": ["0.15"], "1.13": ["0.14"], "1.12": ["0.13"]}
435
+ compatibility_table = {
436
+ "2.5": ["0.20"],
437
+ "2.4": ["0.19"],
438
+ "2.3": ["0.18"],
439
+ "2.2": ["0.17"],
440
+ "2.1": ["0.16"],
441
+ "2.0": ["0.15"],
442
+ "1.13": ["0.14"],
443
+ "1.12": ["0.13"],
444
+ }
422
445
 
423
446
  # Extract only the major and minor versions
424
447
  v_torch = ".".join(torch.__version__.split("+")[0].split(".")[:2])
425
- v_torchvision = ".".join(torchvision.__version__.split("+")[0].split(".")[:2])
426
-
427
448
  if v_torch in compatibility_table:
428
449
  compatible_versions = compatibility_table[v_torch]
450
+ v_torchvision = ".".join(TORCHVISION_VERSION.split("+")[0].split(".")[:2])
429
451
  if all(v_torchvision != v for v in compatible_versions):
430
452
  print(
431
453
  f"WARNING ⚠️ torchvision=={v_torchvision} is incompatible with torch=={v_torch}.\n"
@@ -435,7 +457,7 @@ def check_torchvision():
435
457
  )
436
458
 
437
459
 
438
- def check_suffix(file="yolov8n.pt", suffix=".pt", msg=""):
460
+ def check_suffix(file="yolo11n.pt", suffix=".pt", msg=""):
439
461
  """Check file(s) for acceptable suffix."""
440
462
  if file and suffix:
441
463
  if isinstance(suffix, str):
@@ -473,7 +495,7 @@ def check_model_file_from_stem(model="yolov8n"):
473
495
  return model
474
496
 
475
497
 
476
- def check_file(file, suffix="", download=True, hard=True):
498
+ def check_file(file, suffix="", download=True, download_dir=".", hard=True):
477
499
  """Search/download file (if necessary) and return path."""
478
500
  check_suffix(file, suffix) # optional
479
501
  file = str(file).strip() # convert to string and strip spaces
@@ -486,12 +508,12 @@ def check_file(file, suffix="", download=True, hard=True):
486
508
  return file
487
509
  elif download and file.lower().startswith(("https://", "http://", "rtsp://", "rtmp://", "tcp://")): # download
488
510
  url = file # warning: Pathlib turns :// -> :/
489
- file = url2file(file) # '%2F' to '/', split https://url.com/file.txt?auth
490
- if Path(file).exists():
511
+ file = Path(download_dir) / url2file(file) # '%2F' to '/', split https://url.com/file.txt?auth
512
+ if file.exists():
491
513
  LOGGER.info(f"Found {clean_url(url)} locally at {file}") # file already exists
492
514
  else:
493
515
  downloads.safe_download(url=url, file=file, unzip=False)
494
- return file
516
+ return str(file)
495
517
  else: # search
496
518
  files = glob.glob(str(ROOT / "**" / file), recursive=True) or glob.glob(str(ROOT.parent / file)) # find file
497
519
  if not files and hard:
@@ -520,14 +542,15 @@ def check_is_path_safe(basedir, path):
520
542
  base_dir_resolved = Path(basedir).resolve()
521
543
  path_resolved = Path(path).resolve()
522
544
 
523
- return path_resolved.is_file() and path_resolved.parts[: len(base_dir_resolved.parts)] == base_dir_resolved.parts
545
+ return path_resolved.exists() and path_resolved.parts[: len(base_dir_resolved.parts)] == base_dir_resolved.parts
524
546
 
525
547
 
526
548
  def check_imshow(warn=False):
527
549
  """Check if environment supports image displays."""
528
550
  try:
529
551
  if LINUX:
530
- assert "DISPLAY" in os.environ and not is_docker() and not is_colab() and not is_kaggle()
552
+ assert not IS_COLAB and not IS_KAGGLE
553
+ assert "DISPLAY" in os.environ, "The DISPLAY environment variable isn't set."
531
554
  cv2.imshow("test", np.zeros((8, 8, 3), dtype=np.uint8)) # show a small 8-pixel image
532
555
  cv2.waitKey(1)
533
556
  cv2.destroyAllWindows()
@@ -545,11 +568,8 @@ def check_yolo(verbose=True, device=""):
545
568
 
546
569
  from ultralytics.utils.torch_utils import select_device
547
570
 
548
- if is_jupyter():
549
- if check_requirements("wandb", install=False):
550
- os.system("pip uninstall -y wandb") # uninstall wandb: unwanted account creation prompt with infinite hang
551
- if is_colab():
552
- shutil.rmtree("sample_data", ignore_errors=True) # remove colab /sample_data directory
571
+ if IS_COLAB:
572
+ shutil.rmtree("sample_data", ignore_errors=True) # remove colab /sample_data directory
553
573
 
554
574
  if verbose:
555
575
  # System info
@@ -557,10 +577,12 @@ def check_yolo(verbose=True, device=""):
557
577
  ram = psutil.virtual_memory().total
558
578
  total, used, free = shutil.disk_usage("/")
559
579
  s = f"({os.cpu_count()} CPUs, {ram / gib:.1f} GB RAM, {(total - free) / gib:.1f}/{total / gib:.1f} GB disk)"
560
- with contextlib.suppress(Exception): # clear display if ipython is installed
580
+ try:
561
581
  from IPython import display
562
582
 
563
- display.clear_output()
583
+ display.clear_output() # clear display if notebook
584
+ except ImportError:
585
+ pass
564
586
  else:
565
587
  s = ""
566
588
 
@@ -570,92 +592,126 @@ def check_yolo(verbose=True, device=""):
570
592
 
571
593
  def collect_system_info():
572
594
  """Collect and print relevant system information including OS, Python, RAM, CPU, and CUDA."""
573
-
574
595
  import psutil
575
596
 
576
- from ultralytics.utils import ENVIRONMENT, is_git_dir
577
- from ultralytics.utils.torch_utils import get_cpu_info
597
+ from ultralytics.utils import ENVIRONMENT # scope to avoid circular import
598
+ from ultralytics.utils.torch_utils import get_cpu_info, get_gpu_info
578
599
 
579
- ram_info = psutil.virtual_memory().total / (1024**3) # Convert bytes to GB
600
+ gib = 1 << 30 # bytes per GiB
601
+ cuda = torch and torch.cuda.is_available()
580
602
  check_yolo()
581
- LOGGER.info(
582
- f"\n{'OS':<20}{platform.platform()}\n"
583
- f"{'Environment':<20}{ENVIRONMENT}\n"
584
- f"{'Python':<20}{PYTHON_VERSION}\n"
585
- f"{'Install':<20}{'git' if is_git_dir() else 'pip' if is_pip_package() else 'other'}\n"
586
- f"{'RAM':<20}{ram_info:.2f} GB\n"
587
- f"{'CPU':<20}{get_cpu_info()}\n"
588
- f"{'CUDA':<20}{torch.version.cuda if torch and torch.cuda.is_available() else None}\n"
589
- )
590
-
603
+ total, used, free = shutil.disk_usage("/")
604
+
605
+ info_dict = {
606
+ "OS": platform.platform(),
607
+ "Environment": ENVIRONMENT,
608
+ "Python": PYTHON_VERSION,
609
+ "Install": "git" if IS_GIT_DIR else "pip" if IS_PIP_PACKAGE else "other",
610
+ "RAM": f"{psutil.virtual_memory().total / gib:.2f} GB",
611
+ "Disk": f"{(total - free) / gib:.1f}/{total / gib:.1f} GB",
612
+ "CPU": get_cpu_info(),
613
+ "CPU count": os.cpu_count(),
614
+ "GPU": get_gpu_info(index=0) if cuda else None,
615
+ "GPU count": torch.cuda.device_count() if cuda else None,
616
+ "CUDA": torch.version.cuda if cuda else None,
617
+ }
618
+ LOGGER.info("\n" + "\n".join(f"{k:<20}{v}" for k, v in info_dict.items()) + "\n")
619
+
620
+ package_info = {}
591
621
  for r in parse_requirements(package="ultralytics"):
592
622
  try:
593
623
  current = metadata.version(r.name)
594
- is_met = "✅ " if check_version(current, str(r.specifier), hard=True) else "❌ "
624
+ is_met = "✅ " if check_version(current, str(r.specifier), name=r.name, hard=True) else "❌ "
595
625
  except metadata.PackageNotFoundError:
596
626
  current = "(not installed)"
597
627
  is_met = "❌ "
598
- LOGGER.info(f"{r.name:<20}{is_met}{current}{r.specifier}")
628
+ package_info[r.name] = f"{is_met}{current}{r.specifier}"
629
+ LOGGER.info(f"{r.name:<20}{package_info[r.name]}")
630
+
631
+ info_dict["Package Info"] = package_info
599
632
 
600
633
  if is_github_action_running():
601
- LOGGER.info(
602
- f"\nRUNNER_OS: {os.getenv('RUNNER_OS')}\n"
603
- f"GITHUB_EVENT_NAME: {os.getenv('GITHUB_EVENT_NAME')}\n"
604
- f"GITHUB_WORKFLOW: {os.getenv('GITHUB_WORKFLOW')}\n"
605
- f"GITHUB_ACTOR: {os.getenv('GITHUB_ACTOR')}\n"
606
- f"GITHUB_REPOSITORY: {os.getenv('GITHUB_REPOSITORY')}\n"
607
- f"GITHUB_REPOSITORY_OWNER: {os.getenv('GITHUB_REPOSITORY_OWNER')}\n"
608
- )
634
+ github_info = {
635
+ "RUNNER_OS": os.getenv("RUNNER_OS"),
636
+ "GITHUB_EVENT_NAME": os.getenv("GITHUB_EVENT_NAME"),
637
+ "GITHUB_WORKFLOW": os.getenv("GITHUB_WORKFLOW"),
638
+ "GITHUB_ACTOR": os.getenv("GITHUB_ACTOR"),
639
+ "GITHUB_REPOSITORY": os.getenv("GITHUB_REPOSITORY"),
640
+ "GITHUB_REPOSITORY_OWNER": os.getenv("GITHUB_REPOSITORY_OWNER"),
641
+ }
642
+ LOGGER.info("\n" + "\n".join(f"{k}: {v}" for k, v in github_info.items()))
643
+ info_dict["GitHub Info"] = github_info
644
+
645
+ return info_dict
609
646
 
610
647
 
611
648
  def check_amp(model):
612
649
  """
613
- This function checks the PyTorch Automatic Mixed Precision (AMP) functionality of a YOLOv8 model. If the checks
614
- fail, it means there are anomalies with AMP on the system that may cause NaN losses or zero-mAP results, so AMP will
615
- be disabled during training.
650
+ Checks the PyTorch Automatic Mixed Precision (AMP) functionality of a YOLO11 model. If the checks fail, it means
651
+ there are anomalies with AMP on the system that may cause NaN losses or zero-mAP results, so AMP will be disabled
652
+ during training.
616
653
 
617
654
  Args:
618
- model (nn.Module): A YOLOv8 model instance.
655
+ model (nn.Module): A YOLO11 model instance.
619
656
 
620
657
  Example:
621
658
  ```python
622
659
  from ultralytics import YOLO
623
660
  from ultralytics.utils.checks import check_amp
624
661
 
625
- model = YOLO('yolov8n.pt').model.cuda()
662
+ model = YOLO("yolo11n.pt").model.cuda()
626
663
  check_amp(model)
627
664
  ```
628
665
 
629
666
  Returns:
630
- (bool): Returns True if the AMP functionality works correctly with YOLOv8 model, else False.
667
+ (bool): Returns True if the AMP functionality works correctly with YOLO11 model, else False.
631
668
  """
669
+ from ultralytics.utils.torch_utils import autocast
670
+
632
671
  device = next(model.parameters()).device # get model device
633
- if device.type in ("cpu", "mps"):
672
+ prefix = colorstr("AMP: ")
673
+ if device.type in {"cpu", "mps"}:
634
674
  return False # AMP only used on CUDA devices
675
+ else:
676
+ # GPUs that have issues with AMP
677
+ pattern = re.compile(
678
+ r"(nvidia|geforce|quadro|tesla).*?(1660|1650|1630|t400|t550|t600|t1000|t1200|t2000|k40m)", re.IGNORECASE
679
+ )
680
+
681
+ gpu = torch.cuda.get_device_name(device)
682
+ if bool(pattern.search(gpu)):
683
+ LOGGER.warning(
684
+ f"{prefix}checks failed ❌. AMP training on {gpu} GPU may cause "
685
+ f"NaN losses or zero-mAP results, so AMP will be disabled during training."
686
+ )
687
+ return False
635
688
 
636
689
  def amp_allclose(m, im):
637
690
  """All close FP32 vs AMP results."""
638
- a = m(im, device=device, verbose=False)[0].boxes.data # FP32 inference
639
- with torch.cuda.amp.autocast(True):
640
- b = m(im, device=device, verbose=False)[0].boxes.data # AMP inference
691
+ batch = [im] * 8
692
+ imgsz = max(256, int(model.stride.max() * 4)) # max stride P5-32 and P6-64
693
+ a = m(batch, imgsz=imgsz, device=device, verbose=False)[0].boxes.data # FP32 inference
694
+ with autocast(enabled=True):
695
+ b = m(batch, imgsz=imgsz, device=device, verbose=False)[0].boxes.data # AMP inference
641
696
  del m
642
697
  return a.shape == b.shape and torch.allclose(a, b.float(), atol=0.5) # close to 0.5 absolute tolerance
643
698
 
644
699
  im = ASSETS / "bus.jpg" # image to check
645
- prefix = colorstr("AMP: ")
646
- LOGGER.info(f"{prefix}running Automatic Mixed Precision (AMP) checks with YOLOv8n...")
700
+ LOGGER.info(f"{prefix}running Automatic Mixed Precision (AMP) checks...")
647
701
  warning_msg = "Setting 'amp=True'. If you experience zero-mAP or NaN losses you can disable AMP with amp=False."
648
702
  try:
649
703
  from ultralytics import YOLO
650
704
 
651
- assert amp_allclose(YOLO("yolov8n.pt"), im)
705
+ assert amp_allclose(YOLO("yolo11n.pt"), im)
652
706
  LOGGER.info(f"{prefix}checks passed ✅")
653
707
  except ConnectionError:
654
- LOGGER.warning(f"{prefix}checks skipped ⚠️, offline and unable to download YOLOv8n. {warning_msg}")
708
+ LOGGER.warning(
709
+ f"{prefix}checks skipped ⚠️. Offline and unable to download YOLO11n for AMP checks. {warning_msg}"
710
+ )
655
711
  except (AttributeError, ModuleNotFoundError):
656
712
  LOGGER.warning(
657
713
  f"{prefix}checks skipped ⚠️. "
658
- f"Unable to load YOLOv8n due to possible Ultralytics package modifications. {warning_msg}"
714
+ f"Unable to load YOLO11n for AMP checks due to possible Ultralytics package modifications. {warning_msg}"
659
715
  )
660
716
  except AssertionError:
661
717
  LOGGER.warning(
@@ -668,9 +724,10 @@ def check_amp(model):
668
724
 
669
725
  def git_describe(path=ROOT): # path must be a directory
670
726
  """Return human-readable git description, i.e. v5.0-5-g3e25f1e https://git-scm.com/docs/git-describe."""
671
- with contextlib.suppress(Exception):
727
+ try:
672
728
  return subprocess.check_output(f"git -C {path} describe --tags --long --always", shell=True).decode()[:-1]
673
- return ""
729
+ except Exception:
730
+ return ""
674
731
 
675
732
 
676
733
  def print_args(args: Optional[dict] = None, show_file=True, show_func=False):
@@ -725,5 +782,8 @@ def cuda_is_available() -> bool:
725
782
  return cuda_device_count() > 0
726
783
 
727
784
 
728
- # Define constants
729
- IS_PYTHON_3_12 = check_version(PYTHON_VERSION, "==3.12", name="Python ", hard=False)
785
+ # Run checks and define constants
786
+ check_python("3.8", hard=False, verbose=True) # check python version
787
+ check_torchvision() # check torch-torchvision compatibility
788
+ IS_PYTHON_MINIMUM_3_10 = check_python("3.10", hard=False)
789
+ IS_PYTHON_3_12 = PYTHON_VERSION.startswith("3.12")
ultralytics/utils/dist.py CHANGED
@@ -1,4 +1,4 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
3
  import os
4
4
  import shutil
@@ -37,6 +37,7 @@ if __name__ == "__main__":
37
37
  cfg = DEFAULT_CFG_DICT.copy()
38
38
  cfg.update(save_dir='') # handle the extra key 'save_dir'
39
39
  trainer = {name}(cfg=cfg, overrides=overrides)
40
+ trainer.args.model = "{getattr(trainer.hub_session, "model_url", trainer.args.model)}"
40
41
  results = trainer.train()
41
42
  """
42
43
  (USER_CONFIG_DIR / "DDP").mkdir(exist_ok=True)