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,4 +1,4 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
  """
3
3
  Benchmark a YOLO model formats for speed and accuracy.
4
4
 
@@ -21,83 +21,106 @@ TensorFlow Lite | `tflite` | yolov8n.tflite
21
21
  TensorFlow Edge TPU | `edgetpu` | yolov8n_edgetpu.tflite
22
22
  TensorFlow.js | `tfjs` | yolov8n_web_model/
23
23
  PaddlePaddle | `paddle` | yolov8n_paddle_model/
24
+ MNN | `mnn` | yolov8n.mnn
24
25
  NCNN | `ncnn` | yolov8n_ncnn_model/
25
26
  """
26
27
 
27
28
  import glob
29
+ import os
28
30
  import platform
31
+ import re
32
+ import shutil
29
33
  import time
30
34
  from pathlib import Path
31
35
 
32
36
  import numpy as np
33
37
  import torch.cuda
38
+ import yaml
34
39
 
35
40
  from ultralytics import YOLO, YOLOWorld
36
41
  from ultralytics.cfg import TASK2DATA, TASK2METRIC
37
42
  from ultralytics.engine.exporter import export_formats
38
- from ultralytics.utils import ASSETS, LINUX, LOGGER, MACOS, TQDM, WEIGHTS_DIR
43
+ from ultralytics.utils import ARM64, ASSETS, IS_JETSON, IS_RASPBERRYPI, LINUX, LOGGER, MACOS, TQDM, WEIGHTS_DIR
39
44
  from ultralytics.utils.checks import IS_PYTHON_3_12, check_requirements, check_yolo
45
+ from ultralytics.utils.downloads import safe_download
40
46
  from ultralytics.utils.files import file_size
41
- from ultralytics.utils.torch_utils import select_device
47
+ from ultralytics.utils.torch_utils import get_cpu_info, select_device
42
48
 
43
49
 
44
50
  def benchmark(
45
- model=WEIGHTS_DIR / "yolov8n.pt", data=None, imgsz=160, half=False, int8=False, device="cpu", verbose=False
51
+ model=WEIGHTS_DIR / "yolo11n.pt",
52
+ data=None,
53
+ imgsz=160,
54
+ half=False,
55
+ int8=False,
56
+ device="cpu",
57
+ verbose=False,
58
+ eps=1e-3,
46
59
  ):
47
60
  """
48
61
  Benchmark a YOLO model across different formats for speed and accuracy.
49
62
 
50
63
  Args:
51
- model (str | Path | optional): Path to the model file or directory. Default is
52
- Path(SETTINGS['weights_dir']) / 'yolov8n.pt'.
53
- data (str, optional): Dataset to evaluate on, inherited from TASK2DATA if not passed. Default is None.
54
- imgsz (int, optional): Image size for the benchmark. Default is 160.
55
- half (bool, optional): Use half-precision for the model if True. Default is False.
56
- int8 (bool, optional): Use int8-precision for the model if True. Default is False.
57
- device (str, optional): Device to run the benchmark on, either 'cpu' or 'cuda'. Default is 'cpu'.
58
- verbose (bool | float | optional): If True or a float, assert benchmarks pass with given metric.
59
- Default is False.
64
+ model (str | Path): Path to the model file or directory.
65
+ data (str | None): Dataset to evaluate on, inherited from TASK2DATA if not passed.
66
+ imgsz (int): Image size for the benchmark.
67
+ half (bool): Use half-precision for the model if True.
68
+ int8 (bool): Use int8-precision for the model if True.
69
+ device (str): Device to run the benchmark on, either 'cpu' or 'cuda'.
70
+ verbose (bool | float): If True or a float, assert benchmarks pass with given metric.
71
+ eps (float): Epsilon value for divide by zero prevention.
60
72
 
61
73
  Returns:
62
- df (pandas.DataFrame): A pandas DataFrame with benchmark results for each format, including file size,
63
- metric, and inference time.
74
+ (pandas.DataFrame): A pandas DataFrame with benchmark results for each format, including file size, metric,
75
+ and inference time.
64
76
 
65
- Example:
66
- ```python
67
- from ultralytics.utils.benchmarks import benchmark
68
-
69
- benchmark(model='yolov8n.pt', imgsz=640)
70
- ```
77
+ Examples:
78
+ Benchmark a YOLO model with default settings:
79
+ >>> from ultralytics.utils.benchmarks import benchmark
80
+ >>> benchmark(model="yolo11n.pt", imgsz=640)
71
81
  """
72
-
73
- import pandas as pd
82
+ import pandas as pd # scope for faster 'import ultralytics'
74
83
 
75
84
  pd.options.display.max_columns = 10
76
85
  pd.options.display.width = 120
77
86
  device = select_device(device, verbose=False)
78
87
  if isinstance(model, (str, Path)):
79
88
  model = YOLO(model)
89
+ is_end2end = getattr(model.model.model[-1], "end2end", False)
80
90
 
81
91
  y = []
82
92
  t0 = time.time()
83
- for i, (name, format, suffix, cpu, gpu) in export_formats().iterrows(): # index, (name, format, suffix, CPU, GPU)
93
+ for i, (name, format, suffix, cpu, gpu, _) in enumerate(zip(*export_formats().values())):
84
94
  emoji, filename = "❌", None # export defaults
85
95
  try:
86
96
  # Checks
87
- if i == 9: # Edge TPU
88
- assert LINUX, "Edge TPU export only supported on Linux"
89
- elif i == 7: # TF GraphDef
97
+ if i == 7: # TF GraphDef
90
98
  assert model.task != "obb", "TensorFlow GraphDef not supported for OBB task"
99
+ elif i == 9: # Edge TPU
100
+ assert LINUX and not ARM64, "Edge TPU export only supported on non-aarch64 Linux"
91
101
  elif i in {5, 10}: # CoreML and TF.js
92
- assert MACOS or LINUX, "export only supported on macOS and Linux"
93
- if i in {3, 5}: # CoreML and OpenVINO
94
- assert not IS_PYTHON_3_12, "CoreML and OpenVINO not supported on Python 3.12"
95
- if i in {6, 7, 8, 9, 10}: # All TF formats
102
+ assert MACOS or LINUX, "CoreML and TF.js export only supported on macOS and Linux"
103
+ assert not IS_RASPBERRYPI, "CoreML and TF.js export not supported on Raspberry Pi"
104
+ assert not IS_JETSON, "CoreML and TF.js export not supported on NVIDIA Jetson"
105
+ if i in {5}: # CoreML
106
+ assert not IS_PYTHON_3_12, "CoreML not supported on Python 3.12"
107
+ if i in {6, 7, 8}: # TF SavedModel, TF GraphDef, and TFLite
108
+ assert not isinstance(model, YOLOWorld), "YOLOWorldv2 TensorFlow exports not supported by onnx2tf yet"
109
+ if i in {9, 10}: # TF EdgeTPU and TF.js
96
110
  assert not isinstance(model, YOLOWorld), "YOLOWorldv2 TensorFlow exports not supported by onnx2tf yet"
97
- if i in {11}: # Paddle
111
+ if i == 11: # Paddle
98
112
  assert not isinstance(model, YOLOWorld), "YOLOWorldv2 Paddle exports not supported yet"
99
- if i in {12}: # NCNN
113
+ assert not is_end2end, "End-to-end models not supported by PaddlePaddle yet"
114
+ assert LINUX or MACOS, "Windows Paddle exports not supported yet"
115
+ if i == 12: # MNN
116
+ assert not isinstance(model, YOLOWorld), "YOLOWorldv2 MNN exports not supported yet"
117
+ if i == 13: # NCNN
100
118
  assert not isinstance(model, YOLOWorld), "YOLOWorldv2 NCNN exports not supported yet"
119
+ if i == 14: # IMX
120
+ assert not is_end2end
121
+ assert not isinstance(model, YOLOWorld), "YOLOWorldv2 IMX exports not supported"
122
+ assert model.task == "detect", "IMX only supported for detection task"
123
+ assert "C2f" in model.__str__(), "IMX only supported for YOLOv8"
101
124
  if "cpu" in device.type:
102
125
  assert cpu, "inference not supported on CPU"
103
126
  if "cuda" in device.type:
@@ -115,8 +138,10 @@ def benchmark(
115
138
 
116
139
  # Predict
117
140
  assert model.task != "pose" or i != 7, "GraphDef Pose inference is not supported"
118
- assert i not in (9, 10), "inference not supported" # Edge TPU and TF.js are unsupported
141
+ assert i not in {9, 10}, "inference not supported" # Edge TPU and TF.js are unsupported
119
142
  assert i != 5 or platform.system() == "Darwin", "inference only supported on macOS>=10.13" # CoreML
143
+ if i in {13}:
144
+ assert not is_end2end, "End-to-end torch.topk operation is not supported for NCNN prediction yet"
120
145
  exported_model.predict(ASSETS / "bus.jpg", imgsz=imgsz, device=device, half=half)
121
146
 
122
147
  # Validate
@@ -126,16 +151,17 @@ def benchmark(
126
151
  data=data, batch=1, imgsz=imgsz, plots=False, device=device, half=half, int8=int8, verbose=False
127
152
  )
128
153
  metric, speed = results.results_dict[key], results.speed["inference"]
129
- y.append([name, "✅", round(file_size(filename), 1), round(metric, 4), round(speed, 2)])
154
+ fps = round(1000 / (speed + eps), 2) # frames per second
155
+ y.append([name, "✅", round(file_size(filename), 1), round(metric, 4), round(speed, 2), fps])
130
156
  except Exception as e:
131
157
  if verbose:
132
158
  assert type(e) is AssertionError, f"Benchmark failure for {name}: {e}"
133
159
  LOGGER.warning(f"ERROR ❌️ Benchmark failure for {name}: {e}")
134
- y.append([name, emoji, round(file_size(filename), 1), None, None]) # mAP, t_inference
160
+ y.append([name, emoji, round(file_size(filename), 1), None, None, None]) # mAP, t_inference
135
161
 
136
162
  # Print results
137
163
  check_yolo(device=device) # print system info
138
- df = pd.DataFrame(y, columns=["Format", "Status❔", "Size (MB)", key, "Inference time (ms/im)"])
164
+ df = pd.DataFrame(y, columns=["Format", "Status❔", "Size (MB)", key, "Inference time (ms/im)", "FPS"])
139
165
 
140
166
  name = Path(model.ckpt_path).name
141
167
  s = f"\nBenchmarks complete for {name} on {data} at imgsz={imgsz} ({time.time() - t0:.2f}s)\n{df}\n"
@@ -151,6 +177,141 @@ def benchmark(
151
177
  return df
152
178
 
153
179
 
180
+ class RF100Benchmark:
181
+ """Benchmark YOLO model performance across various formats for speed and accuracy."""
182
+
183
+ def __init__(self):
184
+ """Initialize the RF100Benchmark class for benchmarking YOLO model performance across various formats."""
185
+ self.ds_names = []
186
+ self.ds_cfg_list = []
187
+ self.rf = None
188
+ self.val_metrics = ["class", "images", "targets", "precision", "recall", "map50", "map95"]
189
+
190
+ def set_key(self, api_key):
191
+ """
192
+ Set Roboflow API key for processing.
193
+
194
+ Args:
195
+ api_key (str): The API key.
196
+
197
+ Examples:
198
+ Set the Roboflow API key for accessing datasets:
199
+ >>> benchmark = RF100Benchmark()
200
+ >>> benchmark.set_key("your_roboflow_api_key")
201
+ """
202
+ check_requirements("roboflow")
203
+ from roboflow import Roboflow
204
+
205
+ self.rf = Roboflow(api_key=api_key)
206
+
207
+ def parse_dataset(self, ds_link_txt="datasets_links.txt"):
208
+ """
209
+ Parse dataset links and download datasets.
210
+
211
+ Args:
212
+ ds_link_txt (str): Path to the file containing dataset links.
213
+
214
+ Examples:
215
+ >>> benchmark = RF100Benchmark()
216
+ >>> benchmark.set_key("api_key")
217
+ >>> benchmark.parse_dataset("datasets_links.txt")
218
+ """
219
+ (shutil.rmtree("rf-100"), os.mkdir("rf-100")) if os.path.exists("rf-100") else os.mkdir("rf-100")
220
+ os.chdir("rf-100")
221
+ os.mkdir("ultralytics-benchmarks")
222
+ safe_download("https://github.com/ultralytics/assets/releases/download/v0.0.0/datasets_links.txt")
223
+
224
+ with open(ds_link_txt) as file:
225
+ for line in file:
226
+ try:
227
+ _, url, workspace, project, version = re.split("/+", line.strip())
228
+ self.ds_names.append(project)
229
+ proj_version = f"{project}-{version}"
230
+ if not Path(proj_version).exists():
231
+ self.rf.workspace(workspace).project(project).version(version).download("yolov8")
232
+ else:
233
+ print("Dataset already downloaded.")
234
+ self.ds_cfg_list.append(Path.cwd() / proj_version / "data.yaml")
235
+ except Exception:
236
+ continue
237
+
238
+ return self.ds_names, self.ds_cfg_list
239
+
240
+ @staticmethod
241
+ def fix_yaml(path):
242
+ """
243
+ Fixes the train and validation paths in a given YAML file.
244
+
245
+ Args:
246
+ path (str): Path to the YAML file to be fixed.
247
+
248
+ Examples:
249
+ >>> RF100Benchmark.fix_yaml("path/to/data.yaml")
250
+ """
251
+ with open(path) as file:
252
+ yaml_data = yaml.safe_load(file)
253
+ yaml_data["train"] = "train/images"
254
+ yaml_data["val"] = "valid/images"
255
+ with open(path, "w") as file:
256
+ yaml.safe_dump(yaml_data, file)
257
+
258
+ def evaluate(self, yaml_path, val_log_file, eval_log_file, list_ind):
259
+ """
260
+ Evaluate model performance on validation results.
261
+
262
+ Args:
263
+ yaml_path (str): Path to the YAML configuration file.
264
+ val_log_file (str): Path to the validation log file.
265
+ eval_log_file (str): Path to the evaluation log file.
266
+ list_ind (int): Index of the current dataset in the list.
267
+
268
+ Returns:
269
+ (float): The mean average precision (mAP) value for the evaluated model.
270
+
271
+ Examples:
272
+ Evaluate a model on a specific dataset
273
+ >>> benchmark = RF100Benchmark()
274
+ >>> benchmark.evaluate("path/to/data.yaml", "path/to/val_log.txt", "path/to/eval_log.txt", 0)
275
+ """
276
+ skip_symbols = ["🚀", "⚠️", "💡", "❌"]
277
+ with open(yaml_path) as stream:
278
+ class_names = yaml.safe_load(stream)["names"]
279
+ with open(val_log_file, encoding="utf-8") as f:
280
+ lines = f.readlines()
281
+ eval_lines = []
282
+ for line in lines:
283
+ if any(symbol in line for symbol in skip_symbols):
284
+ continue
285
+ entries = line.split(" ")
286
+ entries = list(filter(lambda val: val != "", entries))
287
+ entries = [e.strip("\n") for e in entries]
288
+ eval_lines.extend(
289
+ {
290
+ "class": entries[0],
291
+ "images": entries[1],
292
+ "targets": entries[2],
293
+ "precision": entries[3],
294
+ "recall": entries[4],
295
+ "map50": entries[5],
296
+ "map95": entries[6],
297
+ }
298
+ for e in entries
299
+ if e in class_names or (e == "all" and "(AP)" not in entries and "(AR)" not in entries)
300
+ )
301
+ map_val = 0.0
302
+ if len(eval_lines) > 1:
303
+ print("There's more dicts")
304
+ for lst in eval_lines:
305
+ if lst["class"] == "all":
306
+ map_val = lst["map50"]
307
+ else:
308
+ print("There's only one dict res")
309
+ map_val = [res["map50"] for res in eval_lines][0]
310
+
311
+ with open(eval_log_file, "a") as f:
312
+ f.write(f"{self.ds_names[list_ind]}: {map_val}\n")
313
+
314
+
154
315
  class ProfileModels:
155
316
  """
156
317
  ProfileModels class for profiling different models on ONNX and TensorRT.
@@ -158,21 +319,23 @@ class ProfileModels:
158
319
  This class profiles the performance of different models, returning results such as model speed and FLOPs.
159
320
 
160
321
  Attributes:
161
- paths (list): Paths of the models to profile.
162
- num_timed_runs (int): Number of timed runs for the profiling. Default is 100.
163
- num_warmup_runs (int): Number of warmup runs before profiling. Default is 10.
164
- min_time (float): Minimum number of seconds to profile for. Default is 60.
165
- imgsz (int): Image size used in the models. Default is 640.
322
+ paths (List[str]): Paths of the models to profile.
323
+ num_timed_runs (int): Number of timed runs for the profiling.
324
+ num_warmup_runs (int): Number of warmup runs before profiling.
325
+ min_time (float): Minimum number of seconds to profile for.
326
+ imgsz (int): Image size used in the models.
327
+ half (bool): Flag to indicate whether to use FP16 half-precision for TensorRT profiling.
328
+ trt (bool): Flag to indicate whether to profile using TensorRT.
329
+ device (torch.device): Device used for profiling.
166
330
 
167
331
  Methods:
168
- profile(): Profiles the models and prints the result.
332
+ profile: Profiles the models and prints the result.
169
333
 
170
- Example:
171
- ```python
172
- from ultralytics.utils.benchmarks import ProfileModels
173
-
174
- ProfileModels(['yolov8n.yaml', 'yolov8s.yaml'], imgsz=640).profile()
175
- ```
334
+ Examples:
335
+ Profile models and print results
336
+ >>> from ultralytics.utils.benchmarks import ProfileModels
337
+ >>> profiler = ProfileModels(["yolov8n.yaml", "yolov8s.yaml"], imgsz=640)
338
+ >>> profiler.profile()
176
339
  """
177
340
 
178
341
  def __init__(
@@ -190,14 +353,23 @@ class ProfileModels:
190
353
  Initialize the ProfileModels class for profiling models.
191
354
 
192
355
  Args:
193
- paths (list): List of paths of the models to be profiled.
194
- num_timed_runs (int, optional): Number of timed runs for the profiling. Default is 100.
195
- num_warmup_runs (int, optional): Number of warmup runs before the actual profiling starts. Default is 10.
196
- min_time (float, optional): Minimum time in seconds for profiling a model. Default is 60.
197
- imgsz (int, optional): Size of the image used during profiling. Default is 640.
198
- half (bool, optional): Flag to indicate whether to use half-precision floating point for profiling.
199
- trt (bool, optional): Flag to indicate whether to profile using TensorRT. Default is True.
200
- device (torch.device, optional): Device used for profiling. If None, it is determined automatically.
356
+ paths (List[str]): List of paths of the models to be profiled.
357
+ num_timed_runs (int): Number of timed runs for the profiling.
358
+ num_warmup_runs (int): Number of warmup runs before the actual profiling starts.
359
+ min_time (float): Minimum time in seconds for profiling a model.
360
+ imgsz (int): Size of the image used during profiling.
361
+ half (bool): Flag to indicate whether to use FP16 half-precision for TensorRT profiling.
362
+ trt (bool): Flag to indicate whether to profile using TensorRT.
363
+ device (torch.device | None): Device used for profiling. If None, it is determined automatically.
364
+
365
+ Notes:
366
+ FP16 'half' argument option removed for ONNX as slower on CPU than FP32.
367
+
368
+ Examples:
369
+ Initialize and profile models
370
+ >>> from ultralytics.utils.benchmarks import ProfileModels
371
+ >>> profiler = ProfileModels(["yolov8n.yaml", "yolov8s.yaml"], imgsz=640)
372
+ >>> profiler.profile()
201
373
  """
202
374
  self.paths = paths
203
375
  self.num_timed_runs = num_timed_runs
@@ -209,7 +381,7 @@ class ProfileModels:
209
381
  self.device = device or torch.device(0 if torch.cuda.is_available() else "cpu")
210
382
 
211
383
  def profile(self):
212
- """Logs the benchmarking results of a model, checks metrics against floor and returns the results."""
384
+ """Profiles YOLO models for speed and accuracy across various formats including ONNX and TensorRT."""
213
385
  files = self.get_files()
214
386
 
215
387
  if not files:
@@ -220,16 +392,23 @@ class ProfileModels:
220
392
  output = []
221
393
  for file in files:
222
394
  engine_file = file.with_suffix(".engine")
223
- if file.suffix in (".pt", ".yaml", ".yml"):
395
+ if file.suffix in {".pt", ".yaml", ".yml"}:
224
396
  model = YOLO(str(file))
225
397
  model.fuse() # to report correct params and GFLOPs in model.info()
226
398
  model_info = model.info()
227
399
  if self.trt and self.device.type != "cpu" and not engine_file.is_file():
228
400
  engine_file = model.export(
229
- format="engine", half=self.half, imgsz=self.imgsz, device=self.device, verbose=False
401
+ format="engine",
402
+ half=self.half,
403
+ imgsz=self.imgsz,
404
+ device=self.device,
405
+ verbose=False,
230
406
  )
231
407
  onnx_file = model.export(
232
- format="onnx", half=self.half, imgsz=self.imgsz, simplify=True, device=self.device, verbose=False
408
+ format="onnx",
409
+ imgsz=self.imgsz,
410
+ device=self.device,
411
+ verbose=False,
233
412
  )
234
413
  elif file.suffix == ".onnx":
235
414
  model_info = self.get_onnx_model_info(file)
@@ -261,15 +440,14 @@ class ProfileModels:
261
440
  print(f"Profiling: {sorted(files)}")
262
441
  return [Path(file) for file in sorted(files)]
263
442
 
264
- def get_onnx_model_info(self, onnx_file: str):
265
- """Retrieves the information including number of layers, parameters, gradients and FLOPs for an ONNX model
266
- file.
267
- """
443
+ @staticmethod
444
+ def get_onnx_model_info(onnx_file: str):
445
+ """Extracts metadata from an ONNX model file including parameters, GFLOPs, and input shape."""
268
446
  return 0.0, 0.0, 0.0, 0.0 # return (num_layers, num_params, num_gradients, num_flops)
269
447
 
270
448
  @staticmethod
271
449
  def iterative_sigma_clipping(data, sigma=2, max_iters=3):
272
- """Applies an iterative sigma clipping algorithm to the given data times number of iterations."""
450
+ """Applies iterative sigma clipping to data to remove outliers based on specified sigma and iteration count."""
273
451
  data = np.array(data)
274
452
  for _ in range(max_iters):
275
453
  mean, std = np.mean(data), np.std(data)
@@ -280,13 +458,13 @@ class ProfileModels:
280
458
  return data
281
459
 
282
460
  def profile_tensorrt_model(self, engine_file: str, eps: float = 1e-3):
283
- """Profiles the TensorRT model, measuring average run time and standard deviation among runs."""
461
+ """Profiles YOLO model performance with TensorRT, measuring average run time and standard deviation."""
284
462
  if not self.trt or not Path(engine_file).is_file():
285
463
  return 0.0, 0.0
286
464
 
287
465
  # Model and input
288
466
  model = YOLO(engine_file)
289
- input_data = np.random.rand(self.imgsz, self.imgsz, 3).astype(np.float32) # must be FP32
467
+ input_data = np.zeros((self.imgsz, self.imgsz, 3), dtype=np.uint8) # use uint8 for Classify
290
468
 
291
469
  # Warmup runs
292
470
  elapsed = 0.0
@@ -309,9 +487,7 @@ class ProfileModels:
309
487
  return np.mean(run_times), np.std(run_times)
310
488
 
311
489
  def profile_onnx_model(self, onnx_file: str, eps: float = 1e-3):
312
- """Profiles an ONNX model by executing it multiple times and returns the mean and standard deviation of run
313
- times.
314
- """
490
+ """Profiles an ONNX model, measuring average inference time and standard deviation across multiple runs."""
315
491
  check_requirements("onnxruntime")
316
492
  import onnxruntime as ort
317
493
 
@@ -323,6 +499,8 @@ class ProfileModels:
323
499
 
324
500
  input_tensor = sess.get_inputs()[0]
325
501
  input_type = input_tensor.type
502
+ dynamic = not all(isinstance(dim, int) and dim >= 0 for dim in input_tensor.shape) # dynamic input shape
503
+ input_shape = (1, 3, self.imgsz, self.imgsz) if dynamic else input_tensor.shape
326
504
 
327
505
  # Mapping ONNX datatype to numpy datatype
328
506
  if "float16" in input_type:
@@ -338,7 +516,7 @@ class ProfileModels:
338
516
  else:
339
517
  raise ValueError(f"Unsupported ONNX datatype {input_type}")
340
518
 
341
- input_data = np.random.rand(*input_tensor.shape).astype(input_dtype)
519
+ input_data = np.random.rand(*input_shape).astype(input_dtype)
342
520
  input_name = input_tensor.name
343
521
  output_name = sess.get_outputs()[0].name
344
522
 
@@ -364,16 +542,16 @@ class ProfileModels:
364
542
  return np.mean(run_times), np.std(run_times)
365
543
 
366
544
  def generate_table_row(self, model_name, t_onnx, t_engine, model_info):
367
- """Generates a formatted string for a table row that includes model performance and metric details."""
545
+ """Generates a table row string with model performance metrics including inference times and model details."""
368
546
  layers, params, gradients, flops = model_info
369
547
  return (
370
- f"| {model_name:18s} | {self.imgsz} | - | {t_onnx[0]:.2f} ± {t_onnx[1]:.2f} ms | {t_engine[0]:.2f} ± "
371
- f"{t_engine[1]:.2f} ms | {params / 1e6:.1f} | {flops:.1f} |"
548
+ f"| {model_name:18s} | {self.imgsz} | - | {t_onnx[0]:.1f}±{t_onnx[1]:.1f} ms | {t_engine[0]:.1f}±"
549
+ f"{t_engine[1]:.1f} ms | {params / 1e6:.1f} | {flops:.1f} |"
372
550
  )
373
551
 
374
552
  @staticmethod
375
553
  def generate_results_dict(model_name, t_onnx, t_engine, model_info):
376
- """Generates a dictionary of model details including name, parameters, GFLOPS and speed metrics."""
554
+ """Generates a dictionary of profiling results including model name, parameters, GFLOPs, and speed metrics."""
377
555
  layers, params, gradients, flops = model_info
378
556
  return {
379
557
  "model/name": model_name,
@@ -385,16 +563,19 @@ class ProfileModels:
385
563
 
386
564
  @staticmethod
387
565
  def print_table(table_rows):
388
- """Formats and prints a comparison table for different models with given statistics and performance data."""
566
+ """Prints a formatted table of model profiling results, including speed and accuracy metrics."""
389
567
  gpu = torch.cuda.get_device_name(0) if torch.cuda.is_available() else "GPU"
390
- header = (
391
- f"| Model | size<br><sup>(pixels) | mAP<sup>val<br>50-95 | Speed<br><sup>CPU ONNX<br>(ms) | "
392
- f"Speed<br><sup>{gpu} TensorRT<br>(ms) | params<br><sup>(M) | FLOPs<br><sup>(B) |"
393
- )
394
- separator = (
395
- "|-------------|---------------------|--------------------|------------------------------|"
396
- "-----------------------------------|------------------|-----------------|"
397
- )
568
+ headers = [
569
+ "Model",
570
+ "size<br><sup>(pixels)",
571
+ "mAP<sup>val<br>50-95",
572
+ f"Speed<br><sup>CPU ({get_cpu_info()}) ONNX<br>(ms)",
573
+ f"Speed<br><sup>{gpu} TensorRT<br>(ms)",
574
+ "params<br><sup>(M)",
575
+ "FLOPs<br><sup>(B)",
576
+ ]
577
+ header = "|" + "|".join(f" {h} " for h in headers) + "|"
578
+ separator = "|" + "|".join("-" * (len(h) + 2) for h in headers) + "|"
398
579
 
399
580
  print(f"\n\n{header}")
400
581
  print(separator)
@@ -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
  from .base import add_integration_callbacks, default_callbacks, get_default_callbacks
4
4
 
@@ -1,10 +1,9 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
  """Base callbacks."""
3
3
 
4
4
  from collections import defaultdict
5
5
  from copy import deepcopy
6
6
 
7
-
8
7
  # Trainer callbacks ----------------------------------------------------------------------------------------------------
9
8
 
10
9
 
@@ -193,7 +192,6 @@ def add_integration_callbacks(instance):
193
192
  instance (Trainer, Predictor, Validator, Exporter): An object with a 'callbacks' attribute that is a dictionary
194
193
  of callback lists.
195
194
  """
196
-
197
195
  # Load HUB callbacks
198
196
  from .hub import callbacks as hub_cb
199
197
 
@@ -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
  from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING
4
4
 
@@ -7,8 +7,6 @@ try:
7
7
  assert SETTINGS["clearml"] is True # verify integration is enabled
8
8
  import clearml
9
9
  from clearml import Task
10
- from clearml.binding.frameworks.pytorch_bind import PatchPyTorchModelIO
11
- from clearml.binding.matplotlib_bind import PatchedMatplotlib
12
10
 
13
11
  assert hasattr(clearml, "__version__") # verify package is not directory
14
12
 
@@ -61,15 +59,18 @@ def on_pretrain_routine_start(trainer):
61
59
  """Runs at start of pretraining routine; initializes and connects/ logs task to ClearML."""
62
60
  try:
63
61
  if task := Task.current_task():
64
- # Make sure the automatic pytorch and matplotlib bindings are disabled!
62
+ # WARNING: make sure the automatic pytorch and matplotlib bindings are disabled!
65
63
  # We are logging these plots and model files manually in the integration
64
+ from clearml.binding.frameworks.pytorch_bind import PatchPyTorchModelIO
65
+ from clearml.binding.matplotlib_bind import PatchedMatplotlib
66
+
66
67
  PatchPyTorchModelIO.update_current_task(None)
67
68
  PatchedMatplotlib.update_current_task(None)
68
69
  else:
69
70
  task = Task.init(
70
- project_name=trainer.args.project or "YOLOv8",
71
+ project_name=trainer.args.project or "Ultralytics",
71
72
  task_name=trainer.args.name,
72
- tags=["YOLOv8"],
73
+ tags=["Ultralytics"],
73
74
  output_uri=True,
74
75
  reuse_last_task_id=False,
75
76
  auto_connect_frameworks={"pytorch": False, "matplotlib": False},