dgenerate-ultralytics-headless 8.3.137__py3-none-any.whl → 8.3.224__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 (215) hide show
  1. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/METADATA +41 -34
  2. dgenerate_ultralytics_headless-8.3.224.dist-info/RECORD +285 -0
  3. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/WHEEL +1 -1
  4. tests/__init__.py +7 -6
  5. tests/conftest.py +15 -39
  6. tests/test_cli.py +17 -17
  7. tests/test_cuda.py +17 -8
  8. tests/test_engine.py +36 -10
  9. tests/test_exports.py +98 -37
  10. tests/test_integrations.py +12 -15
  11. tests/test_python.py +126 -82
  12. tests/test_solutions.py +319 -135
  13. ultralytics/__init__.py +27 -9
  14. ultralytics/cfg/__init__.py +83 -87
  15. ultralytics/cfg/datasets/Argoverse.yaml +4 -4
  16. ultralytics/cfg/datasets/DOTAv1.5.yaml +2 -2
  17. ultralytics/cfg/datasets/DOTAv1.yaml +2 -2
  18. ultralytics/cfg/datasets/GlobalWheat2020.yaml +2 -2
  19. ultralytics/cfg/datasets/HomeObjects-3K.yaml +4 -5
  20. ultralytics/cfg/datasets/ImageNet.yaml +3 -3
  21. ultralytics/cfg/datasets/Objects365.yaml +24 -20
  22. ultralytics/cfg/datasets/SKU-110K.yaml +9 -9
  23. ultralytics/cfg/datasets/VOC.yaml +10 -13
  24. ultralytics/cfg/datasets/VisDrone.yaml +43 -33
  25. ultralytics/cfg/datasets/african-wildlife.yaml +5 -5
  26. ultralytics/cfg/datasets/brain-tumor.yaml +4 -5
  27. ultralytics/cfg/datasets/carparts-seg.yaml +5 -5
  28. ultralytics/cfg/datasets/coco-pose.yaml +26 -4
  29. ultralytics/cfg/datasets/coco.yaml +4 -4
  30. ultralytics/cfg/datasets/coco128-seg.yaml +2 -2
  31. ultralytics/cfg/datasets/coco128.yaml +2 -2
  32. ultralytics/cfg/datasets/coco8-grayscale.yaml +103 -0
  33. ultralytics/cfg/datasets/coco8-multispectral.yaml +2 -2
  34. ultralytics/cfg/datasets/coco8-pose.yaml +23 -2
  35. ultralytics/cfg/datasets/coco8-seg.yaml +2 -2
  36. ultralytics/cfg/datasets/coco8.yaml +2 -2
  37. ultralytics/cfg/datasets/construction-ppe.yaml +32 -0
  38. ultralytics/cfg/datasets/crack-seg.yaml +5 -5
  39. ultralytics/cfg/datasets/dog-pose.yaml +32 -4
  40. ultralytics/cfg/datasets/dota8-multispectral.yaml +2 -2
  41. ultralytics/cfg/datasets/dota8.yaml +2 -2
  42. ultralytics/cfg/datasets/hand-keypoints.yaml +29 -4
  43. ultralytics/cfg/datasets/lvis.yaml +9 -9
  44. ultralytics/cfg/datasets/medical-pills.yaml +4 -5
  45. ultralytics/cfg/datasets/open-images-v7.yaml +7 -10
  46. ultralytics/cfg/datasets/package-seg.yaml +5 -5
  47. ultralytics/cfg/datasets/signature.yaml +4 -4
  48. ultralytics/cfg/datasets/tiger-pose.yaml +20 -4
  49. ultralytics/cfg/datasets/xView.yaml +5 -5
  50. ultralytics/cfg/default.yaml +96 -93
  51. ultralytics/cfg/trackers/botsort.yaml +16 -17
  52. ultralytics/cfg/trackers/bytetrack.yaml +9 -11
  53. ultralytics/data/__init__.py +4 -4
  54. ultralytics/data/annotator.py +12 -12
  55. ultralytics/data/augment.py +531 -564
  56. ultralytics/data/base.py +76 -81
  57. ultralytics/data/build.py +206 -42
  58. ultralytics/data/converter.py +179 -78
  59. ultralytics/data/dataset.py +121 -121
  60. ultralytics/data/loaders.py +114 -91
  61. ultralytics/data/split.py +28 -15
  62. ultralytics/data/split_dota.py +67 -48
  63. ultralytics/data/utils.py +110 -89
  64. ultralytics/engine/exporter.py +422 -460
  65. ultralytics/engine/model.py +224 -252
  66. ultralytics/engine/predictor.py +94 -89
  67. ultralytics/engine/results.py +345 -595
  68. ultralytics/engine/trainer.py +231 -134
  69. ultralytics/engine/tuner.py +279 -73
  70. ultralytics/engine/validator.py +53 -46
  71. ultralytics/hub/__init__.py +26 -28
  72. ultralytics/hub/auth.py +30 -16
  73. ultralytics/hub/google/__init__.py +34 -36
  74. ultralytics/hub/session.py +53 -77
  75. ultralytics/hub/utils.py +23 -109
  76. ultralytics/models/__init__.py +1 -1
  77. ultralytics/models/fastsam/__init__.py +1 -1
  78. ultralytics/models/fastsam/model.py +36 -18
  79. ultralytics/models/fastsam/predict.py +33 -44
  80. ultralytics/models/fastsam/utils.py +4 -5
  81. ultralytics/models/fastsam/val.py +12 -14
  82. ultralytics/models/nas/__init__.py +1 -1
  83. ultralytics/models/nas/model.py +16 -20
  84. ultralytics/models/nas/predict.py +12 -14
  85. ultralytics/models/nas/val.py +4 -5
  86. ultralytics/models/rtdetr/__init__.py +1 -1
  87. ultralytics/models/rtdetr/model.py +9 -9
  88. ultralytics/models/rtdetr/predict.py +22 -17
  89. ultralytics/models/rtdetr/train.py +20 -16
  90. ultralytics/models/rtdetr/val.py +79 -59
  91. ultralytics/models/sam/__init__.py +8 -2
  92. ultralytics/models/sam/amg.py +53 -38
  93. ultralytics/models/sam/build.py +29 -31
  94. ultralytics/models/sam/model.py +33 -38
  95. ultralytics/models/sam/modules/blocks.py +159 -182
  96. ultralytics/models/sam/modules/decoders.py +38 -47
  97. ultralytics/models/sam/modules/encoders.py +114 -133
  98. ultralytics/models/sam/modules/memory_attention.py +38 -31
  99. ultralytics/models/sam/modules/sam.py +114 -93
  100. ultralytics/models/sam/modules/tiny_encoder.py +268 -291
  101. ultralytics/models/sam/modules/transformer.py +59 -66
  102. ultralytics/models/sam/modules/utils.py +55 -72
  103. ultralytics/models/sam/predict.py +745 -341
  104. ultralytics/models/utils/loss.py +118 -107
  105. ultralytics/models/utils/ops.py +118 -71
  106. ultralytics/models/yolo/__init__.py +1 -1
  107. ultralytics/models/yolo/classify/predict.py +28 -26
  108. ultralytics/models/yolo/classify/train.py +50 -81
  109. ultralytics/models/yolo/classify/val.py +68 -61
  110. ultralytics/models/yolo/detect/predict.py +12 -15
  111. ultralytics/models/yolo/detect/train.py +56 -46
  112. ultralytics/models/yolo/detect/val.py +279 -223
  113. ultralytics/models/yolo/model.py +167 -86
  114. ultralytics/models/yolo/obb/predict.py +7 -11
  115. ultralytics/models/yolo/obb/train.py +23 -25
  116. ultralytics/models/yolo/obb/val.py +107 -99
  117. ultralytics/models/yolo/pose/__init__.py +1 -1
  118. ultralytics/models/yolo/pose/predict.py +12 -14
  119. ultralytics/models/yolo/pose/train.py +31 -69
  120. ultralytics/models/yolo/pose/val.py +119 -254
  121. ultralytics/models/yolo/segment/predict.py +21 -25
  122. ultralytics/models/yolo/segment/train.py +12 -66
  123. ultralytics/models/yolo/segment/val.py +126 -305
  124. ultralytics/models/yolo/world/train.py +53 -45
  125. ultralytics/models/yolo/world/train_world.py +51 -32
  126. ultralytics/models/yolo/yoloe/__init__.py +7 -7
  127. ultralytics/models/yolo/yoloe/predict.py +30 -37
  128. ultralytics/models/yolo/yoloe/train.py +89 -71
  129. ultralytics/models/yolo/yoloe/train_seg.py +15 -17
  130. ultralytics/models/yolo/yoloe/val.py +56 -41
  131. ultralytics/nn/__init__.py +9 -11
  132. ultralytics/nn/autobackend.py +179 -107
  133. ultralytics/nn/modules/__init__.py +67 -67
  134. ultralytics/nn/modules/activation.py +8 -7
  135. ultralytics/nn/modules/block.py +302 -323
  136. ultralytics/nn/modules/conv.py +61 -104
  137. ultralytics/nn/modules/head.py +488 -186
  138. ultralytics/nn/modules/transformer.py +183 -123
  139. ultralytics/nn/modules/utils.py +15 -20
  140. ultralytics/nn/tasks.py +327 -203
  141. ultralytics/nn/text_model.py +81 -65
  142. ultralytics/py.typed +1 -0
  143. ultralytics/solutions/__init__.py +12 -12
  144. ultralytics/solutions/ai_gym.py +19 -27
  145. ultralytics/solutions/analytics.py +36 -26
  146. ultralytics/solutions/config.py +29 -28
  147. ultralytics/solutions/distance_calculation.py +23 -24
  148. ultralytics/solutions/heatmap.py +17 -19
  149. ultralytics/solutions/instance_segmentation.py +21 -19
  150. ultralytics/solutions/object_blurrer.py +16 -17
  151. ultralytics/solutions/object_counter.py +48 -53
  152. ultralytics/solutions/object_cropper.py +22 -16
  153. ultralytics/solutions/parking_management.py +61 -58
  154. ultralytics/solutions/queue_management.py +19 -19
  155. ultralytics/solutions/region_counter.py +63 -50
  156. ultralytics/solutions/security_alarm.py +22 -25
  157. ultralytics/solutions/similarity_search.py +107 -60
  158. ultralytics/solutions/solutions.py +343 -262
  159. ultralytics/solutions/speed_estimation.py +35 -31
  160. ultralytics/solutions/streamlit_inference.py +104 -40
  161. ultralytics/solutions/templates/similarity-search.html +31 -24
  162. ultralytics/solutions/trackzone.py +24 -24
  163. ultralytics/solutions/vision_eye.py +11 -12
  164. ultralytics/trackers/__init__.py +1 -1
  165. ultralytics/trackers/basetrack.py +18 -27
  166. ultralytics/trackers/bot_sort.py +48 -39
  167. ultralytics/trackers/byte_tracker.py +94 -94
  168. ultralytics/trackers/track.py +7 -16
  169. ultralytics/trackers/utils/gmc.py +37 -69
  170. ultralytics/trackers/utils/kalman_filter.py +68 -76
  171. ultralytics/trackers/utils/matching.py +13 -17
  172. ultralytics/utils/__init__.py +251 -275
  173. ultralytics/utils/autobatch.py +19 -7
  174. ultralytics/utils/autodevice.py +68 -38
  175. ultralytics/utils/benchmarks.py +169 -130
  176. ultralytics/utils/callbacks/base.py +12 -13
  177. ultralytics/utils/callbacks/clearml.py +14 -15
  178. ultralytics/utils/callbacks/comet.py +139 -66
  179. ultralytics/utils/callbacks/dvc.py +19 -27
  180. ultralytics/utils/callbacks/hub.py +8 -6
  181. ultralytics/utils/callbacks/mlflow.py +6 -10
  182. ultralytics/utils/callbacks/neptune.py +11 -19
  183. ultralytics/utils/callbacks/platform.py +73 -0
  184. ultralytics/utils/callbacks/raytune.py +3 -4
  185. ultralytics/utils/callbacks/tensorboard.py +9 -12
  186. ultralytics/utils/callbacks/wb.py +33 -30
  187. ultralytics/utils/checks.py +163 -114
  188. ultralytics/utils/cpu.py +89 -0
  189. ultralytics/utils/dist.py +24 -20
  190. ultralytics/utils/downloads.py +176 -146
  191. ultralytics/utils/errors.py +11 -13
  192. ultralytics/utils/events.py +113 -0
  193. ultralytics/utils/export/__init__.py +7 -0
  194. ultralytics/utils/{export.py → export/engine.py} +81 -63
  195. ultralytics/utils/export/imx.py +294 -0
  196. ultralytics/utils/export/tensorflow.py +217 -0
  197. ultralytics/utils/files.py +33 -36
  198. ultralytics/utils/git.py +137 -0
  199. ultralytics/utils/instance.py +105 -120
  200. ultralytics/utils/logger.py +404 -0
  201. ultralytics/utils/loss.py +99 -61
  202. ultralytics/utils/metrics.py +649 -478
  203. ultralytics/utils/nms.py +337 -0
  204. ultralytics/utils/ops.py +263 -451
  205. ultralytics/utils/patches.py +70 -31
  206. ultralytics/utils/plotting.py +253 -223
  207. ultralytics/utils/tal.py +48 -61
  208. ultralytics/utils/torch_utils.py +244 -251
  209. ultralytics/utils/tqdm.py +438 -0
  210. ultralytics/utils/triton.py +22 -23
  211. ultralytics/utils/tuner.py +11 -10
  212. dgenerate_ultralytics_headless-8.3.137.dist-info/RECORD +0 -272
  213. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/entry_points.txt +0 -0
  214. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/licenses/LICENSE +0 -0
  215. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/top_level.txt +0 -0
@@ -8,9 +8,9 @@ from pathlib import Path
8
8
 
9
9
  import pytest
10
10
 
11
- from tests import MODEL, SOURCE, TMP
11
+ from tests import MODEL, SOURCE
12
12
  from ultralytics import YOLO, download
13
- from ultralytics.utils import DATASETS_DIR, SETTINGS
13
+ from ultralytics.utils import ASSETS_URL, DATASETS_DIR, SETTINGS
14
14
  from ultralytics.utils.checks import check_requirements
15
15
 
16
16
 
@@ -32,7 +32,7 @@ def test_model_ray_tune():
32
32
 
33
33
  @pytest.mark.skipif(not check_requirements("mlflow", install=False), reason="mlflow not installed")
34
34
  def test_mlflow():
35
- """Test training with MLflow tracking enabled (see https://mlflow.org/ for details)."""
35
+ """Test training with MLflow tracking enabled."""
36
36
  SETTINGS["mlflow"] = True
37
37
  YOLO("yolo11n-cls.yaml").train(data="imagenet10", imgsz=32, epochs=3, plots=False, device="cpu")
38
38
  SETTINGS["mlflow"] = False
@@ -71,14 +71,14 @@ def test_mlflow_keep_run_active():
71
71
 
72
72
 
73
73
  @pytest.mark.skipif(not check_requirements("tritonclient", install=False), reason="tritonclient[all] not installed")
74
- def test_triton():
74
+ def test_triton(tmp_path):
75
75
  """Test NVIDIA Triton Server functionalities with YOLO model."""
76
76
  check_requirements("tritonclient[all]")
77
- from tritonclient.http import InferenceServerClient # noqa
77
+ from tritonclient.http import InferenceServerClient
78
78
 
79
79
  # Create variables
80
80
  model_name = "yolo"
81
- triton_repo = TMP / "triton_repo" # Triton repo path
81
+ triton_repo = tmp_path / "triton_repo" # Triton repo path
82
82
  triton_model = triton_repo / model_name # Triton model path
83
83
 
84
84
  # Export model to ONNX
@@ -122,33 +122,30 @@ def test_triton():
122
122
  subprocess.call(f"docker kill {container_id}", shell=True)
123
123
 
124
124
 
125
- @pytest.mark.skipif(not check_requirements("pycocotools", install=False), reason="pycocotools not installed")
126
- def test_pycocotools():
127
- """Validate YOLO model predictions on COCO dataset using pycocotools."""
125
+ @pytest.mark.skipif(not check_requirements("faster-coco-eval", install=False), reason="faster-coco-eval not installed")
126
+ def test_faster_coco_eval():
127
+ """Validate YOLO model predictions on COCO dataset using faster-coco-eval."""
128
128
  from ultralytics.models.yolo.detect import DetectionValidator
129
129
  from ultralytics.models.yolo.pose import PoseValidator
130
130
  from ultralytics.models.yolo.segment import SegmentationValidator
131
131
 
132
- # Download annotations after each dataset downloads first
133
- url = "https://github.com/ultralytics/assets/releases/download/v0.0.0/"
134
-
135
132
  args = {"model": "yolo11n.pt", "data": "coco8.yaml", "save_json": True, "imgsz": 64}
136
133
  validator = DetectionValidator(args=args)
137
134
  validator()
138
135
  validator.is_coco = True
139
- download(f"{url}instances_val2017.json", dir=DATASETS_DIR / "coco8/annotations")
136
+ download(f"{ASSETS_URL}/instances_val2017.json", dir=DATASETS_DIR / "coco8/annotations")
140
137
  _ = validator.eval_json(validator.stats)
141
138
 
142
139
  args = {"model": "yolo11n-seg.pt", "data": "coco8-seg.yaml", "save_json": True, "imgsz": 64}
143
140
  validator = SegmentationValidator(args=args)
144
141
  validator()
145
142
  validator.is_coco = True
146
- download(f"{url}instances_val2017.json", dir=DATASETS_DIR / "coco8-seg/annotations")
143
+ download(f"{ASSETS_URL}/instances_val2017.json", dir=DATASETS_DIR / "coco8-seg/annotations")
147
144
  _ = validator.eval_json(validator.stats)
148
145
 
149
146
  args = {"model": "yolo11n-pose.pt", "data": "coco8-pose.yaml", "save_json": True, "imgsz": 64}
150
147
  validator = PoseValidator(args=args)
151
148
  validator()
152
149
  validator.is_coco = True
153
- download(f"{url}person_keypoints_val2017.json", dir=DATASETS_DIR / "coco8-pose/annotations")
150
+ download(f"{ASSETS_URL}/person_keypoints_val2017.json", dir=DATASETS_DIR / "coco8-pose/annotations")
154
151
  _ = validator.eval_json(validator.stats)
tests/test_python.py CHANGED
@@ -12,15 +12,19 @@ import pytest
12
12
  import torch
13
13
  from PIL import Image
14
14
 
15
- from tests import CFG, MODEL, SOURCE, SOURCES_LIST, TMP
15
+ from tests import CFG, MODEL, MODELS, SOURCE, SOURCES_LIST, TASK_MODEL_DATA
16
16
  from ultralytics import RTDETR, YOLO
17
- from ultralytics.cfg import MODELS, TASK2DATA, TASKS
17
+ from ultralytics.cfg import TASK2DATA, TASKS
18
18
  from ultralytics.data.build import load_inference_source
19
+ from ultralytics.data.utils import check_det_dataset
19
20
  from ultralytics.utils import (
20
21
  ARM64,
21
22
  ASSETS,
23
+ ASSETS_URL,
22
24
  DEFAULT_CFG,
23
25
  DEFAULT_CFG_PATH,
26
+ IS_JETSON,
27
+ IS_RASPBERRYPI,
24
28
  LINUX,
25
29
  LOGGER,
26
30
  ONLINE,
@@ -29,13 +33,10 @@ from ultralytics.utils import (
29
33
  WINDOWS,
30
34
  YAML,
31
35
  checks,
32
- is_dir_writeable,
33
36
  is_github_action_running,
34
37
  )
35
38
  from ultralytics.utils.downloads import download
36
- from ultralytics.utils.torch_utils import TORCH_1_9
37
-
38
- IS_TMP_WRITEABLE = is_dir_writeable(TMP) # WARNING: must be run once tests start as TMP does not exist on tests/init
39
+ from ultralytics.utils.torch_utils import TORCH_1_11, TORCH_1_13
39
40
 
40
41
 
41
42
  def test_model_forward():
@@ -73,10 +74,9 @@ def test_model_profile():
73
74
  _ = model.predict(im, profile=True)
74
75
 
75
76
 
76
- @pytest.mark.skipif(not IS_TMP_WRITEABLE, reason="directory is not writeable")
77
- def test_predict_txt():
77
+ def test_predict_txt(tmp_path):
78
78
  """Test YOLO predictions with file, directory, and pattern sources listed in a text file."""
79
- file = TMP / "sources_multi_row.txt"
79
+ file = tmp_path / "sources_multi_row.txt"
80
80
  with open(file, "w") as f:
81
81
  for src in SOURCES_LIST:
82
82
  f.write(f"{src}\n")
@@ -85,10 +85,9 @@ def test_predict_txt():
85
85
 
86
86
 
87
87
  @pytest.mark.skipif(True, reason="disabled for testing")
88
- @pytest.mark.skipif(not IS_TMP_WRITEABLE, reason="directory is not writeable")
89
- def test_predict_csv_multi_row():
88
+ def test_predict_csv_multi_row(tmp_path):
90
89
  """Test YOLO predictions with sources listed in multiple rows of a CSV file."""
91
- file = TMP / "sources_multi_row.csv"
90
+ file = tmp_path / "sources_multi_row.csv"
92
91
  with open(file, "w", newline="") as f:
93
92
  writer = csv.writer(f)
94
93
  writer.writerow(["source"])
@@ -98,10 +97,9 @@ def test_predict_csv_multi_row():
98
97
 
99
98
 
100
99
  @pytest.mark.skipif(True, reason="disabled for testing")
101
- @pytest.mark.skipif(not IS_TMP_WRITEABLE, reason="directory is not writeable")
102
- def test_predict_csv_single_row():
100
+ def test_predict_csv_single_row(tmp_path):
103
101
  """Test YOLO predictions with sources listed in a single row of a CSV file."""
104
- file = TMP / "sources_single_row.csv"
102
+ file = tmp_path / "sources_single_row.csv"
105
103
  with open(file, "w", newline="") as f:
106
104
  writer = csv.writer(f)
107
105
  writer.writerow(SOURCES_LIST)
@@ -112,21 +110,22 @@ def test_predict_csv_single_row():
112
110
  @pytest.mark.parametrize("model_name", MODELS)
113
111
  def test_predict_img(model_name):
114
112
  """Test YOLO model predictions on various image input types and sources, including online images."""
113
+ channels = 1 if model_name == "yolo11n-grayscale.pt" else 3
115
114
  model = YOLO(WEIGHTS_DIR / model_name)
116
- im = cv2.imread(str(SOURCE)) # uint8 numpy array
115
+ im = cv2.imread(str(SOURCE), flags=cv2.IMREAD_GRAYSCALE if channels == 1 else cv2.IMREAD_COLOR) # uint8 numpy array
117
116
  assert len(model(source=Image.open(SOURCE), save=True, verbose=True, imgsz=32)) == 1 # PIL
118
117
  assert len(model(source=im, save=True, save_txt=True, imgsz=32)) == 1 # ndarray
119
- assert len(model(torch.rand((2, 3, 32, 32)), imgsz=32)) == 2 # batch-size 2 Tensor, FP32 0.0-1.0 RGB order
118
+ assert len(model(torch.rand((2, channels, 32, 32)), imgsz=32)) == 2 # batch-size 2 Tensor, FP32 0.0-1.0 RGB order
120
119
  assert len(model(source=[im, im], save=True, save_txt=True, imgsz=32)) == 2 # batch
121
120
  assert len(list(model(source=[im, im], save=True, stream=True, imgsz=32))) == 2 # stream
122
- assert len(model(torch.zeros(320, 640, 3).numpy().astype(np.uint8), imgsz=32)) == 1 # tensor to numpy
121
+ assert len(model(torch.zeros(320, 640, channels).numpy().astype(np.uint8), imgsz=32)) == 1 # tensor to numpy
123
122
  batch = [
124
123
  str(SOURCE), # filename
125
124
  Path(SOURCE), # Path
126
- "https://github.com/ultralytics/assets/releases/download/v0.0.0/zidane.jpg" if ONLINE else SOURCE, # URI
127
- cv2.imread(str(SOURCE)), # OpenCV
125
+ f"{ASSETS_URL}/zidane.jpg?token=123" if ONLINE else SOURCE, # URI
126
+ im, # OpenCV
128
127
  Image.open(SOURCE), # PIL
129
- np.zeros((320, 640, 3), dtype=np.uint8), # numpy
128
+ np.zeros((320, 640, channels), dtype=np.uint8), # numpy
130
129
  ]
131
130
  assert len(model(batch, imgsz=32, classes=0)) == len(batch) # multiple sources in a batch
132
131
 
@@ -137,25 +136,23 @@ def test_predict_visualize(model):
137
136
  YOLO(WEIGHTS_DIR / model)(SOURCE, imgsz=32, visualize=True)
138
137
 
139
138
 
140
- def test_predict_grey_and_4ch():
141
- """Test YOLO prediction on SOURCE converted to greyscale and 4-channel images with various filenames."""
139
+ def test_predict_gray_and_4ch(tmp_path):
140
+ """Test YOLO prediction on SOURCE converted to grayscale and 4-channel images with various filenames."""
142
141
  im = Image.open(SOURCE)
143
- directory = TMP / "im4"
144
- directory.mkdir(parents=True, exist_ok=True)
145
142
 
146
- source_greyscale = directory / "greyscale.jpg"
147
- source_rgba = directory / "4ch.png"
148
- source_non_utf = directory / "non_UTF_测试文件_tést_image.jpg"
149
- source_spaces = directory / "image with spaces.jpg"
143
+ source_grayscale = tmp_path / "grayscale.jpg"
144
+ source_rgba = tmp_path / "4ch.png"
145
+ source_non_utf = tmp_path / "non_UTF_测试文件_tést_image.jpg"
146
+ source_spaces = tmp_path / "image with spaces.jpg"
150
147
 
151
- im.convert("L").save(source_greyscale) # greyscale
148
+ im.convert("L").save(source_grayscale) # grayscale
152
149
  im.convert("RGBA").save(source_rgba) # 4-ch PNG with alpha
153
150
  im.save(source_non_utf) # non-UTF characters in filename
154
151
  im.save(source_spaces) # spaces in filename
155
152
 
156
153
  # Inference
157
154
  model = YOLO(MODEL)
158
- for f in source_rgba, source_greyscale, source_non_utf, source_spaces:
155
+ for f in source_rgba, source_grayscale, source_non_utf, source_spaces:
159
156
  for source in Image.open(f), cv2.imread(str(f)), f:
160
157
  results = model(source, save=True, verbose=True, imgsz=32)
161
158
  assert len(results) == 1 # verify that an image was run
@@ -176,31 +173,43 @@ def test_youtube():
176
173
 
177
174
 
178
175
  @pytest.mark.skipif(not ONLINE, reason="environment is offline")
179
- @pytest.mark.skipif(not IS_TMP_WRITEABLE, reason="directory is not writeable")
180
- def test_track_stream():
181
- """
182
- Test streaming tracking on a short 10 frame video using ByteTrack tracker and different GMC methods.
176
+ @pytest.mark.parametrize("model", MODELS)
177
+ def test_track_stream(model, tmp_path):
178
+ """Test streaming tracking on a short 10 frame video using ByteTrack tracker and different GMC methods.
183
179
 
184
180
  Note imgsz=160 required for tracking for higher confidence and better matches.
185
181
  """
186
- video_url = "https://github.com/ultralytics/assets/releases/download/v0.0.0/decelera_portrait_min.mov"
187
- model = YOLO(MODEL)
182
+ if model == "yolo11n-cls.pt": # classification model not supported for tracking
183
+ return
184
+ video_url = f"{ASSETS_URL}/decelera_portrait_min.mov"
185
+ model = YOLO(model)
188
186
  model.track(video_url, imgsz=160, tracker="bytetrack.yaml")
189
187
  model.track(video_url, imgsz=160, tracker="botsort.yaml", save_frames=True) # test frame saving also
190
188
 
191
189
  # Test Global Motion Compensation (GMC) methods and ReID
192
190
  for gmc, reidm in zip(["orb", "sift", "ecc"], ["auto", "auto", "yolo11n-cls.pt"]):
193
191
  default_args = YAML.load(ROOT / "cfg/trackers/botsort.yaml")
194
- custom_yaml = TMP / f"botsort-{gmc}.yaml"
192
+ custom_yaml = tmp_path / f"botsort-{gmc}.yaml"
195
193
  YAML.save(custom_yaml, {**default_args, "gmc_method": gmc, "with_reid": True, "model": reidm})
196
194
  model.track(video_url, imgsz=160, tracker=custom_yaml)
197
195
 
198
196
 
199
- def test_val():
197
+ @pytest.mark.parametrize("task,weight,data", TASK_MODEL_DATA)
198
+ def test_val(task: str, weight: str, data: str) -> None:
200
199
  """Test the validation mode of the YOLO model."""
201
- YOLO(MODEL).val(data="coco8.yaml", imgsz=32)
202
-
203
-
200
+ model = YOLO(weight)
201
+ for plots in {True, False}: # Test both cases i.e. plots=True and plots=False
202
+ metrics = model.val(data=data, imgsz=32, plots=plots)
203
+ metrics.to_df()
204
+ metrics.to_csv()
205
+ metrics.to_json()
206
+ # Tests for confusion matrix export
207
+ metrics.confusion_matrix.to_df()
208
+ metrics.confusion_matrix.to_csv()
209
+ metrics.confusion_matrix.to_json()
210
+
211
+
212
+ @pytest.mark.skipif(IS_JETSON or IS_RASPBERRYPI, reason="Edge devices not intended for training")
204
213
  def test_train_scratch():
205
214
  """Test training the YOLO model from scratch using the provided configuration."""
206
215
  model = YOLO(CFG)
@@ -208,6 +217,13 @@ def test_train_scratch():
208
217
  model(SOURCE)
209
218
 
210
219
 
220
+ @pytest.mark.skipif(not ONLINE, reason="environment is offline")
221
+ def test_train_ndjson():
222
+ """Test training the YOLO model using NDJSON format dataset."""
223
+ model = YOLO(WEIGHTS_DIR / "yolo11n.pt")
224
+ model.train(data=f"{ASSETS_URL}/coco8-ndjson.ndjson", epochs=1, imgsz=32)
225
+
226
+
211
227
  @pytest.mark.parametrize("scls", [False, True])
212
228
  def test_train_pretrained(scls):
213
229
  """Test training of the YOLO model starting from a pre-trained checkpoint."""
@@ -222,7 +238,7 @@ def test_all_model_yamls():
222
238
  """Test YOLO model creation for all available YAML configurations in the `cfg/models` directory."""
223
239
  for m in (ROOT / "cfg" / "models").rglob("*.yaml"):
224
240
  if "rtdetr" in m.name:
225
- if TORCH_1_9: # torch<=1.8 issue - TypeError: __init__() got an unexpected keyword argument 'batch_first'
241
+ if TORCH_1_11:
226
242
  _ = RTDETR(m.name)(SOURCE, imgsz=640) # must be 640
227
243
  else:
228
244
  YOLO(m.name)
@@ -246,13 +262,13 @@ def test_predict_callback_and_setup():
246
262
  path, im0s, _ = predictor.batch
247
263
  im0s = im0s if isinstance(im0s, list) else [im0s]
248
264
  bs = [predictor.dataset.bs for _ in range(len(path))]
249
- predictor.results = zip(predictor.results, im0s, bs) # results is List[batch_size]
265
+ predictor.results = zip(predictor.results, im0s, bs) # results is list[batch_size]
250
266
 
251
267
  model = YOLO(MODEL)
252
268
  model.add_callback("on_predict_batch_end", on_predict_batch_end)
253
269
 
254
270
  dataset = load_inference_source(source=SOURCE)
255
- bs = dataset.bs # noqa access predictor properties
271
+ bs = dataset.bs # access predictor properties
256
272
  results = model.predict(dataset, stream=True, imgsz=160) # source already setup
257
273
  for r, im0, bs in results:
258
274
  print("test_callback", im0.shape)
@@ -262,22 +278,21 @@ def test_predict_callback_and_setup():
262
278
 
263
279
 
264
280
  @pytest.mark.parametrize("model", MODELS)
265
- def test_results(model):
281
+ def test_results(model: str, tmp_path):
266
282
  """Test YOLO model results processing and output in various formats."""
267
- results = YOLO(WEIGHTS_DIR / model)([SOURCE, SOURCE], imgsz=160)
283
+ im = f"{ASSETS_URL}/boats.jpg" if model == "yolo11n-obb.pt" else SOURCE
284
+ results = YOLO(WEIGHTS_DIR / model)([im, im], imgsz=160)
268
285
  for r in results:
286
+ assert len(r), f"'{model}' results should not be empty!"
269
287
  r = r.cpu().numpy()
270
288
  print(r, len(r), r.path) # print numpy attributes
271
289
  r = r.to(device="cpu", dtype=torch.float32)
272
- r.save_txt(txt_file=TMP / "runs/tests/label.txt", save_conf=True)
273
- r.save_crop(save_dir=TMP / "runs/tests/crops/")
290
+ r.save_txt(txt_file=tmp_path / "runs/tests/label.txt", save_conf=True)
291
+ r.save_crop(save_dir=tmp_path / "runs/tests/crops/")
274
292
  r.to_df(decimals=3) # Align to_ methods: https://docs.ultralytics.com/modes/predict/#working-with-results
275
293
  r.to_csv()
276
- r.to_xml()
277
- r.to_html()
278
294
  r.to_json(normalize=True)
279
- r.to_sql()
280
- r.plot(pil=True, save=True, filename=TMP / "results_plot_save.jpg")
295
+ r.plot(pil=True, save=True, filename=tmp_path / "results_plot_save.jpg")
281
296
  r.plot(conf=True, boxes=True)
282
297
  print(r, len(r), r.path) # print after methods
283
298
 
@@ -307,7 +322,7 @@ def test_labels_and_crops():
307
322
 
308
323
 
309
324
  @pytest.mark.skipif(not ONLINE, reason="environment is offline")
310
- def test_data_utils():
325
+ def test_data_utils(tmp_path):
311
326
  """Test utility functions in ultralytics/data/utils.py, including dataset stats and auto-splitting."""
312
327
  from ultralytics.data.split import autosplit
313
328
  from ultralytics.data.utils import HUBDatasetStats
@@ -318,27 +333,28 @@ def test_data_utils():
318
333
 
319
334
  for task in TASKS:
320
335
  file = Path(TASK2DATA[task]).with_suffix(".zip") # i.e. coco8.zip
321
- download(f"https://github.com/ultralytics/hub/raw/main/example_datasets/{file}", unzip=False, dir=TMP)
322
- stats = HUBDatasetStats(TMP / file, task=task)
336
+ download(f"https://github.com/ultralytics/hub/raw/main/example_datasets/{file}", unzip=False, dir=tmp_path)
337
+ stats = HUBDatasetStats(tmp_path / file, task=task)
323
338
  stats.get_json(save=True)
324
339
  stats.process_images()
325
340
 
326
- autosplit(TMP / "coco8")
327
- zip_directory(TMP / "coco8/images/val") # zip
341
+ autosplit(tmp_path / "coco8")
342
+ zip_directory(tmp_path / "coco8/images/val") # zip
328
343
 
329
344
 
330
345
  @pytest.mark.skipif(not ONLINE, reason="environment is offline")
331
- def test_data_converter():
346
+ def test_data_converter(tmp_path):
332
347
  """Test dataset conversion functions from COCO to YOLO format and class mappings."""
333
348
  from ultralytics.data.converter import coco80_to_coco91_class, convert_coco
334
349
 
335
- file = "instances_val2017.json"
336
- download(f"https://github.com/ultralytics/assets/releases/download/v0.0.0/{file}", dir=TMP)
337
- convert_coco(labels_dir=TMP, save_dir=TMP / "yolo_labels", use_segments=True, use_keypoints=False, cls91to80=True)
350
+ download(f"{ASSETS_URL}/instances_val2017.json", dir=tmp_path)
351
+ convert_coco(
352
+ labels_dir=tmp_path, save_dir=tmp_path / "yolo_labels", use_segments=True, use_keypoints=False, cls91to80=True
353
+ )
338
354
  coco80_to_coco91_class()
339
355
 
340
356
 
341
- def test_data_annotator():
357
+ def test_data_annotator(tmp_path):
342
358
  """Test automatic annotation of data using detection and segmentation models."""
343
359
  from ultralytics.data.annotator import auto_annotate
344
360
 
@@ -346,13 +362,13 @@ def test_data_annotator():
346
362
  ASSETS,
347
363
  det_model=WEIGHTS_DIR / "yolo11n.pt",
348
364
  sam_model=WEIGHTS_DIR / "mobile_sam.pt",
349
- output_dir=TMP / "auto_annotate_labels",
365
+ output_dir=tmp_path / "auto_annotate_labels",
350
366
  )
351
367
 
352
368
 
353
369
  def test_events():
354
370
  """Test event sending functionality."""
355
- from ultralytics.hub.utils import Events
371
+ from ultralytics.utils.events import Events
356
372
 
357
373
  events = Events()
358
374
  events.enabled = True
@@ -369,24 +385,21 @@ def test_cfg_init():
369
385
  check_dict_alignment({"a": 1}, {"b": 2})
370
386
  copy_default_cfg()
371
387
  (Path.cwd() / DEFAULT_CFG_PATH.name.replace(".yaml", "_copy.yaml")).unlink(missing_ok=False)
372
- [smart_value(x) for x in ["none", "true", "false"]]
388
+ [smart_value(x) for x in {"none", "true", "false"}]
373
389
 
374
390
 
375
391
  def test_utils_init():
376
392
  """Test initialization utilities in the Ultralytics library."""
377
- from ultralytics.utils import get_git_branch, get_git_origin_url, get_ubuntu_version, is_github_action_running
393
+ from ultralytics.utils import get_ubuntu_version, is_github_action_running
378
394
 
379
395
  get_ubuntu_version()
380
396
  is_github_action_running()
381
- get_git_origin_url()
382
- get_git_branch()
383
397
 
384
398
 
385
399
  def test_utils_checks():
386
400
  """Test various utility checks for filenames, git status, requirements, image sizes, and versions."""
387
401
  checks.check_yolov5u_filename("yolov5n.pt")
388
- checks.git_describe(ROOT)
389
- checks.check_requirements() # check requirements.txt
402
+ checks.check_requirements("numpy") # check requirements.txt
390
403
  checks.check_imgsz([600, 600], max_dim=1)
391
404
  checks.check_imshow(warn=True)
392
405
  checks.check_version("ultralytics", "8.0.0")
@@ -443,7 +456,7 @@ def test_utils_ops():
443
456
  torch.allclose(boxes, xyxyxyxy2xywhr(xywhr2xyxyxyxy(boxes)), rtol=1e-3)
444
457
 
445
458
 
446
- def test_utils_files():
459
+ def test_utils_files(tmp_path):
447
460
  """Test file handling utilities including file age, date, and paths with spaces."""
448
461
  from ultralytics.utils.files import file_age, file_date, get_latest_run, spaces_in_path
449
462
 
@@ -451,14 +464,14 @@ def test_utils_files():
451
464
  file_date(SOURCE)
452
465
  get_latest_run(ROOT / "runs")
453
466
 
454
- path = TMP / "path/with spaces"
467
+ path = tmp_path / "path/with spaces"
455
468
  path.mkdir(parents=True, exist_ok=True)
456
469
  with spaces_in_path(path) as new_path:
457
470
  print(new_path)
458
471
 
459
472
 
460
473
  @pytest.mark.slow
461
- def test_utils_patches_torch_save():
474
+ def test_utils_patches_torch_save(tmp_path):
462
475
  """Test torch_save backoff when _torch_save raises RuntimeError."""
463
476
  from unittest.mock import MagicMock, patch
464
477
 
@@ -468,7 +481,7 @@ def test_utils_patches_torch_save():
468
481
 
469
482
  with patch("ultralytics.utils.patches._torch_save", new=mock):
470
483
  with pytest.raises(RuntimeError):
471
- torch_save(torch.zeros(1), TMP / "test.pt")
484
+ torch_save(torch.zeros(1), tmp_path / "test.pt")
472
485
 
473
486
  assert mock.call_count == 4, "torch_save was not attempted the expected number of times"
474
487
 
@@ -614,7 +627,8 @@ def test_yolo_world():
614
627
  )
615
628
 
616
629
 
617
- @pytest.mark.skipif(checks.IS_PYTHON_3_12 or not TORCH_1_9, reason="YOLOE with CLIP is not supported in Python 3.12")
630
+ @pytest.mark.skipif(not TORCH_1_13, reason="YOLOE with CLIP requires torch>=1.13")
631
+ @pytest.mark.skipif(checks.IS_PYTHON_3_12, reason="YOLOE with CLIP is not supported in Python 3.12")
618
632
  @pytest.mark.skipif(
619
633
  checks.IS_PYTHON_3_8 and LINUX and ARM64,
620
634
  reason="YOLOE with CLIP is not supported in Python 3.8 and aarch64 Linux",
@@ -628,16 +642,12 @@ def test_yoloe():
628
642
  model.set_classes(names, model.get_text_pe(names))
629
643
  model(SOURCE, conf=0.01)
630
644
 
631
- import numpy as np
632
-
633
645
  from ultralytics import YOLOE
634
646
  from ultralytics.models.yolo.yoloe import YOLOEVPSegPredictor
635
647
 
636
648
  # visual-prompts
637
649
  visuals = dict(
638
- bboxes=np.array(
639
- [[221.52, 405.8, 344.98, 857.54], [120, 425, 160, 445]],
640
- ),
650
+ bboxes=np.array([[221.52, 405.8, 344.98, 857.54], [120, 425, 160, 445]]),
641
651
  cls=np.array([0, 1]),
642
652
  )
643
653
  model.predict(
@@ -654,7 +664,7 @@ def test_yoloe():
654
664
  model.val(data="coco128-seg.yaml", load_vp=True, imgsz=32)
655
665
 
656
666
  # Train, fine-tune
657
- from ultralytics.models.yolo.yoloe import YOLOEPESegTrainer
667
+ from ultralytics.models.yolo.yoloe import YOLOEPESegTrainer, YOLOESegTrainerFromScratch
658
668
 
659
669
  model = YOLOE("yoloe-11s-seg.pt")
660
670
  model.train(
@@ -664,6 +674,15 @@ def test_yoloe():
664
674
  trainer=YOLOEPESegTrainer,
665
675
  imgsz=32,
666
676
  )
677
+ # Train, from scratch
678
+ model = YOLOE("yoloe-11s-seg.yaml")
679
+ model.train(
680
+ data=dict(train=dict(yolo_data=["coco128-seg.yaml"]), val=dict(yolo_data=["coco128-seg.yaml"])),
681
+ epochs=1,
682
+ close_mosaic=1,
683
+ trainer=YOLOESegTrainerFromScratch,
684
+ imgsz=32,
685
+ )
667
686
 
668
687
  # prompt-free
669
688
  # predict
@@ -692,3 +711,28 @@ def test_multichannel():
692
711
  im = np.zeros((32, 32, 10), dtype=np.uint8)
693
712
  model.predict(source=im, imgsz=32, save_txt=True, save_crop=True, augment=True)
694
713
  model.export(format="onnx")
714
+
715
+
716
+ @pytest.mark.parametrize("task,model,data", TASK_MODEL_DATA)
717
+ def test_grayscale(task: str, model: str, data: str, tmp_path) -> None:
718
+ """Test YOLO model grayscale training, validation, and prediction functionality."""
719
+ if task == "classify": # not support grayscale classification yet
720
+ return
721
+ grayscale_data = tmp_path / f"{Path(data).stem}-grayscale.yaml"
722
+ data = check_det_dataset(data)
723
+ data["channels"] = 1 # add additional channels key for grayscale
724
+ YAML.save(grayscale_data, data)
725
+ # remove npy files in train/val splits if exists, might be created by previous tests
726
+ for split in {"train", "val"}:
727
+ for npy_file in (Path(data["path"]) / data[split]).glob("*.npy"):
728
+ npy_file.unlink()
729
+
730
+ model = YOLO(model)
731
+ model.train(data=grayscale_data, epochs=1, imgsz=32, close_mosaic=1)
732
+ model.val(data=grayscale_data)
733
+ im = np.zeros((32, 32, 1), dtype=np.uint8)
734
+ model.predict(source=im, imgsz=32, save_txt=True, save_crop=True, augment=True)
735
+ export_model = model.export(format="onnx")
736
+
737
+ model = YOLO(export_model, task=task)
738
+ model.predict(source=im, imgsz=32)