dgenerate-ultralytics-headless 8.3.196__py3-none-any.whl → 8.3.248__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.
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/METADATA +33 -34
- dgenerate_ultralytics_headless-8.3.248.dist-info/RECORD +298 -0
- tests/__init__.py +5 -7
- tests/conftest.py +8 -15
- tests/test_cli.py +8 -10
- tests/test_cuda.py +9 -10
- tests/test_engine.py +29 -2
- tests/test_exports.py +69 -21
- tests/test_integrations.py +8 -11
- tests/test_python.py +109 -71
- tests/test_solutions.py +170 -159
- ultralytics/__init__.py +27 -9
- ultralytics/cfg/__init__.py +57 -64
- ultralytics/cfg/datasets/Argoverse.yaml +7 -6
- ultralytics/cfg/datasets/DOTAv1.5.yaml +1 -1
- ultralytics/cfg/datasets/DOTAv1.yaml +1 -1
- ultralytics/cfg/datasets/ImageNet.yaml +1 -1
- ultralytics/cfg/datasets/Objects365.yaml +19 -15
- ultralytics/cfg/datasets/SKU-110K.yaml +1 -1
- ultralytics/cfg/datasets/VOC.yaml +19 -21
- ultralytics/cfg/datasets/VisDrone.yaml +5 -5
- ultralytics/cfg/datasets/african-wildlife.yaml +1 -1
- ultralytics/cfg/datasets/coco-pose.yaml +24 -2
- ultralytics/cfg/datasets/coco.yaml +2 -2
- ultralytics/cfg/datasets/coco128-seg.yaml +1 -1
- ultralytics/cfg/datasets/coco8-pose.yaml +21 -0
- ultralytics/cfg/datasets/construction-ppe.yaml +32 -0
- ultralytics/cfg/datasets/dog-pose.yaml +28 -0
- ultralytics/cfg/datasets/dota8-multispectral.yaml +1 -1
- ultralytics/cfg/datasets/dota8.yaml +2 -2
- ultralytics/cfg/datasets/hand-keypoints.yaml +26 -2
- ultralytics/cfg/datasets/kitti.yaml +27 -0
- ultralytics/cfg/datasets/lvis.yaml +7 -7
- ultralytics/cfg/datasets/open-images-v7.yaml +1 -1
- ultralytics/cfg/datasets/tiger-pose.yaml +16 -0
- ultralytics/cfg/datasets/xView.yaml +16 -16
- ultralytics/cfg/default.yaml +96 -94
- ultralytics/cfg/models/11/yolo11-pose.yaml +1 -1
- ultralytics/cfg/models/11/yoloe-11-seg.yaml +2 -2
- ultralytics/cfg/models/11/yoloe-11.yaml +2 -2
- ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +1 -1
- ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +1 -1
- ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +1 -1
- ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +1 -1
- ultralytics/cfg/models/v10/yolov10b.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10l.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10m.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10n.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10s.yaml +2 -2
- ultralytics/cfg/models/v10/yolov10x.yaml +2 -2
- ultralytics/cfg/models/v3/yolov3-tiny.yaml +1 -1
- ultralytics/cfg/models/v6/yolov6.yaml +1 -1
- ultralytics/cfg/models/v8/yoloe-v8-seg.yaml +9 -6
- ultralytics/cfg/models/v8/yoloe-v8.yaml +9 -6
- ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +2 -2
- ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +2 -2
- ultralytics/cfg/models/v8/yolov8-ghost.yaml +2 -2
- ultralytics/cfg/models/v8/yolov8-obb.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-p2.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-world.yaml +1 -1
- ultralytics/cfg/models/v8/yolov8-worldv2.yaml +6 -6
- ultralytics/cfg/models/v9/yolov9s.yaml +1 -1
- ultralytics/cfg/trackers/botsort.yaml +16 -17
- ultralytics/cfg/trackers/bytetrack.yaml +9 -11
- ultralytics/data/__init__.py +4 -4
- ultralytics/data/annotator.py +3 -4
- ultralytics/data/augment.py +286 -476
- ultralytics/data/base.py +18 -26
- ultralytics/data/build.py +151 -26
- ultralytics/data/converter.py +38 -50
- ultralytics/data/dataset.py +47 -75
- ultralytics/data/loaders.py +42 -49
- ultralytics/data/split.py +5 -6
- ultralytics/data/split_dota.py +8 -15
- ultralytics/data/utils.py +41 -45
- ultralytics/engine/exporter.py +462 -462
- ultralytics/engine/model.py +150 -191
- ultralytics/engine/predictor.py +30 -40
- ultralytics/engine/results.py +177 -311
- ultralytics/engine/trainer.py +193 -120
- ultralytics/engine/tuner.py +77 -63
- ultralytics/engine/validator.py +39 -22
- ultralytics/hub/__init__.py +16 -19
- ultralytics/hub/auth.py +6 -12
- ultralytics/hub/google/__init__.py +7 -10
- ultralytics/hub/session.py +15 -25
- ultralytics/hub/utils.py +5 -8
- ultralytics/models/__init__.py +1 -1
- ultralytics/models/fastsam/__init__.py +1 -1
- ultralytics/models/fastsam/model.py +8 -10
- ultralytics/models/fastsam/predict.py +19 -30
- ultralytics/models/fastsam/utils.py +1 -2
- ultralytics/models/fastsam/val.py +5 -7
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/nas/model.py +5 -8
- ultralytics/models/nas/predict.py +7 -9
- ultralytics/models/nas/val.py +1 -2
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/rtdetr/model.py +7 -8
- ultralytics/models/rtdetr/predict.py +15 -19
- ultralytics/models/rtdetr/train.py +10 -13
- ultralytics/models/rtdetr/val.py +21 -23
- ultralytics/models/sam/__init__.py +15 -2
- ultralytics/models/sam/amg.py +14 -20
- ultralytics/models/sam/build.py +26 -19
- ultralytics/models/sam/build_sam3.py +377 -0
- ultralytics/models/sam/model.py +29 -32
- ultralytics/models/sam/modules/blocks.py +83 -144
- ultralytics/models/sam/modules/decoders.py +22 -40
- ultralytics/models/sam/modules/encoders.py +44 -101
- ultralytics/models/sam/modules/memory_attention.py +16 -30
- ultralytics/models/sam/modules/sam.py +206 -79
- ultralytics/models/sam/modules/tiny_encoder.py +64 -83
- ultralytics/models/sam/modules/transformer.py +18 -28
- ultralytics/models/sam/modules/utils.py +174 -50
- ultralytics/models/sam/predict.py +2268 -366
- ultralytics/models/sam/sam3/__init__.py +3 -0
- ultralytics/models/sam/sam3/decoder.py +546 -0
- ultralytics/models/sam/sam3/encoder.py +529 -0
- ultralytics/models/sam/sam3/geometry_encoders.py +415 -0
- ultralytics/models/sam/sam3/maskformer_segmentation.py +286 -0
- ultralytics/models/sam/sam3/model_misc.py +199 -0
- ultralytics/models/sam/sam3/necks.py +129 -0
- ultralytics/models/sam/sam3/sam3_image.py +339 -0
- ultralytics/models/sam/sam3/text_encoder_ve.py +307 -0
- ultralytics/models/sam/sam3/vitdet.py +547 -0
- ultralytics/models/sam/sam3/vl_combiner.py +160 -0
- ultralytics/models/utils/loss.py +14 -26
- ultralytics/models/utils/ops.py +13 -17
- ultralytics/models/yolo/__init__.py +1 -1
- ultralytics/models/yolo/classify/predict.py +9 -12
- ultralytics/models/yolo/classify/train.py +15 -41
- ultralytics/models/yolo/classify/val.py +34 -32
- ultralytics/models/yolo/detect/predict.py +8 -11
- ultralytics/models/yolo/detect/train.py +13 -32
- ultralytics/models/yolo/detect/val.py +75 -63
- ultralytics/models/yolo/model.py +37 -53
- ultralytics/models/yolo/obb/predict.py +5 -14
- ultralytics/models/yolo/obb/train.py +11 -14
- ultralytics/models/yolo/obb/val.py +42 -39
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +7 -22
- ultralytics/models/yolo/pose/train.py +10 -22
- ultralytics/models/yolo/pose/val.py +40 -59
- ultralytics/models/yolo/segment/predict.py +16 -20
- ultralytics/models/yolo/segment/train.py +3 -12
- ultralytics/models/yolo/segment/val.py +106 -56
- ultralytics/models/yolo/world/train.py +12 -16
- ultralytics/models/yolo/world/train_world.py +11 -34
- ultralytics/models/yolo/yoloe/__init__.py +7 -7
- ultralytics/models/yolo/yoloe/predict.py +16 -23
- ultralytics/models/yolo/yoloe/train.py +31 -56
- ultralytics/models/yolo/yoloe/train_seg.py +5 -10
- ultralytics/models/yolo/yoloe/val.py +16 -21
- ultralytics/nn/__init__.py +7 -7
- ultralytics/nn/autobackend.py +152 -80
- ultralytics/nn/modules/__init__.py +60 -60
- ultralytics/nn/modules/activation.py +4 -6
- ultralytics/nn/modules/block.py +133 -217
- ultralytics/nn/modules/conv.py +52 -97
- ultralytics/nn/modules/head.py +64 -116
- ultralytics/nn/modules/transformer.py +79 -89
- ultralytics/nn/modules/utils.py +16 -21
- ultralytics/nn/tasks.py +111 -156
- ultralytics/nn/text_model.py +40 -67
- ultralytics/solutions/__init__.py +12 -12
- ultralytics/solutions/ai_gym.py +11 -17
- ultralytics/solutions/analytics.py +15 -16
- ultralytics/solutions/config.py +5 -6
- ultralytics/solutions/distance_calculation.py +10 -13
- ultralytics/solutions/heatmap.py +7 -13
- ultralytics/solutions/instance_segmentation.py +5 -8
- ultralytics/solutions/object_blurrer.py +7 -10
- ultralytics/solutions/object_counter.py +12 -19
- ultralytics/solutions/object_cropper.py +8 -14
- ultralytics/solutions/parking_management.py +33 -31
- ultralytics/solutions/queue_management.py +10 -12
- ultralytics/solutions/region_counter.py +9 -12
- ultralytics/solutions/security_alarm.py +15 -20
- ultralytics/solutions/similarity_search.py +13 -17
- ultralytics/solutions/solutions.py +75 -74
- ultralytics/solutions/speed_estimation.py +7 -10
- ultralytics/solutions/streamlit_inference.py +4 -7
- ultralytics/solutions/templates/similarity-search.html +7 -18
- ultralytics/solutions/trackzone.py +7 -10
- ultralytics/solutions/vision_eye.py +5 -8
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/basetrack.py +3 -5
- ultralytics/trackers/bot_sort.py +10 -27
- ultralytics/trackers/byte_tracker.py +14 -30
- ultralytics/trackers/track.py +3 -6
- ultralytics/trackers/utils/gmc.py +11 -22
- ultralytics/trackers/utils/kalman_filter.py +37 -48
- ultralytics/trackers/utils/matching.py +12 -15
- ultralytics/utils/__init__.py +116 -116
- ultralytics/utils/autobatch.py +2 -4
- ultralytics/utils/autodevice.py +17 -18
- ultralytics/utils/benchmarks.py +70 -70
- ultralytics/utils/callbacks/base.py +8 -10
- ultralytics/utils/callbacks/clearml.py +5 -13
- ultralytics/utils/callbacks/comet.py +32 -46
- ultralytics/utils/callbacks/dvc.py +13 -18
- ultralytics/utils/callbacks/mlflow.py +4 -5
- ultralytics/utils/callbacks/neptune.py +7 -15
- ultralytics/utils/callbacks/platform.py +314 -38
- ultralytics/utils/callbacks/raytune.py +3 -4
- ultralytics/utils/callbacks/tensorboard.py +23 -31
- ultralytics/utils/callbacks/wb.py +10 -13
- ultralytics/utils/checks.py +151 -87
- ultralytics/utils/cpu.py +3 -8
- ultralytics/utils/dist.py +19 -15
- ultralytics/utils/downloads.py +29 -41
- ultralytics/utils/errors.py +6 -14
- ultralytics/utils/events.py +2 -4
- ultralytics/utils/export/__init__.py +7 -0
- ultralytics/utils/{export.py → export/engine.py} +16 -16
- ultralytics/utils/export/imx.py +325 -0
- ultralytics/utils/export/tensorflow.py +231 -0
- ultralytics/utils/files.py +24 -28
- ultralytics/utils/git.py +9 -11
- ultralytics/utils/instance.py +30 -51
- ultralytics/utils/logger.py +212 -114
- ultralytics/utils/loss.py +15 -24
- ultralytics/utils/metrics.py +131 -160
- ultralytics/utils/nms.py +21 -30
- ultralytics/utils/ops.py +107 -165
- ultralytics/utils/patches.py +33 -21
- ultralytics/utils/plotting.py +122 -119
- ultralytics/utils/tal.py +28 -44
- ultralytics/utils/torch_utils.py +70 -187
- ultralytics/utils/tqdm.py +20 -20
- ultralytics/utils/triton.py +13 -19
- ultralytics/utils/tuner.py +17 -5
- dgenerate_ultralytics_headless-8.3.196.dist-info/RECORD +0 -281
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/WHEEL +0 -0
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.196.dist-info → dgenerate_ultralytics_headless-8.3.248.dist-info}/top_level.txt +0 -0
tests/test_python.py
CHANGED
|
@@ -12,7 +12,7 @@ import pytest
|
|
|
12
12
|
import torch
|
|
13
13
|
from PIL import Image
|
|
14
14
|
|
|
15
|
-
from tests import CFG, MODEL, MODELS, SOURCE, SOURCES_LIST, TASK_MODEL_DATA
|
|
15
|
+
from tests import CFG, MODEL, MODELS, SOURCE, SOURCES_LIST, TASK_MODEL_DATA
|
|
16
16
|
from ultralytics import RTDETR, YOLO
|
|
17
17
|
from ultralytics.cfg import TASK2DATA, TASKS
|
|
18
18
|
from ultralytics.data.build import load_inference_source
|
|
@@ -20,8 +20,11 @@ from ultralytics.data.utils import check_det_dataset
|
|
|
20
20
|
from ultralytics.utils import (
|
|
21
21
|
ARM64,
|
|
22
22
|
ASSETS,
|
|
23
|
+
ASSETS_URL,
|
|
23
24
|
DEFAULT_CFG,
|
|
24
25
|
DEFAULT_CFG_PATH,
|
|
26
|
+
IS_JETSON,
|
|
27
|
+
IS_RASPBERRYPI,
|
|
25
28
|
LINUX,
|
|
26
29
|
LOGGER,
|
|
27
30
|
ONLINE,
|
|
@@ -30,13 +33,10 @@ from ultralytics.utils import (
|
|
|
30
33
|
WINDOWS,
|
|
31
34
|
YAML,
|
|
32
35
|
checks,
|
|
33
|
-
is_dir_writeable,
|
|
34
36
|
is_github_action_running,
|
|
35
37
|
)
|
|
36
38
|
from ultralytics.utils.downloads import download
|
|
37
|
-
from ultralytics.utils.torch_utils import
|
|
38
|
-
|
|
39
|
-
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
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
def test_model_forward():
|
|
@@ -74,10 +74,9 @@ def test_model_profile():
|
|
|
74
74
|
_ = model.predict(im, profile=True)
|
|
75
75
|
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
def test_predict_txt():
|
|
77
|
+
def test_predict_txt(tmp_path):
|
|
79
78
|
"""Test YOLO predictions with file, directory, and pattern sources listed in a text file."""
|
|
80
|
-
file =
|
|
79
|
+
file = tmp_path / "sources_multi_row.txt"
|
|
81
80
|
with open(file, "w") as f:
|
|
82
81
|
for src in SOURCES_LIST:
|
|
83
82
|
f.write(f"{src}\n")
|
|
@@ -86,10 +85,9 @@ def test_predict_txt():
|
|
|
86
85
|
|
|
87
86
|
|
|
88
87
|
@pytest.mark.skipif(True, reason="disabled for testing")
|
|
89
|
-
|
|
90
|
-
def test_predict_csv_multi_row():
|
|
88
|
+
def test_predict_csv_multi_row(tmp_path):
|
|
91
89
|
"""Test YOLO predictions with sources listed in multiple rows of a CSV file."""
|
|
92
|
-
file =
|
|
90
|
+
file = tmp_path / "sources_multi_row.csv"
|
|
93
91
|
with open(file, "w", newline="") as f:
|
|
94
92
|
writer = csv.writer(f)
|
|
95
93
|
writer.writerow(["source"])
|
|
@@ -99,10 +97,9 @@ def test_predict_csv_multi_row():
|
|
|
99
97
|
|
|
100
98
|
|
|
101
99
|
@pytest.mark.skipif(True, reason="disabled for testing")
|
|
102
|
-
|
|
103
|
-
def test_predict_csv_single_row():
|
|
100
|
+
def test_predict_csv_single_row(tmp_path):
|
|
104
101
|
"""Test YOLO predictions with sources listed in a single row of a CSV file."""
|
|
105
|
-
file =
|
|
102
|
+
file = tmp_path / "sources_single_row.csv"
|
|
106
103
|
with open(file, "w", newline="") as f:
|
|
107
104
|
writer = csv.writer(f)
|
|
108
105
|
writer.writerow(SOURCES_LIST)
|
|
@@ -115,7 +112,7 @@ def test_predict_img(model_name):
|
|
|
115
112
|
"""Test YOLO model predictions on various image input types and sources, including online images."""
|
|
116
113
|
channels = 1 if model_name == "yolo11n-grayscale.pt" else 3
|
|
117
114
|
model = YOLO(WEIGHTS_DIR / model_name)
|
|
118
|
-
im = cv2.imread(str(SOURCE), flags=cv2.IMREAD_GRAYSCALE if channels == 1 else cv2.IMREAD_COLOR) # uint8
|
|
115
|
+
im = cv2.imread(str(SOURCE), flags=cv2.IMREAD_GRAYSCALE if channels == 1 else cv2.IMREAD_COLOR) # uint8 NumPy array
|
|
119
116
|
assert len(model(source=Image.open(SOURCE), save=True, verbose=True, imgsz=32)) == 1 # PIL
|
|
120
117
|
assert len(model(source=im, save=True, save_txt=True, imgsz=32)) == 1 # ndarray
|
|
121
118
|
assert len(model(torch.rand((2, channels, 32, 32)), imgsz=32)) == 2 # batch-size 2 Tensor, FP32 0.0-1.0 RGB order
|
|
@@ -125,7 +122,7 @@ def test_predict_img(model_name):
|
|
|
125
122
|
batch = [
|
|
126
123
|
str(SOURCE), # filename
|
|
127
124
|
Path(SOURCE), # Path
|
|
128
|
-
"
|
|
125
|
+
f"{ASSETS_URL}/zidane.jpg?token=123" if ONLINE else SOURCE, # URI
|
|
129
126
|
im, # OpenCV
|
|
130
127
|
Image.open(SOURCE), # PIL
|
|
131
128
|
np.zeros((320, 640, channels), dtype=np.uint8), # numpy
|
|
@@ -139,25 +136,23 @@ def test_predict_visualize(model):
|
|
|
139
136
|
YOLO(WEIGHTS_DIR / model)(SOURCE, imgsz=32, visualize=True)
|
|
140
137
|
|
|
141
138
|
|
|
142
|
-
def
|
|
143
|
-
"""Test YOLO prediction on SOURCE converted to
|
|
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."""
|
|
144
141
|
im = Image.open(SOURCE)
|
|
145
|
-
directory = TMP / "im4"
|
|
146
|
-
directory.mkdir(parents=True, exist_ok=True)
|
|
147
142
|
|
|
148
|
-
|
|
149
|
-
source_rgba =
|
|
150
|
-
source_non_utf =
|
|
151
|
-
source_spaces =
|
|
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"
|
|
152
147
|
|
|
153
|
-
im.convert("L").save(
|
|
148
|
+
im.convert("L").save(source_grayscale) # grayscale
|
|
154
149
|
im.convert("RGBA").save(source_rgba) # 4-ch PNG with alpha
|
|
155
150
|
im.save(source_non_utf) # non-UTF characters in filename
|
|
156
151
|
im.save(source_spaces) # spaces in filename
|
|
157
152
|
|
|
158
153
|
# Inference
|
|
159
154
|
model = YOLO(MODEL)
|
|
160
|
-
for f in source_rgba,
|
|
155
|
+
for f in source_rgba, source_grayscale, source_non_utf, source_spaces:
|
|
161
156
|
for source in Image.open(f), cv2.imread(str(f)), f:
|
|
162
157
|
results = model(source, save=True, verbose=True, imgsz=32)
|
|
163
158
|
assert len(results) == 1 # verify that an image was run
|
|
@@ -178,17 +173,15 @@ def test_youtube():
|
|
|
178
173
|
|
|
179
174
|
|
|
180
175
|
@pytest.mark.skipif(not ONLINE, reason="environment is offline")
|
|
181
|
-
@pytest.mark.skipif(not IS_TMP_WRITEABLE, reason="directory is not writeable")
|
|
182
176
|
@pytest.mark.parametrize("model", MODELS)
|
|
183
|
-
def test_track_stream(model):
|
|
184
|
-
"""
|
|
185
|
-
Test streaming tracking on a short 10 frame video using ByteTrack tracker and different GMC methods.
|
|
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.
|
|
186
179
|
|
|
187
180
|
Note imgsz=160 required for tracking for higher confidence and better matches.
|
|
188
181
|
"""
|
|
189
182
|
if model == "yolo11n-cls.pt": # classification model not supported for tracking
|
|
190
183
|
return
|
|
191
|
-
video_url = "
|
|
184
|
+
video_url = f"{ASSETS_URL}/decelera_portrait_min.mov"
|
|
192
185
|
model = YOLO(model)
|
|
193
186
|
model.track(video_url, imgsz=160, tracker="bytetrack.yaml")
|
|
194
187
|
model.track(video_url, imgsz=160, tracker="botsort.yaml", save_frames=True) # test frame saving also
|
|
@@ -196,7 +189,7 @@ def test_track_stream(model):
|
|
|
196
189
|
# Test Global Motion Compensation (GMC) methods and ReID
|
|
197
190
|
for gmc, reidm in zip(["orb", "sift", "ecc"], ["auto", "auto", "yolo11n-cls.pt"]):
|
|
198
191
|
default_args = YAML.load(ROOT / "cfg/trackers/botsort.yaml")
|
|
199
|
-
custom_yaml =
|
|
192
|
+
custom_yaml = tmp_path / f"botsort-{gmc}.yaml"
|
|
200
193
|
YAML.save(custom_yaml, {**default_args, "gmc_method": gmc, "with_reid": True, "model": reidm})
|
|
201
194
|
model.track(video_url, imgsz=160, tracker=custom_yaml)
|
|
202
195
|
|
|
@@ -216,6 +209,7 @@ def test_val(task: str, weight: str, data: str) -> None:
|
|
|
216
209
|
metrics.confusion_matrix.to_json()
|
|
217
210
|
|
|
218
211
|
|
|
212
|
+
@pytest.mark.skipif(IS_JETSON or IS_RASPBERRYPI, reason="Edge devices not intended for training")
|
|
219
213
|
def test_train_scratch():
|
|
220
214
|
"""Test training the YOLO model from scratch using the provided configuration."""
|
|
221
215
|
model = YOLO(CFG)
|
|
@@ -227,9 +221,7 @@ def test_train_scratch():
|
|
|
227
221
|
def test_train_ndjson():
|
|
228
222
|
"""Test training the YOLO model using NDJSON format dataset."""
|
|
229
223
|
model = YOLO(WEIGHTS_DIR / "yolo11n.pt")
|
|
230
|
-
model.train(
|
|
231
|
-
data="https://github.com/ultralytics/assets/releases/download/v0.0.0/coco8-ndjson.ndjson", epochs=1, imgsz=32
|
|
232
|
-
)
|
|
224
|
+
model.train(data=f"{ASSETS_URL}/coco8-ndjson.ndjson", epochs=1, imgsz=32)
|
|
233
225
|
|
|
234
226
|
|
|
235
227
|
@pytest.mark.parametrize("scls", [False, True])
|
|
@@ -246,7 +238,7 @@ def test_all_model_yamls():
|
|
|
246
238
|
"""Test YOLO model creation for all available YAML configurations in the `cfg/models` directory."""
|
|
247
239
|
for m in (ROOT / "cfg" / "models").rglob("*.yaml"):
|
|
248
240
|
if "rtdetr" in m.name:
|
|
249
|
-
if
|
|
241
|
+
if TORCH_1_11:
|
|
250
242
|
_ = RTDETR(m.name)(SOURCE, imgsz=640) # must be 640
|
|
251
243
|
else:
|
|
252
244
|
YOLO(m.name)
|
|
@@ -276,7 +268,7 @@ def test_predict_callback_and_setup():
|
|
|
276
268
|
model.add_callback("on_predict_batch_end", on_predict_batch_end)
|
|
277
269
|
|
|
278
270
|
dataset = load_inference_source(source=SOURCE)
|
|
279
|
-
bs = dataset.bs #
|
|
271
|
+
bs = dataset.bs # access predictor properties
|
|
280
272
|
results = model.predict(dataset, stream=True, imgsz=160) # source already setup
|
|
281
273
|
for r, im0, bs in results:
|
|
282
274
|
print("test_callback", im0.shape)
|
|
@@ -286,21 +278,21 @@ def test_predict_callback_and_setup():
|
|
|
286
278
|
|
|
287
279
|
|
|
288
280
|
@pytest.mark.parametrize("model", MODELS)
|
|
289
|
-
def test_results(model: str):
|
|
281
|
+
def test_results(model: str, tmp_path):
|
|
290
282
|
"""Test YOLO model results processing and output in various formats."""
|
|
291
|
-
|
|
292
|
-
results = YOLO(WEIGHTS_DIR / model)([
|
|
283
|
+
im = f"{ASSETS_URL}/boats.jpg" if model == "yolo11n-obb.pt" else SOURCE
|
|
284
|
+
results = YOLO(WEIGHTS_DIR / model)([im, im], imgsz=160)
|
|
293
285
|
for r in results:
|
|
294
286
|
assert len(r), f"'{model}' results should not be empty!"
|
|
295
287
|
r = r.cpu().numpy()
|
|
296
288
|
print(r, len(r), r.path) # print numpy attributes
|
|
297
289
|
r = r.to(device="cpu", dtype=torch.float32)
|
|
298
|
-
r.save_txt(txt_file=
|
|
299
|
-
r.save_crop(save_dir=
|
|
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/")
|
|
300
292
|
r.to_df(decimals=3) # Align to_ methods: https://docs.ultralytics.com/modes/predict/#working-with-results
|
|
301
293
|
r.to_csv()
|
|
302
294
|
r.to_json(normalize=True)
|
|
303
|
-
r.plot(pil=True, save=True, filename=
|
|
295
|
+
r.plot(pil=True, save=True, filename=tmp_path / "results_plot_save.jpg")
|
|
304
296
|
r.plot(conf=True, boxes=True)
|
|
305
297
|
print(r, len(r), r.path) # print after methods
|
|
306
298
|
|
|
@@ -330,7 +322,7 @@ def test_labels_and_crops():
|
|
|
330
322
|
|
|
331
323
|
|
|
332
324
|
@pytest.mark.skipif(not ONLINE, reason="environment is offline")
|
|
333
|
-
def test_data_utils():
|
|
325
|
+
def test_data_utils(tmp_path):
|
|
334
326
|
"""Test utility functions in ultralytics/data/utils.py, including dataset stats and auto-splitting."""
|
|
335
327
|
from ultralytics.data.split import autosplit
|
|
336
328
|
from ultralytics.data.utils import HUBDatasetStats
|
|
@@ -341,27 +333,28 @@ def test_data_utils():
|
|
|
341
333
|
|
|
342
334
|
for task in TASKS:
|
|
343
335
|
file = Path(TASK2DATA[task]).with_suffix(".zip") # i.e. coco8.zip
|
|
344
|
-
download(f"https://github.com/ultralytics/hub/raw/main/example_datasets/{file}", unzip=False, dir=
|
|
345
|
-
stats = HUBDatasetStats(
|
|
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)
|
|
346
338
|
stats.get_json(save=True)
|
|
347
339
|
stats.process_images()
|
|
348
340
|
|
|
349
|
-
autosplit(
|
|
350
|
-
zip_directory(
|
|
341
|
+
autosplit(tmp_path / "coco8")
|
|
342
|
+
zip_directory(tmp_path / "coco8/images/val") # zip
|
|
351
343
|
|
|
352
344
|
|
|
353
345
|
@pytest.mark.skipif(not ONLINE, reason="environment is offline")
|
|
354
|
-
def test_data_converter():
|
|
346
|
+
def test_data_converter(tmp_path):
|
|
355
347
|
"""Test dataset conversion functions from COCO to YOLO format and class mappings."""
|
|
356
348
|
from ultralytics.data.converter import coco80_to_coco91_class, convert_coco
|
|
357
349
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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
|
+
)
|
|
361
354
|
coco80_to_coco91_class()
|
|
362
355
|
|
|
363
356
|
|
|
364
|
-
def test_data_annotator():
|
|
357
|
+
def test_data_annotator(tmp_path):
|
|
365
358
|
"""Test automatic annotation of data using detection and segmentation models."""
|
|
366
359
|
from ultralytics.data.annotator import auto_annotate
|
|
367
360
|
|
|
@@ -369,7 +362,7 @@ def test_data_annotator():
|
|
|
369
362
|
ASSETS,
|
|
370
363
|
det_model=WEIGHTS_DIR / "yolo11n.pt",
|
|
371
364
|
sam_model=WEIGHTS_DIR / "mobile_sam.pt",
|
|
372
|
-
output_dir=
|
|
365
|
+
output_dir=tmp_path / "auto_annotate_labels",
|
|
373
366
|
)
|
|
374
367
|
|
|
375
368
|
|
|
@@ -392,7 +385,46 @@ def test_cfg_init():
|
|
|
392
385
|
check_dict_alignment({"a": 1}, {"b": 2})
|
|
393
386
|
copy_default_cfg()
|
|
394
387
|
(Path.cwd() / DEFAULT_CFG_PATH.name.replace(".yaml", "_copy.yaml")).unlink(missing_ok=False)
|
|
395
|
-
|
|
388
|
+
|
|
389
|
+
# Test smart_value() with comprehensive cases
|
|
390
|
+
# Test None conversion
|
|
391
|
+
assert smart_value("none") is None
|
|
392
|
+
assert smart_value("None") is None
|
|
393
|
+
assert smart_value("NONE") is None
|
|
394
|
+
|
|
395
|
+
# Test boolean conversion
|
|
396
|
+
assert smart_value("true") is True
|
|
397
|
+
assert smart_value("True") is True
|
|
398
|
+
assert smart_value("TRUE") is True
|
|
399
|
+
assert smart_value("false") is False
|
|
400
|
+
assert smart_value("False") is False
|
|
401
|
+
assert smart_value("FALSE") is False
|
|
402
|
+
|
|
403
|
+
# Test numeric conversion (ast.literal_eval)
|
|
404
|
+
assert smart_value("42") == 42
|
|
405
|
+
assert smart_value("-42") == -42
|
|
406
|
+
assert smart_value("3.14") == 3.14
|
|
407
|
+
assert smart_value("-3.14") == -3.14
|
|
408
|
+
assert smart_value("1e-3") == 0.001
|
|
409
|
+
|
|
410
|
+
# Test list/tuple conversion (ast.literal_eval)
|
|
411
|
+
assert smart_value("[1, 2, 3]") == [1, 2, 3]
|
|
412
|
+
assert smart_value("(1, 2, 3)") == (1, 2, 3)
|
|
413
|
+
assert smart_value("[640, 640]") == [640, 640]
|
|
414
|
+
|
|
415
|
+
# Test dict conversion (ast.literal_eval)
|
|
416
|
+
assert smart_value("{'a': 1, 'b': 2}") == {"a": 1, "b": 2}
|
|
417
|
+
|
|
418
|
+
# Test string fallback (when ast.literal_eval fails)
|
|
419
|
+
assert smart_value("some_string") == "some_string"
|
|
420
|
+
assert smart_value("path/to/file") == "path/to/file"
|
|
421
|
+
assert smart_value("hello world") == "hello world"
|
|
422
|
+
|
|
423
|
+
# Test that code injection is prevented (ast.literal_eval safety)
|
|
424
|
+
# These should return strings, not execute code
|
|
425
|
+
assert smart_value("__import__('os').system('ls')") == "__import__('os').system('ls')"
|
|
426
|
+
assert smart_value("eval('1+1')") == "eval('1+1')"
|
|
427
|
+
assert smart_value("exec('x=1')") == "exec('x=1')"
|
|
396
428
|
|
|
397
429
|
|
|
398
430
|
def test_utils_init():
|
|
@@ -406,7 +438,7 @@ def test_utils_init():
|
|
|
406
438
|
def test_utils_checks():
|
|
407
439
|
"""Test various utility checks for filenames, git status, requirements, image sizes, and versions."""
|
|
408
440
|
checks.check_yolov5u_filename("yolov5n.pt")
|
|
409
|
-
checks.check_requirements() # check requirements.txt
|
|
441
|
+
checks.check_requirements("numpy") # check requirements.txt
|
|
410
442
|
checks.check_imgsz([600, 600], max_dim=1)
|
|
411
443
|
checks.check_imshow(warn=True)
|
|
412
444
|
checks.check_version("ultralytics", "8.0.0")
|
|
@@ -463,7 +495,7 @@ def test_utils_ops():
|
|
|
463
495
|
torch.allclose(boxes, xyxyxyxy2xywhr(xywhr2xyxyxyxy(boxes)), rtol=1e-3)
|
|
464
496
|
|
|
465
497
|
|
|
466
|
-
def test_utils_files():
|
|
498
|
+
def test_utils_files(tmp_path):
|
|
467
499
|
"""Test file handling utilities including file age, date, and paths with spaces."""
|
|
468
500
|
from ultralytics.utils.files import file_age, file_date, get_latest_run, spaces_in_path
|
|
469
501
|
|
|
@@ -471,14 +503,14 @@ def test_utils_files():
|
|
|
471
503
|
file_date(SOURCE)
|
|
472
504
|
get_latest_run(ROOT / "runs")
|
|
473
505
|
|
|
474
|
-
path =
|
|
506
|
+
path = tmp_path / "path/with spaces"
|
|
475
507
|
path.mkdir(parents=True, exist_ok=True)
|
|
476
508
|
with spaces_in_path(path) as new_path:
|
|
477
509
|
print(new_path)
|
|
478
510
|
|
|
479
511
|
|
|
480
512
|
@pytest.mark.slow
|
|
481
|
-
def test_utils_patches_torch_save():
|
|
513
|
+
def test_utils_patches_torch_save(tmp_path):
|
|
482
514
|
"""Test torch_save backoff when _torch_save raises RuntimeError."""
|
|
483
515
|
from unittest.mock import MagicMock, patch
|
|
484
516
|
|
|
@@ -488,7 +520,7 @@ def test_utils_patches_torch_save():
|
|
|
488
520
|
|
|
489
521
|
with patch("ultralytics.utils.patches._torch_save", new=mock):
|
|
490
522
|
with pytest.raises(RuntimeError):
|
|
491
|
-
torch_save(torch.zeros(1),
|
|
523
|
+
torch_save(torch.zeros(1), tmp_path / "test.pt")
|
|
492
524
|
|
|
493
525
|
assert mock.call_count == 4, "torch_save was not attempted the expected number of times"
|
|
494
526
|
|
|
@@ -540,7 +572,7 @@ def test_hub():
|
|
|
540
572
|
|
|
541
573
|
@pytest.fixture
|
|
542
574
|
def image():
|
|
543
|
-
"""Load and return an image from a predefined source."""
|
|
575
|
+
"""Load and return an image from a predefined source (OpenCV BGR)."""
|
|
544
576
|
return cv2.imread(str(SOURCE))
|
|
545
577
|
|
|
546
578
|
|
|
@@ -634,7 +666,8 @@ def test_yolo_world():
|
|
|
634
666
|
)
|
|
635
667
|
|
|
636
668
|
|
|
637
|
-
@pytest.mark.skipif(
|
|
669
|
+
@pytest.mark.skipif(not TORCH_1_13, reason="YOLOE with CLIP requires torch>=1.13")
|
|
670
|
+
@pytest.mark.skipif(checks.IS_PYTHON_3_12, reason="YOLOE with CLIP is not supported in Python 3.12")
|
|
638
671
|
@pytest.mark.skipif(
|
|
639
672
|
checks.IS_PYTHON_3_8 and LINUX and ARM64,
|
|
640
673
|
reason="YOLOE with CLIP is not supported in Python 3.8 and aarch64 Linux",
|
|
@@ -648,16 +681,12 @@ def test_yoloe():
|
|
|
648
681
|
model.set_classes(names, model.get_text_pe(names))
|
|
649
682
|
model(SOURCE, conf=0.01)
|
|
650
683
|
|
|
651
|
-
import numpy as np
|
|
652
|
-
|
|
653
684
|
from ultralytics import YOLOE
|
|
654
685
|
from ultralytics.models.yolo.yoloe import YOLOEVPSegPredictor
|
|
655
686
|
|
|
656
687
|
# visual-prompts
|
|
657
688
|
visuals = dict(
|
|
658
|
-
bboxes=np.array(
|
|
659
|
-
[[221.52, 405.8, 344.98, 857.54], [120, 425, 160, 445]],
|
|
660
|
-
),
|
|
689
|
+
bboxes=np.array([[221.52, 405.8, 344.98, 857.54], [120, 425, 160, 445]]),
|
|
661
690
|
cls=np.array([0, 1]),
|
|
662
691
|
)
|
|
663
692
|
model.predict(
|
|
@@ -674,7 +703,7 @@ def test_yoloe():
|
|
|
674
703
|
model.val(data="coco128-seg.yaml", load_vp=True, imgsz=32)
|
|
675
704
|
|
|
676
705
|
# Train, fine-tune
|
|
677
|
-
from ultralytics.models.yolo.yoloe import YOLOEPESegTrainer
|
|
706
|
+
from ultralytics.models.yolo.yoloe import YOLOEPESegTrainer, YOLOESegTrainerFromScratch
|
|
678
707
|
|
|
679
708
|
model = YOLOE("yoloe-11s-seg.pt")
|
|
680
709
|
model.train(
|
|
@@ -684,6 +713,15 @@ def test_yoloe():
|
|
|
684
713
|
trainer=YOLOEPESegTrainer,
|
|
685
714
|
imgsz=32,
|
|
686
715
|
)
|
|
716
|
+
# Train, from scratch
|
|
717
|
+
model = YOLOE("yoloe-11s-seg.yaml")
|
|
718
|
+
model.train(
|
|
719
|
+
data=dict(train=dict(yolo_data=["coco128-seg.yaml"]), val=dict(yolo_data=["coco128-seg.yaml"])),
|
|
720
|
+
epochs=1,
|
|
721
|
+
close_mosaic=1,
|
|
722
|
+
trainer=YOLOESegTrainerFromScratch,
|
|
723
|
+
imgsz=32,
|
|
724
|
+
)
|
|
687
725
|
|
|
688
726
|
# prompt-free
|
|
689
727
|
# predict
|
|
@@ -715,14 +753,14 @@ def test_multichannel():
|
|
|
715
753
|
|
|
716
754
|
|
|
717
755
|
@pytest.mark.parametrize("task,model,data", TASK_MODEL_DATA)
|
|
718
|
-
def test_grayscale(task: str, model: str, data: str) -> None:
|
|
756
|
+
def test_grayscale(task: str, model: str, data: str, tmp_path) -> None:
|
|
719
757
|
"""Test YOLO model grayscale training, validation, and prediction functionality."""
|
|
720
758
|
if task == "classify": # not support grayscale classification yet
|
|
721
759
|
return
|
|
722
|
-
grayscale_data =
|
|
760
|
+
grayscale_data = tmp_path / f"{Path(data).stem}-grayscale.yaml"
|
|
723
761
|
data = check_det_dataset(data)
|
|
724
762
|
data["channels"] = 1 # add additional channels key for grayscale
|
|
725
|
-
YAML.save(
|
|
763
|
+
YAML.save(data=data, file=grayscale_data)
|
|
726
764
|
# remove npy files in train/val splits if exists, might be created by previous tests
|
|
727
765
|
for split in {"train", "val"}:
|
|
728
766
|
for npy_file in (Path(data["path"]) / data[split]).glob("*.npy"):
|