dgenerate-ultralytics-headless 8.3.146__py3-none-any.whl → 8.3.148__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.146.dist-info → dgenerate_ultralytics_headless-8.3.148.dist-info}/METADATA +1 -1
- {dgenerate_ultralytics_headless-8.3.146.dist-info → dgenerate_ultralytics_headless-8.3.148.dist-info}/RECORD +16 -16
- tests/test_python.py +14 -7
- ultralytics/__init__.py +1 -1
- ultralytics/data/dataset.py +1 -1
- ultralytics/engine/exporter.py +2 -2
- ultralytics/engine/model.py +1 -1
- ultralytics/models/yolo/classify/val.py +4 -4
- ultralytics/models/yolo/detect/val.py +2 -4
- ultralytics/nn/tasks.py +9 -0
- ultralytics/utils/__init__.py +1 -1
- ultralytics/utils/metrics.py +27 -7
- {dgenerate_ultralytics_headless-8.3.146.dist-info → dgenerate_ultralytics_headless-8.3.148.dist-info}/WHEEL +0 -0
- {dgenerate_ultralytics_headless-8.3.146.dist-info → dgenerate_ultralytics_headless-8.3.148.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.146.dist-info → dgenerate_ultralytics_headless-8.3.148.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.146.dist-info → dgenerate_ultralytics_headless-8.3.148.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dgenerate-ultralytics-headless
|
3
|
-
Version: 8.3.
|
3
|
+
Version: 8.3.148
|
4
4
|
Summary: Automatically built Ultralytics package with python-opencv-headless dependency instead of python-opencv
|
5
5
|
Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>, Jing Qiu <jing.qiu@ultralytics.com>
|
6
6
|
Maintainer-email: Ultralytics <hello@ultralytics.com>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
dgenerate_ultralytics_headless-8.3.
|
1
|
+
dgenerate_ultralytics_headless-8.3.148.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
2
2
|
tests/__init__.py,sha256=b4KP5_q-2IO8Br8YHOSLYnn7IwZS81l_vfEF2YPa2lM,894
|
3
3
|
tests/conftest.py,sha256=JjgKSs36ZaGmmtqGmAapmFSoFF1YwyV3IZsOgqt2IVM,2593
|
4
4
|
tests/test_cli.py,sha256=Kpfxq_RlbKK1Z8xNScDUbre6GB7neZhXZAYGI1tiDS8,5660
|
@@ -6,9 +6,9 @@ tests/test_cuda.py,sha256=-nQsfF3lGfqLm6cIeu_BCiXqLj7HzpL7R1GzPEc6z2I,8128
|
|
6
6
|
tests/test_engine.py,sha256=Jpt2KVrltrEgh2-3Ykouz-2Z_2fza0eymL5ectRXadM,4922
|
7
7
|
tests/test_exports.py,sha256=HmMKOTCia9ZDC0VYc_EPmvBTM5LM5eeI1NF_pKjLpd8,9677
|
8
8
|
tests/test_integrations.py,sha256=cQfgueFhEZ8Xs-tF0uiIEhvn0DlhOH-Wqrx96LXp3D0,6303
|
9
|
-
tests/test_python.py,sha256=
|
9
|
+
tests/test_python.py,sha256=_7xc7mqQxw3OsLhAdx-P85u9sqkfIXVhIloxmhBXph4,27800
|
10
10
|
tests/test_solutions.py,sha256=tuf6n_fsI8KvSdJrnc-cqP2qYdiYqCWuVrx0z9dOz3Q,13213
|
11
|
-
ultralytics/__init__.py,sha256
|
11
|
+
ultralytics/__init__.py,sha256=-j64BcLg5L1mlIwD6otFJ5lbv_q3zQIrzTOMQ_NrxI4,730
|
12
12
|
ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
|
13
13
|
ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
|
14
14
|
ultralytics/cfg/__init__.py,sha256=H19EalaxuIa44J_nVBrNxMj8EAPmlZl3ecbX0-xK8y8,39600
|
@@ -110,7 +110,7 @@ ultralytics/data/augment.py,sha256=fvYug6B0qrSSS8IYpvdju9uENnEJWCf-GNG5WqIayng,1
|
|
110
110
|
ultralytics/data/base.py,sha256=mRcuehK1thNuuzQGL6D1AaZkod71oHRdYTod_zdQZQg,19688
|
111
111
|
ultralytics/data/build.py,sha256=Djz6stD1FXmFhnoUJp-MKp7geu-k3xhnvt9kfXFKGhI,11020
|
112
112
|
ultralytics/data/converter.py,sha256=oKW8ODtvFOKBx9Un8n87xUUm3b5GStU4ViIBH5UDylM,27200
|
113
|
-
ultralytics/data/dataset.py,sha256=
|
113
|
+
ultralytics/data/dataset.py,sha256=bVi1yTfQKJGKItMDTYzIE6MIEPpWqzXnUqra5AXmV18,35443
|
114
114
|
ultralytics/data/loaders.py,sha256=hjkQ3aMU4A884pKNrxxQ5HDYvcwJob84qw_XUZRrav0,31732
|
115
115
|
ultralytics/data/split.py,sha256=qOHZwsHi3I1IKLgLfcz7jH3CTibeJUDyjo7HwNtB_kk,5121
|
116
116
|
ultralytics/data/split_dota.py,sha256=RJHxwOX2Z9CfSX_h7L7mO-aLQ4Ap_ZpZanQdno10oSA,12893
|
@@ -120,8 +120,8 @@ ultralytics/data/scripts/get_coco.sh,sha256=UuJpJeo3qQpTHVINeOpmP0NYmg8PhEFE3A8J
|
|
120
120
|
ultralytics/data/scripts/get_coco128.sh,sha256=qmRQl_hOKrsdHrTrnyQuFIH01oDz3lfaz138OgGfLt8,650
|
121
121
|
ultralytics/data/scripts/get_imagenet.sh,sha256=hr42H16bM47iT27rgS7MpEo-GeOZAYUQXgr0B2cwn48,1705
|
122
122
|
ultralytics/engine/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
|
123
|
-
ultralytics/engine/exporter.py,sha256=
|
124
|
-
ultralytics/engine/model.py,sha256=
|
123
|
+
ultralytics/engine/exporter.py,sha256=8lKolKJsOvMCuBDlAh1Rl9Iqy14aX8PxOiJl80xTewg,73902
|
124
|
+
ultralytics/engine/model.py,sha256=0Yslj0TPWi25CELtVQs1dRzJyJAw9-tWTlDbC6kJ0pA,53310
|
125
125
|
ultralytics/engine/predictor.py,sha256=30fBpuwOuNT3hr8bju4coeOr-jqU_8hDYESugmowLBE,22151
|
126
126
|
ultralytics/engine/results.py,sha256=Mb8pBTOrBtQh0PQtGVbhRZ_C1VyqYFumjLggiKCRIJs,72295
|
127
127
|
ultralytics/engine/trainer.py,sha256=zZ2Lm7VJOlBX-Ya52ec3n3IlSn9_yM5fbsRIWGeGOyo,39556
|
@@ -169,11 +169,11 @@ ultralytics/models/yolo/model.py,sha256=C0wInQC6rFuFOGpdAen1s2e5LIFDmqevto8uPbpm
|
|
169
169
|
ultralytics/models/yolo/classify/__init__.py,sha256=9--HVaNOfI1K7rn_rRqclL8FUAnpfeBrRqEQIaQw2xM,383
|
170
170
|
ultralytics/models/yolo/classify/predict.py,sha256=_GiN6muuZOBrMS1KER85FE4ktcw_Onn1bZdGvpbsGCE,4618
|
171
171
|
ultralytics/models/yolo/classify/train.py,sha256=jXErkxnsC3pBFQBrFxObF8BJyqkckcw3C_qHMSWZrsY,10312
|
172
|
-
ultralytics/models/yolo/classify/val.py,sha256=
|
172
|
+
ultralytics/models/yolo/classify/val.py,sha256=6YbsbqJA2J6Aw1kyOWj4eGGD0_--23G1Cz5p8lmYFLo,9705
|
173
173
|
ultralytics/models/yolo/detect/__init__.py,sha256=GIRsLYR-kT4JJx7lh4ZZAFGBZj0aebokuU0A7JbjDVA,257
|
174
174
|
ultralytics/models/yolo/detect/predict.py,sha256=ySUsdIf8dw00bzWhcxN1jZwLWKPRT2M7-N7TNL3o4zo,5387
|
175
175
|
ultralytics/models/yolo/detect/train.py,sha256=qCWz0nvU-pQofa-_F7UhUoLQe-U1ExW0mvE5ZHnav4o,9818
|
176
|
-
ultralytics/models/yolo/detect/val.py,sha256=
|
176
|
+
ultralytics/models/yolo/detect/val.py,sha256=pb9CzA8qGWGjQnp4EsoK0rlQq0rmIBppCuobNJL7QSc,19126
|
177
177
|
ultralytics/models/yolo/obb/__init__.py,sha256=tQmpG8wVHsajWkZdmD6cjGohJ4ki64iSXQT8JY_dydo,221
|
178
178
|
ultralytics/models/yolo/obb/predict.py,sha256=4r1eSld6TNJlk9JG56e-DX6oPL8uBBqiuztyBpxWlHE,2888
|
179
179
|
ultralytics/models/yolo/obb/train.py,sha256=bnYFAMur7Uvbw5Dc09-S2ge7B05iGX-t37Ksgc0ef6g,3921
|
@@ -196,7 +196,7 @@ ultralytics/models/yolo/yoloe/train_seg.py,sha256=aCV7M8oQOvODFnU4piZdJh3tIrBJYA
|
|
196
196
|
ultralytics/models/yolo/yoloe/val.py,sha256=Y0oCiqGvj8LHLrvnfPPUADSj_zNp68BVdpgcER4999E,9736
|
197
197
|
ultralytics/nn/__init__.py,sha256=rjociYD9lo_K-d-1s6TbdWklPLjTcEHk7OIlRDJstIE,615
|
198
198
|
ultralytics/nn/autobackend.py,sha256=uTOQyQ4v0_IZvvqAHnDsAxJv3QKe9-L2ozsZWSlZpPU,41287
|
199
|
-
ultralytics/nn/tasks.py,sha256=
|
199
|
+
ultralytics/nn/tasks.py,sha256=u3xrh78tzI_K_uk0b7gNaDZZQYiwIz7kRrsZGb2SGdM,72436
|
200
200
|
ultralytics/nn/text_model.py,sha256=m4jDB5bzOLOS8XNmFi9oQk-skzRHiIpJy4K-_SIARR0,13498
|
201
201
|
ultralytics/nn/modules/__init__.py,sha256=2nY0X69Z5DD5SWt6v3CUTZa5gXSzC9TQr3VTVqhyGho,3158
|
202
202
|
ultralytics/nn/modules/activation.py,sha256=75JcIMH2Cu9GTC2Uf55r_5YLpxcrXQDaVoeGQ0hlUAU,2233
|
@@ -235,7 +235,7 @@ ultralytics/trackers/utils/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6D
|
|
235
235
|
ultralytics/trackers/utils/gmc.py,sha256=9IvCf5MhBYY9ppVHykN02_oBWHmE98R8EaYFKaykdV0,14032
|
236
236
|
ultralytics/trackers/utils/kalman_filter.py,sha256=PPmM0lwBMdT_hGojvfLoUsBUFMBBMNRAxKbMcQa3wJ0,21619
|
237
237
|
ultralytics/trackers/utils/matching.py,sha256=uSYtywqi1lE_uNN1FwuBFPyISfDQXHMu8K5KH69nrRI,7160
|
238
|
-
ultralytics/utils/__init__.py,sha256=
|
238
|
+
ultralytics/utils/__init__.py,sha256=GYsojWuYvvSCKhUtQhzv-HmLjfUJrqZXqvu8bw7HbeU,59523
|
239
239
|
ultralytics/utils/autobatch.py,sha256=33m8YgggLIhltDqMXZ5OE-FGs2QiHrl2-LfgY1mI4cw,5119
|
240
240
|
ultralytics/utils/autodevice.py,sha256=AvgXFt8c1Cg4icKh0Hbhhz8UmVQ2Wjyfdfkeb2C8zck,8855
|
241
241
|
ultralytics/utils/benchmarks.py,sha256=14jidnH74g_ZCChuJF5qUnQ2YugX5amGTjea9__RlJ4,30836
|
@@ -247,7 +247,7 @@ ultralytics/utils/export.py,sha256=ZmxiY5Y2MuL4iBFsLr8ykbUsnvT01DCs0Kg1w3_Ikac,9
|
|
247
247
|
ultralytics/utils/files.py,sha256=ZCbLGleiF0f-PqYfaxMFAWop88w7U1hpreHXl8b2ko0,8238
|
248
248
|
ultralytics/utils/instance.py,sha256=vhqaZRGT_4K9Q3oQH5KNNK4ISOzxlf1_JjauwhuFhu0,18408
|
249
249
|
ultralytics/utils/loss.py,sha256=fbOWc3Iu0QOJiWbi-mXWA9-1otTYlehtmUsI7os7ydM,39799
|
250
|
-
ultralytics/utils/metrics.py,sha256=
|
250
|
+
ultralytics/utils/metrics.py,sha256=N-QwG-a3ox2cUYdS7-q-cOxLdwlkkZvhA2mF5UdO3jU,63020
|
251
251
|
ultralytics/utils/ops.py,sha256=Yjm397sirPt9wNlgHU2SeVEApeEeYX1msSg5cTBGN8g,34381
|
252
252
|
ultralytics/utils/patches.py,sha256=GI7NXCJ5H22FGp3sIvj5rrGfwdYNRWlxFcW-Jhjgius,5181
|
253
253
|
ultralytics/utils/plotting.py,sha256=QMwedj19XNHus5NbUY3cQI1PGDgriPhHOzGirBsxdK8,48277
|
@@ -266,8 +266,8 @@ ultralytics/utils/callbacks/neptune.py,sha256=j8pecmlcsM8FGzLKWoBw5xUsi5t8E5HuxY
|
|
266
266
|
ultralytics/utils/callbacks/raytune.py,sha256=S6Bq16oQDQ8BQgnZzA0zJHGN_BBr8iAM_WtGoLiEcwg,1283
|
267
267
|
ultralytics/utils/callbacks/tensorboard.py,sha256=MDPBW7aDes-66OE6YqKXXvqA_EocjzEMHWGM-8z9vUQ,5281
|
268
268
|
ultralytics/utils/callbacks/wb.py,sha256=Tm_-aRr2CN32MJkY9tylpMBJkb007-MSRNSQ7rDJ5QU,7521
|
269
|
-
dgenerate_ultralytics_headless-8.3.
|
270
|
-
dgenerate_ultralytics_headless-8.3.
|
271
|
-
dgenerate_ultralytics_headless-8.3.
|
272
|
-
dgenerate_ultralytics_headless-8.3.
|
273
|
-
dgenerate_ultralytics_headless-8.3.
|
269
|
+
dgenerate_ultralytics_headless-8.3.148.dist-info/METADATA,sha256=UqyClvdjnReFjdUuo37nR-nQ1WVErIm6tTIT9svuamk,38296
|
270
|
+
dgenerate_ultralytics_headless-8.3.148.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
271
|
+
dgenerate_ultralytics_headless-8.3.148.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
|
272
|
+
dgenerate_ultralytics_headless-8.3.148.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
|
273
|
+
dgenerate_ultralytics_headless-8.3.148.dist-info/RECORD,,
|
tests/test_python.py
CHANGED
@@ -203,13 +203,20 @@ def test_track_stream(model):
|
|
203
203
|
@pytest.mark.parametrize("task,model,data", TASK_MODEL_DATA)
|
204
204
|
def test_val(task: str, model: str, data: str) -> None:
|
205
205
|
"""Test the validation mode of the YOLO model."""
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
206
|
+
for plots in [True, False]: # Test both cases i.e. plots=True and plots=False
|
207
|
+
metrics = YOLO(model).val(data=data, imgsz=32, plots=plots)
|
208
|
+
metrics.to_df()
|
209
|
+
metrics.to_csv()
|
210
|
+
metrics.to_xml()
|
211
|
+
metrics.to_html()
|
212
|
+
metrics.to_json()
|
213
|
+
metrics.to_sql()
|
214
|
+
metrics.confusion_matrix.to_df() # Tests for confusion matrix export
|
215
|
+
metrics.confusion_matrix.to_csv()
|
216
|
+
metrics.confusion_matrix.to_xml()
|
217
|
+
metrics.confusion_matrix.to_html()
|
218
|
+
metrics.confusion_matrix.to_json()
|
219
|
+
metrics.confusion_matrix.to_sql()
|
213
220
|
|
214
221
|
|
215
222
|
def test_train_scratch():
|
ultralytics/__init__.py
CHANGED
ultralytics/data/dataset.py
CHANGED
@@ -577,7 +577,7 @@ class GroundingDataset(YOLODataset):
|
|
577
577
|
cache, _ = load_dataset_cache_file(cache_path), True # attempt to load a *.cache file
|
578
578
|
assert cache["version"] == DATASET_CACHE_VERSION # matches current version
|
579
579
|
assert cache["hash"] == get_hash(self.json_file) # identical hash
|
580
|
-
except (FileNotFoundError, AssertionError, AttributeError):
|
580
|
+
except (FileNotFoundError, AssertionError, AttributeError, ModuleNotFoundError):
|
581
581
|
cache, _ = self.cache_labels(cache_path), False # run cache ops
|
582
582
|
[cache.pop(k) for k in ("hash", "version")] # remove items
|
583
583
|
labels = cache["labels"]
|
ultralytics/engine/exporter.py
CHANGED
@@ -598,7 +598,7 @@ class Exporter:
|
|
598
598
|
"""Export YOLO model to ONNX format."""
|
599
599
|
requirements = ["onnx>=1.12.0,<1.18.0"]
|
600
600
|
if self.args.simplify:
|
601
|
-
requirements += ["onnxslim>=0.1.
|
601
|
+
requirements += ["onnxslim>=0.1.56", "onnxruntime" + ("-gpu" if torch.cuda.is_available() else "")]
|
602
602
|
check_requirements(requirements)
|
603
603
|
import onnx # noqa
|
604
604
|
|
@@ -969,7 +969,7 @@ class Exporter:
|
|
969
969
|
"ai-edge-litert>=1.2.0", # required by 'onnx2tf' package
|
970
970
|
"onnx>=1.12.0,<1.18.0",
|
971
971
|
"onnx2tf>=1.26.3",
|
972
|
-
"onnxslim>=0.1.
|
972
|
+
"onnxslim>=0.1.56",
|
973
973
|
"onnxruntime-gpu" if cuda else "onnxruntime",
|
974
974
|
"protobuf>=5",
|
975
975
|
),
|
ultralytics/engine/model.py
CHANGED
@@ -754,7 +754,7 @@ class Model(torch.nn.Module):
|
|
754
754
|
**kwargs (Any): Arbitrary keyword arguments for training configuration. Common options include:
|
755
755
|
data (str): Path to dataset configuration file.
|
756
756
|
epochs (int): Number of training epochs.
|
757
|
-
|
757
|
+
batch (int): Batch size for training.
|
758
758
|
imgsz (int): Input image size.
|
759
759
|
device (str): Device to run training on (e.g., 'cuda', 'cpu').
|
760
760
|
workers (int): Number of worker threads for data loading.
|
@@ -79,7 +79,9 @@ class ClassificationValidator(BaseValidator):
|
|
79
79
|
"""Initialize confusion matrix, class names, and tracking containers for predictions and targets."""
|
80
80
|
self.names = model.names
|
81
81
|
self.nc = len(model.names)
|
82
|
-
self.confusion_matrix = ConfusionMatrix(
|
82
|
+
self.confusion_matrix = ConfusionMatrix(
|
83
|
+
nc=self.nc, conf=self.args.conf, names=self.names.values(), task="classify"
|
84
|
+
)
|
83
85
|
self.pred = []
|
84
86
|
self.targets = []
|
85
87
|
|
@@ -124,9 +126,7 @@ class ClassificationValidator(BaseValidator):
|
|
124
126
|
self.confusion_matrix.process_cls_preds(self.pred, self.targets)
|
125
127
|
if self.args.plots:
|
126
128
|
for normalize in True, False:
|
127
|
-
self.confusion_matrix.plot(
|
128
|
-
save_dir=self.save_dir, names=self.names.values(), normalize=normalize, on_plot=self.on_plot
|
129
|
-
)
|
129
|
+
self.confusion_matrix.plot(save_dir=self.save_dir, normalize=normalize, on_plot=self.on_plot)
|
130
130
|
self.metrics.speed = self.speed
|
131
131
|
self.metrics.confusion_matrix = self.confusion_matrix
|
132
132
|
self.metrics.save_dir = self.save_dir
|
@@ -102,7 +102,7 @@ class DetectionValidator(BaseValidator):
|
|
102
102
|
self.end2end = getattr(model, "end2end", False)
|
103
103
|
self.metrics.names = self.names
|
104
104
|
self.metrics.plot = self.args.plots
|
105
|
-
self.confusion_matrix = ConfusionMatrix(nc=self.nc, conf=self.args.conf)
|
105
|
+
self.confusion_matrix = ConfusionMatrix(nc=self.nc, conf=self.args.conf, names=self.names.values())
|
106
106
|
self.seen = 0
|
107
107
|
self.jdict = []
|
108
108
|
self.stats = dict(tp=[], conf=[], pred_cls=[], target_cls=[], target_img=[])
|
@@ -231,9 +231,7 @@ class DetectionValidator(BaseValidator):
|
|
231
231
|
"""Set final values for metrics speed and confusion matrix."""
|
232
232
|
if self.args.plots:
|
233
233
|
for normalize in True, False:
|
234
|
-
self.confusion_matrix.plot(
|
235
|
-
save_dir=self.save_dir, names=self.names.values(), normalize=normalize, on_plot=self.on_plot
|
236
|
-
)
|
234
|
+
self.confusion_matrix.plot(save_dir=self.save_dir, normalize=normalize, on_plot=self.on_plot)
|
237
235
|
self.metrics.speed = self.speed
|
238
236
|
self.metrics.confusion_matrix = self.confusion_matrix
|
239
237
|
|
ultralytics/nn/tasks.py
CHANGED
@@ -411,8 +411,11 @@ class DetectionModel(BaseModel):
|
|
411
411
|
return self.forward(x)["one2many"]
|
412
412
|
return self.forward(x)[0] if isinstance(m, (Segment, YOLOESegment, Pose, OBB)) else self.forward(x)
|
413
413
|
|
414
|
+
self.model.eval() # Avoid changing batch statistics until training begins
|
415
|
+
m.training = True # Setting it to True to properly return strides
|
414
416
|
m.stride = torch.tensor([s / x.shape[-2] for x in _forward(torch.zeros(1, ch, s, s))]) # forward
|
415
417
|
self.stride = m.stride
|
418
|
+
self.model.train() # Set model back to training(default) mode
|
416
419
|
m.bias_init() # only run once
|
417
420
|
else:
|
418
421
|
self.stride = torch.Tensor([32]) # default stride for i.e. RTDETR
|
@@ -1454,6 +1457,12 @@ def torch_safe_load(weight, safe_only=False):
|
|
1454
1457
|
f"run a command with an official Ultralytics model, i.e. 'yolo predict model=yolo11n.pt'"
|
1455
1458
|
)
|
1456
1459
|
) from e
|
1460
|
+
elif e.name == "numpy._core":
|
1461
|
+
raise ModuleNotFoundError(
|
1462
|
+
emojis(
|
1463
|
+
f"ERROR ❌️ {weight} requires numpy>=1.26.1, however numpy=={__import__('numpy').__version__} is installed."
|
1464
|
+
)
|
1465
|
+
) from e
|
1457
1466
|
LOGGER.warning(
|
1458
1467
|
f"{weight} appears to require '{e.name}', which is not in Ultralytics requirements."
|
1459
1468
|
f"\nAutoInstall will run now for '{e.name}' but this feature will be removed in the future."
|
ultralytics/utils/__init__.py
CHANGED
ultralytics/utils/metrics.py
CHANGED
@@ -309,7 +309,7 @@ def smooth_bce(eps: float = 0.1) -> Tuple[float, float]:
|
|
309
309
|
return 1.0 - 0.5 * eps, 0.5 * eps
|
310
310
|
|
311
311
|
|
312
|
-
class ConfusionMatrix:
|
312
|
+
class ConfusionMatrix(DataExportMixin):
|
313
313
|
"""
|
314
314
|
A class for calculating and updating a confusion matrix for object detection and classification tasks.
|
315
315
|
|
@@ -321,7 +321,7 @@ class ConfusionMatrix:
|
|
321
321
|
iou_thres (float): The Intersection over Union threshold.
|
322
322
|
"""
|
323
323
|
|
324
|
-
def __init__(self, nc: int, conf: float = 0.25, iou_thres: float = 0.45, task: str = "detect"):
|
324
|
+
def __init__(self, nc: int, conf: float = 0.25, iou_thres: float = 0.45, names: tuple = (), task: str = "detect"):
|
325
325
|
"""
|
326
326
|
Initialize a ConfusionMatrix instance.
|
327
327
|
|
@@ -329,11 +329,13 @@ class ConfusionMatrix:
|
|
329
329
|
nc (int): Number of classes.
|
330
330
|
conf (float, optional): Confidence threshold for detections.
|
331
331
|
iou_thres (float, optional): IoU threshold for matching detections to ground truth.
|
332
|
+
names (tuple, optional): Names of classes, used as labels on the plot.
|
332
333
|
task (str, optional): Type of task, either 'detect' or 'classify'.
|
333
334
|
"""
|
334
335
|
self.task = task
|
335
336
|
self.matrix = np.zeros((nc + 1, nc + 1)) if self.task == "detect" else np.zeros((nc, nc))
|
336
337
|
self.nc = nc # number of classes
|
338
|
+
self.names = list(names) # name of classes
|
337
339
|
self.conf = 0.25 if conf in {None, 0.001} else conf # apply 0.25 if default val conf is passed
|
338
340
|
self.iou_thres = iou_thres
|
339
341
|
|
@@ -426,14 +428,13 @@ class ConfusionMatrix:
|
|
426
428
|
|
427
429
|
@TryExcept(msg="ConfusionMatrix plot failure")
|
428
430
|
@plt_settings()
|
429
|
-
def plot(self, normalize: bool = True, save_dir: str = "",
|
431
|
+
def plot(self, normalize: bool = True, save_dir: str = "", on_plot=None):
|
430
432
|
"""
|
431
433
|
Plot the confusion matrix using matplotlib and save it to a file.
|
432
434
|
|
433
435
|
Args:
|
434
436
|
normalize (bool, optional): Whether to normalize the confusion matrix.
|
435
437
|
save_dir (str, optional): Directory where the plot will be saved.
|
436
|
-
names (tuple, optional): Names of classes, used as labels on the plot.
|
437
438
|
on_plot (callable, optional): An optional callback to pass plots path and data when they are rendered.
|
438
439
|
"""
|
439
440
|
import matplotlib.pyplot as plt # scope for faster 'import ultralytics'
|
@@ -441,18 +442,17 @@ class ConfusionMatrix:
|
|
441
442
|
array = self.matrix / ((self.matrix.sum(0).reshape(1, -1) + 1e-9) if normalize else 1) # normalize columns
|
442
443
|
array[array < 0.005] = np.nan # don't annotate (would appear as 0.00)
|
443
444
|
|
444
|
-
names = list(names)
|
445
445
|
fig, ax = plt.subplots(1, 1, figsize=(12, 9))
|
446
446
|
if self.nc >= 100: # downsample for large class count
|
447
447
|
k = max(2, self.nc // 60) # step size for downsampling, always > 1
|
448
448
|
keep_idx = slice(None, None, k) # create slice instead of array
|
449
|
-
names = names[keep_idx] # slice class names
|
449
|
+
self.names = self.names[keep_idx] # slice class names
|
450
450
|
array = array[keep_idx, :][:, keep_idx] # slice matrix rows and cols
|
451
451
|
n = (self.nc + k - 1) // k # number of retained classes
|
452
452
|
nc = nn = n if self.task == "classify" else n + 1 # adjust for background if needed
|
453
453
|
else:
|
454
454
|
nc = nn = self.nc if self.task == "classify" else self.nc + 1
|
455
|
-
ticklabels = (names + ["background"]) if (0 < nn < 99) and (nn == nc) else "auto"
|
455
|
+
ticklabels = (self.names + ["background"]) if (0 < nn < 99) and (nn == nc) else "auto"
|
456
456
|
xy_ticks = np.arange(len(ticklabels))
|
457
457
|
tick_fontsize = max(6, 15 - 0.1 * nc) # Minimum size is 6
|
458
458
|
label_fontsize = max(6, 12 - 0.1 * nc)
|
@@ -505,6 +505,26 @@ class ConfusionMatrix:
|
|
505
505
|
for i in range(self.matrix.shape[0]):
|
506
506
|
LOGGER.info(" ".join(map(str, self.matrix[i])))
|
507
507
|
|
508
|
+
def summary(self, **kwargs):
|
509
|
+
"""Returns summary of the confusion matrix for export in different formats CSV, XML, HTML."""
|
510
|
+
import re
|
511
|
+
|
512
|
+
names = self.names if self.task == "classify" else self.names + ["background"]
|
513
|
+
clean_names, seen = [], set()
|
514
|
+
for name in names:
|
515
|
+
clean_name = re.sub(r"[^a-zA-Z0-9_]", "_", name)
|
516
|
+
original_clean = clean_name
|
517
|
+
counter = 1
|
518
|
+
while clean_name.lower() in seen:
|
519
|
+
clean_name = f"{original_clean}_{counter}"
|
520
|
+
counter += 1
|
521
|
+
seen.add(clean_name.lower())
|
522
|
+
clean_names.append(clean_name)
|
523
|
+
return [
|
524
|
+
dict({"Predicted": clean_names[i]}, **{clean_names[j]: self.matrix[i, j] for j in range(len(clean_names))})
|
525
|
+
for i in range(len(clean_names))
|
526
|
+
]
|
527
|
+
|
508
528
|
|
509
529
|
def smooth(y: np.ndarray, f: float = 0.05) -> np.ndarray:
|
510
530
|
"""Box filter of fraction f."""
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|