dgenerate-ultralytics-headless 8.3.187__py3-none-any.whl → 8.3.189__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.187.dist-info → dgenerate_ultralytics_headless-8.3.189.dist-info}/METADATA +3 -2
- {dgenerate_ultralytics_headless-8.3.187.dist-info → dgenerate_ultralytics_headless-8.3.189.dist-info}/RECORD +19 -19
- ultralytics/__init__.py +1 -1
- ultralytics/engine/exporter.py +4 -4
- ultralytics/models/rtdetr/val.py +3 -1
- ultralytics/models/yolo/detect/val.py +13 -2
- ultralytics/models/yolo/obb/val.py +3 -1
- ultralytics/models/yolo/segment/val.py +0 -3
- ultralytics/nn/autobackend.py +6 -3
- ultralytics/nn/tasks.py +2 -2
- ultralytics/utils/__init__.py +15 -2
- ultralytics/utils/benchmarks.py +12 -6
- ultralytics/utils/downloads.py +44 -38
- ultralytics/utils/torch_utils.py +50 -47
- ultralytics/utils/tqdm.py +25 -37
- {dgenerate_ultralytics_headless-8.3.187.dist-info → dgenerate_ultralytics_headless-8.3.189.dist-info}/WHEEL +0 -0
- {dgenerate_ultralytics_headless-8.3.187.dist-info → dgenerate_ultralytics_headless-8.3.189.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.187.dist-info → dgenerate_ultralytics_headless-8.3.189.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.187.dist-info → dgenerate_ultralytics_headless-8.3.189.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.189
|
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>
|
@@ -58,7 +58,8 @@ Requires-Dist: mkdocs-ultralytics-plugin>=0.1.29; extra == "dev"
|
|
58
58
|
Requires-Dist: mkdocs-macros-plugin>=1.0.5; extra == "dev"
|
59
59
|
Provides-Extra: export
|
60
60
|
Requires-Dist: numpy<2.0.0; extra == "export"
|
61
|
-
Requires-Dist: onnx
|
61
|
+
Requires-Dist: onnx>=1.12.0; platform_system != "Darwin" and extra == "export"
|
62
|
+
Requires-Dist: onnx<1.18.0,>=1.12.0; platform_system == "Darwin" and extra == "export"
|
62
63
|
Requires-Dist: coremltools>=8.0; (platform_system != "Windows" and python_version <= "3.13") and extra == "export"
|
63
64
|
Requires-Dist: scikit-learn>=1.3.2; (platform_system != "Windows" and python_version <= "3.13") and extra == "export"
|
64
65
|
Requires-Dist: openvino>=2024.0.0; extra == "export"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
dgenerate_ultralytics_headless-8.3.
|
1
|
+
dgenerate_ultralytics_headless-8.3.189.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=LXtQJcFNWPGuzauTGkiXgsvVC3llJKfg22WcmhRzuQc,2593
|
4
4
|
tests/test_cli.py,sha256=EMf5gTAopOnIz8VvzaM-Qb044o7D0flnUHYQ-2ffOM4,5670
|
@@ -8,7 +8,7 @@ tests/test_exports.py,sha256=CY-4xVZlVM16vdyIC0mSR3Ix59aiZm1qjFGIhSNmB20,11007
|
|
8
8
|
tests/test_integrations.py,sha256=kl_AKmE_Qs1GB0_91iVwbzNxofm_hFTt0zzU6JF-pg4,6323
|
9
9
|
tests/test_python.py,sha256=ENUbLIobqCZAxEy9W7gvhmkmW5OJ2oG-3gI8QLiJjzs,28020
|
10
10
|
tests/test_solutions.py,sha256=tuf6n_fsI8KvSdJrnc-cqP2qYdiYqCWuVrx0z9dOz3Q,13213
|
11
|
-
ultralytics/__init__.py,sha256=
|
11
|
+
ultralytics/__init__.py,sha256=do7OwLDZuVDuQVLM4bkHUsrGS_kMw-_Eoq4GGUl3zHI,730
|
12
12
|
ultralytics/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
|
13
13
|
ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
|
14
14
|
ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
|
@@ -121,7 +121,7 @@ ultralytics/data/scripts/get_coco.sh,sha256=UuJpJeo3qQpTHVINeOpmP0NYmg8PhEFE3A8J
|
|
121
121
|
ultralytics/data/scripts/get_coco128.sh,sha256=qmRQl_hOKrsdHrTrnyQuFIH01oDz3lfaz138OgGfLt8,650
|
122
122
|
ultralytics/data/scripts/get_imagenet.sh,sha256=hr42H16bM47iT27rgS7MpEo-GeOZAYUQXgr0B2cwn48,1705
|
123
123
|
ultralytics/engine/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
|
124
|
-
ultralytics/engine/exporter.py,sha256
|
124
|
+
ultralytics/engine/exporter.py,sha256=qHGD5wFmka_o8BNZTiPH8Qfp7-_y7Cz-OREOsfw9vmM,75261
|
125
125
|
ultralytics/engine/model.py,sha256=877u2n0ISz2COOYtEMUqQe0E-HHB4Atb2DuH1XCE98k,53530
|
126
126
|
ultralytics/engine/predictor.py,sha256=iXnUB-tvBHtVpKbB-5EKs1wSREBIerdUxWx39MaFYuk,22485
|
127
127
|
ultralytics/engine/results.py,sha256=6xagidv6FDJlstAX6tHob_mgfNs3459JVWeyOZgNpko,71686
|
@@ -147,7 +147,7 @@ ultralytics/models/rtdetr/__init__.py,sha256=_jEHmOjI_QP_nT3XJXLgYHQ6bXG4EL8Gnvn
|
|
147
147
|
ultralytics/models/rtdetr/model.py,sha256=e2u6kQEYawRXGGO6HbFDE1uyHfsIqvKk4IpVjjYN41k,2182
|
148
148
|
ultralytics/models/rtdetr/predict.py,sha256=Jqorq8OkGgXCCRS8DmeuGQj3XJxEhz97m22p7VxzXTw,4279
|
149
149
|
ultralytics/models/rtdetr/train.py,sha256=6FA3nDEcH1diFQ8Ky0xENp9cOOYATHxU6f42z9npMvs,3766
|
150
|
-
ultralytics/models/rtdetr/val.py,sha256=
|
150
|
+
ultralytics/models/rtdetr/val.py,sha256=8WVwlfSa6V8PQdFJIFp2bmKTZ_kBoLEvnXMLf08BbWI,8913
|
151
151
|
ultralytics/models/sam/__init__.py,sha256=4VtjxrbrSsqBvteaD_CwA4Nj3DdSUG1MknymtWwRMbc,359
|
152
152
|
ultralytics/models/sam/amg.py,sha256=IpcuIfC5KBRiF4sdrsPl1ecWEJy75axo1yG23r5BFsw,11783
|
153
153
|
ultralytics/models/sam/build.py,sha256=J6n-_QOYLa63jldEZmhRe9D3Is_AJE8xyZLUjzfRyTY,12629
|
@@ -174,11 +174,11 @@ ultralytics/models/yolo/classify/val.py,sha256=iQZRS6D3-YQjygBhFpC8VCJMI05L3uUPe
|
|
174
174
|
ultralytics/models/yolo/detect/__init__.py,sha256=GIRsLYR-kT4JJx7lh4ZZAFGBZj0aebokuU0A7JbjDVA,257
|
175
175
|
ultralytics/models/yolo/detect/predict.py,sha256=ySUsdIf8dw00bzWhcxN1jZwLWKPRT2M7-N7TNL3o4zo,5387
|
176
176
|
ultralytics/models/yolo/detect/train.py,sha256=HlaCoHJ6Y2TpCXXWabMRZApAYqBvjuM_YQJUV5JYCvw,9907
|
177
|
-
ultralytics/models/yolo/detect/val.py,sha256=
|
177
|
+
ultralytics/models/yolo/detect/val.py,sha256=rHg0lPC0ccGbVF6113-18grCViVgGdXkg-aT-0sWT4U,21318
|
178
178
|
ultralytics/models/yolo/obb/__init__.py,sha256=tQmpG8wVHsajWkZdmD6cjGohJ4ki64iSXQT8JY_dydo,221
|
179
179
|
ultralytics/models/yolo/obb/predict.py,sha256=4r1eSld6TNJlk9JG56e-DX6oPL8uBBqiuztyBpxWlHE,2888
|
180
180
|
ultralytics/models/yolo/obb/train.py,sha256=bnYFAMur7Uvbw5Dc09-S2ge7B05iGX-t37Ksgc0ef6g,3921
|
181
|
-
ultralytics/models/yolo/obb/val.py,sha256=
|
181
|
+
ultralytics/models/yolo/obb/val.py,sha256=I05mwGK620JFBz9yuGPlV9NN1fsWZE0lDqMxL5iG9YA,14085
|
182
182
|
ultralytics/models/yolo/pose/__init__.py,sha256=63xmuHZLNzV8I76HhVXAq4f2W0KTk8Oi9eL-Y204LyQ,227
|
183
183
|
ultralytics/models/yolo/pose/predict.py,sha256=M0C7ZfVXx4QXgv-szjnaXYEPas76ZLGAgDNNh1GG0vI,3743
|
184
184
|
ultralytics/models/yolo/pose/train.py,sha256=GyvNnDPJ3UFq_90HN8_FJ0dbwRkw3JJTVpkMFH0vC0o,5457
|
@@ -186,7 +186,7 @@ ultralytics/models/yolo/pose/val.py,sha256=4aOTgor8EcWvLEN5wCbk9I7ILFvb1q8_F1LlH
|
|
186
186
|
ultralytics/models/yolo/segment/__init__.py,sha256=3IThhZ1wlkY9FvmWm9cE-5-ZyE6F1FgzAtQ6jOOFzzw,275
|
187
187
|
ultralytics/models/yolo/segment/predict.py,sha256=qlprQCZn4_bpjpI08U0MU9Q9_1gpHrw_7MXwtXE1l1Y,5377
|
188
188
|
ultralytics/models/yolo/segment/train.py,sha256=XrPkXUiNu1Jvhn8iDew_RaLLjZA3un65rK-QH9mtNIw,3802
|
189
|
-
ultralytics/models/yolo/segment/val.py,sha256=
|
189
|
+
ultralytics/models/yolo/segment/val.py,sha256=GRlHSN75j7M3B5rP5owop5LzG7THIzzCxhNgec3Qi1c,11309
|
190
190
|
ultralytics/models/yolo/world/__init__.py,sha256=nlh8I6t8hMGz_vZg8QSlsUW1R-2eKvn9CGUoPPQEGhA,131
|
191
191
|
ultralytics/models/yolo/world/train.py,sha256=wBKnSC-TvrKWM1Taxqwo13XcwGHwwAXzNYV1tmqcOpc,7845
|
192
192
|
ultralytics/models/yolo/world/train_world.py,sha256=lk9z_INGPSTP_W7Rjh3qrWSmjHaxOJtGngonh1cj2SM,9551
|
@@ -196,8 +196,8 @@ ultralytics/models/yolo/yoloe/train.py,sha256=XYpQYSnSD8vi_9VSj_S5oIsNUEqm3e66vP
|
|
196
196
|
ultralytics/models/yolo/yoloe/train_seg.py,sha256=aCV7M8oQOvODFnU4piZdJh3tIrBJYAzZfRVRx1vRgxo,4956
|
197
197
|
ultralytics/models/yolo/yoloe/val.py,sha256=2NuERI3B3WeED658Cat1xL2SVpORUHlCHCWI3L8pJJc,9784
|
198
198
|
ultralytics/nn/__init__.py,sha256=rjociYD9lo_K-d-1s6TbdWklPLjTcEHk7OIlRDJstIE,615
|
199
|
-
ultralytics/nn/autobackend.py,sha256=
|
200
|
-
ultralytics/nn/tasks.py,sha256=
|
199
|
+
ultralytics/nn/autobackend.py,sha256=K98yjm1jF6aVFwfyPkS9pG1AWPFuYdQzCD4PNi6MzMY,42029
|
200
|
+
ultralytics/nn/tasks.py,sha256=wI15MlEX5FOgAIM1O2ygMxeljthvaUinYcz_jy7CJh0,72485
|
201
201
|
ultralytics/nn/text_model.py,sha256=cYwD-0el4VeToDBP4iPFOQGqyEQatJOBHrVyONL3K_s,15282
|
202
202
|
ultralytics/nn/modules/__init__.py,sha256=2nY0X69Z5DD5SWt6v3CUTZa5gXSzC9TQr3VTVqhyGho,3158
|
203
203
|
ultralytics/nn/modules/activation.py,sha256=75JcIMH2Cu9GTC2Uf55r_5YLpxcrXQDaVoeGQ0hlUAU,2233
|
@@ -236,13 +236,13 @@ ultralytics/trackers/utils/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6D
|
|
236
236
|
ultralytics/trackers/utils/gmc.py,sha256=9IvCf5MhBYY9ppVHykN02_oBWHmE98R8EaYFKaykdV0,14032
|
237
237
|
ultralytics/trackers/utils/kalman_filter.py,sha256=PPmM0lwBMdT_hGojvfLoUsBUFMBBMNRAxKbMcQa3wJ0,21619
|
238
238
|
ultralytics/trackers/utils/matching.py,sha256=uSYtywqi1lE_uNN1FwuBFPyISfDQXHMu8K5KH69nrRI,7160
|
239
|
-
ultralytics/utils/__init__.py,sha256=
|
239
|
+
ultralytics/utils/__init__.py,sha256=J4i95DBEP2t6HeNLRqCjbNqz9SwxbOBIk6IFgj11UpI,54472
|
240
240
|
ultralytics/utils/autobatch.py,sha256=33m8YgggLIhltDqMXZ5OE-FGs2QiHrl2-LfgY1mI4cw,5119
|
241
241
|
ultralytics/utils/autodevice.py,sha256=1wwjkO2tmyR5IAYa6t8G9QJgGrm00niPY4bTbTRH0Uk,8861
|
242
|
-
ultralytics/utils/benchmarks.py,sha256=
|
242
|
+
ultralytics/utils/benchmarks.py,sha256=wqIdUpYLp3Ac-oWX9bgngqOvmGyUiKuI61KBOcCqR6A,31479
|
243
243
|
ultralytics/utils/checks.py,sha256=q64U5wKyejD-2W2fCPqJ0Oiaa4_4vq2pVxV9wp6lMz4,34707
|
244
244
|
ultralytics/utils/dist.py,sha256=A9lDGtGefTjSVvVS38w86GOdbtLzNBDZuDGK0MT4PRI,4170
|
245
|
-
ultralytics/utils/downloads.py,sha256=
|
245
|
+
ultralytics/utils/downloads.py,sha256=jtaStUmZiWhJ9-ovubsSJHqnWS891qIZggQHGUC0fJo,23009
|
246
246
|
ultralytics/utils/errors.py,sha256=XT9Ru7ivoBgofK6PlnyigGoa7Fmf5nEhyHtnD-8TRXI,1584
|
247
247
|
ultralytics/utils/export.py,sha256=LK-wlTlyb_zIKtSvOmfmvR70RcUU9Ct9UBDt5wn9_rY,9880
|
248
248
|
ultralytics/utils/files.py,sha256=ZCbLGleiF0f-PqYfaxMFAWop88w7U1hpreHXl8b2ko0,8238
|
@@ -254,8 +254,8 @@ ultralytics/utils/ops.py,sha256=8d60fbpntrexK3gPoLUS6mWAYGrtrQaQCOYyRJsCjuI,3452
|
|
254
254
|
ultralytics/utils/patches.py,sha256=PPWiKzwGbCvuawLzDKVR8tWOQAlZbJBi8g_-A6eTCYA,6536
|
255
255
|
ultralytics/utils/plotting.py,sha256=npFWWIGEdQM3IsSSqoZ29kAFyCN3myeZOFj-gALFT6M,47465
|
256
256
|
ultralytics/utils/tal.py,sha256=aXawOnhn8ni65tJWIW-PYqWr_TRvltbHBjrTo7o6lDQ,20924
|
257
|
-
ultralytics/utils/torch_utils.py,sha256=
|
258
|
-
ultralytics/utils/tqdm.py,sha256=
|
257
|
+
ultralytics/utils/torch_utils.py,sha256=PoqnrVRRgnNw2aTxcSrjZ1PvzEg2iR8XKZYIOKVqy0o,39476
|
258
|
+
ultralytics/utils/tqdm.py,sha256=G7V-0Ku_XEKKjA8D2duWD9OToekX2LGLbbOTzd1UrWo,16414
|
259
259
|
ultralytics/utils/triton.py,sha256=M7qe4RztiADBJQEWQKaIQsp94ERFJ_8_DUHDR6TXEOM,5410
|
260
260
|
ultralytics/utils/tuner.py,sha256=bHr09Fz-0-t0ei55gX5wJh-obyiAQoicP7HUVM2I8qA,6826
|
261
261
|
ultralytics/utils/callbacks/__init__.py,sha256=hzL63Rce6VkZhP4Lcim9LKjadixaQG86nKqPhk7IkS0,242
|
@@ -270,8 +270,8 @@ ultralytics/utils/callbacks/platform.py,sha256=gdbEuedXEs1VjdU0IiedjPFwttZJUiI0d
|
|
270
270
|
ultralytics/utils/callbacks/raytune.py,sha256=S6Bq16oQDQ8BQgnZzA0zJHGN_BBr8iAM_WtGoLiEcwg,1283
|
271
271
|
ultralytics/utils/callbacks/tensorboard.py,sha256=MDPBW7aDes-66OE6YqKXXvqA_EocjzEMHWGM-8z9vUQ,5281
|
272
272
|
ultralytics/utils/callbacks/wb.py,sha256=ngQO8EJ1kxJDF1YajScVtzBbm26jGuejA0uWeOyvf5A,7685
|
273
|
-
dgenerate_ultralytics_headless-8.3.
|
274
|
-
dgenerate_ultralytics_headless-8.3.
|
275
|
-
dgenerate_ultralytics_headless-8.3.
|
276
|
-
dgenerate_ultralytics_headless-8.3.
|
277
|
-
dgenerate_ultralytics_headless-8.3.
|
273
|
+
dgenerate_ultralytics_headless-8.3.189.dist-info/METADATA,sha256=WtEdG5rsQrWBMYF3Hi2ha6V9RAeNCIkumcmrba3a5xw,38789
|
274
|
+
dgenerate_ultralytics_headless-8.3.189.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
275
|
+
dgenerate_ultralytics_headless-8.3.189.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
|
276
|
+
dgenerate_ultralytics_headless-8.3.189.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
|
277
|
+
dgenerate_ultralytics_headless-8.3.189.dist-info/RECORD,,
|
ultralytics/__init__.py
CHANGED
ultralytics/engine/exporter.py
CHANGED
@@ -582,9 +582,9 @@ class Exporter:
|
|
582
582
|
@try_export
|
583
583
|
def export_onnx(self, prefix=colorstr("ONNX:")):
|
584
584
|
"""Export YOLO model to ONNX format."""
|
585
|
-
requirements = ["onnx>=1.12.0
|
585
|
+
requirements = ["onnx>=1.12.0"]
|
586
586
|
if self.args.simplify:
|
587
|
-
requirements += ["onnxslim>=0.1.
|
587
|
+
requirements += ["onnxslim>=0.1.65", "onnxruntime" + ("-gpu" if torch.cuda.is_available() else "")]
|
588
588
|
check_requirements(requirements)
|
589
589
|
import onnx # noqa
|
590
590
|
|
@@ -960,9 +960,9 @@ class Exporter:
|
|
960
960
|
"sng4onnx>=1.0.1", # required by 'onnx2tf' package
|
961
961
|
"onnx_graphsurgeon>=0.3.26", # required by 'onnx2tf' package
|
962
962
|
"ai-edge-litert>=1.2.0,<1.4.0", # required by 'onnx2tf' package
|
963
|
-
"onnx>=1.12.0
|
963
|
+
"onnx>=1.12.0",
|
964
964
|
"onnx2tf>=1.26.3",
|
965
|
-
"onnxslim>=0.1.
|
965
|
+
"onnxslim>=0.1.65",
|
966
966
|
"onnxruntime-gpu" if cuda else "onnxruntime",
|
967
967
|
"protobuf>=5",
|
968
968
|
),
|
ultralytics/models/rtdetr/val.py
CHANGED
@@ -196,7 +196,8 @@ class RTDETRValidator(DetectionValidator):
|
|
196
196
|
with bounding box coordinates, confidence scores, and class predictions.
|
197
197
|
pbatch (Dict[str, Any]): Batch dictionary containing 'imgsz', 'ori_shape', 'ratio_pad', and 'im_file'.
|
198
198
|
"""
|
199
|
-
|
199
|
+
path = Path(pbatch["im_file"])
|
200
|
+
stem = path.stem
|
200
201
|
image_id = int(stem) if stem.isnumeric() else stem
|
201
202
|
box = predn["bboxes"].clone()
|
202
203
|
box[..., [0, 2]] *= pbatch["ori_shape"][1] / self.args.imgsz # native-space pred
|
@@ -207,6 +208,7 @@ class RTDETRValidator(DetectionValidator):
|
|
207
208
|
self.jdict.append(
|
208
209
|
{
|
209
210
|
"image_id": image_id,
|
211
|
+
"file_name": path.name,
|
210
212
|
"category_id": self.class_map[int(c)],
|
211
213
|
"bbox": [round(x, 3) for x in b],
|
212
214
|
"score": round(s, 5),
|
@@ -372,8 +372,18 @@ class DetectionValidator(BaseValidator):
|
|
372
372
|
predn (Dict[str, torch.Tensor]): Predictions dictionary containing 'bboxes', 'conf', and 'cls' keys
|
373
373
|
with bounding box coordinates, confidence scores, and class predictions.
|
374
374
|
pbatch (Dict[str, Any]): Batch dictionary containing 'imgsz', 'ori_shape', 'ratio_pad', and 'im_file'.
|
375
|
-
|
376
|
-
|
375
|
+
|
376
|
+
Examples:
|
377
|
+
>>> result = {
|
378
|
+
... "image_id": 42,
|
379
|
+
... "file_name": "42.jpg",
|
380
|
+
... "category_id": 18,
|
381
|
+
... "bbox": [258.15, 41.29, 348.26, 243.78],
|
382
|
+
... "score": 0.236,
|
383
|
+
... }
|
384
|
+
"""
|
385
|
+
path = Path(pbatch["im_file"])
|
386
|
+
stem = path.stem
|
377
387
|
image_id = int(stem) if stem.isnumeric() else stem
|
378
388
|
box = ops.xyxy2xywh(predn["bboxes"]) # xywh
|
379
389
|
box[:, :2] -= box[:, 2:] / 2 # xy center to top-left corner
|
@@ -381,6 +391,7 @@ class DetectionValidator(BaseValidator):
|
|
381
391
|
self.jdict.append(
|
382
392
|
{
|
383
393
|
"image_id": image_id,
|
394
|
+
"file_name": path.name,
|
384
395
|
"category_id": self.class_map[int(c)],
|
385
396
|
"bbox": [round(x, 3) for x in b],
|
386
397
|
"score": round(s, 5),
|
@@ -176,7 +176,8 @@ class OBBValidator(DetectionValidator):
|
|
176
176
|
(x, y, w, h, angle) and polygon format (x1, y1, x2, y2, x3, y3, x4, y4) before adding them
|
177
177
|
to the JSON dictionary.
|
178
178
|
"""
|
179
|
-
|
179
|
+
path = Path(pbatch["im_file"])
|
180
|
+
stem = path.stem
|
180
181
|
image_id = int(stem) if stem.isnumeric() else stem
|
181
182
|
rbox = predn["bboxes"]
|
182
183
|
poly = ops.xywhr2xyxyxyxy(rbox).view(-1, 8)
|
@@ -184,6 +185,7 @@ class OBBValidator(DetectionValidator):
|
|
184
185
|
self.jdict.append(
|
185
186
|
{
|
186
187
|
"image_id": image_id,
|
188
|
+
"file_name": path.name,
|
187
189
|
"category_id": self.class_map[int(c)],
|
188
190
|
"score": round(s, 5),
|
189
191
|
"rbox": [round(x, 3) for x in r],
|
@@ -217,9 +217,6 @@ class SegmentationValidator(DetectionValidator):
|
|
217
217
|
Args:
|
218
218
|
predn (Dict[str, torch.Tensor]): Predictions containing bboxes, masks, confidence scores, and classes.
|
219
219
|
pbatch (Dict[str, Any]): Batch dictionary containing 'imgsz', 'ori_shape', 'ratio_pad', and 'im_file'.
|
220
|
-
|
221
|
-
Examples:
|
222
|
-
>>> result = {"image_id": 42, "category_id": 18, "bbox": [258.15, 41.29, 348.26, 243.78], "score": 0.236}
|
223
220
|
"""
|
224
221
|
from faster_coco_eval.core.mask import encode # noqa
|
225
222
|
|
ultralytics/nn/autobackend.py
CHANGED
@@ -14,7 +14,7 @@ import torch
|
|
14
14
|
import torch.nn as nn
|
15
15
|
from PIL import Image
|
16
16
|
|
17
|
-
from ultralytics.utils import ARM64, IS_JETSON, LINUX, LOGGER, PYTHON_VERSION, ROOT, YAML
|
17
|
+
from ultralytics.utils import ARM64, IS_JETSON, LINUX, LOGGER, PYTHON_VERSION, ROOT, YAML, is_jetson
|
18
18
|
from ultralytics.utils.checks import check_requirements, check_suffix, check_version, check_yaml, is_rockchip
|
19
19
|
from ultralytics.utils.downloads import attempt_download_asset, is_url
|
20
20
|
|
@@ -194,9 +194,12 @@ class AutoBackend(nn.Module):
|
|
194
194
|
|
195
195
|
# In-memory PyTorch model
|
196
196
|
if nn_module:
|
197
|
-
model = weights.to(device)
|
198
197
|
if fuse:
|
199
|
-
|
198
|
+
if IS_JETSON and is_jetson(jetpack=5):
|
199
|
+
# Jetson Jetpack5 requires device before fuse https://github.com/ultralytics/ultralytics/pull/21028
|
200
|
+
weights = weights.to(device)
|
201
|
+
weights = weights.fuse(verbose=verbose)
|
202
|
+
model = weights.to(device)
|
200
203
|
if hasattr(model, "kpt_shape"):
|
201
204
|
kpt_shape = model.kpt_shape # pose-only
|
202
205
|
stride = max(int(model.stride.max()), 32) # model stride
|
ultralytics/nn/tasks.py
CHANGED
@@ -1500,7 +1500,7 @@ def attempt_load_weights(weights, device=None, inplace=True, fuse=False):
|
|
1500
1500
|
for w in weights if isinstance(weights, list) else [weights]:
|
1501
1501
|
ckpt, w = torch_safe_load(w) # load ckpt
|
1502
1502
|
args = {**DEFAULT_CFG_DICT, **ckpt["train_args"]} if "train_args" in ckpt else None # combined args
|
1503
|
-
model = (ckpt.get("ema") or ckpt["model"]).
|
1503
|
+
model = (ckpt.get("ema") or ckpt["model"]).float() # FP32 model
|
1504
1504
|
|
1505
1505
|
# Model compatibility updates
|
1506
1506
|
model.args = args # attach args to model
|
@@ -1510,7 +1510,7 @@ def attempt_load_weights(weights, device=None, inplace=True, fuse=False):
|
|
1510
1510
|
model.stride = torch.tensor([32.0])
|
1511
1511
|
|
1512
1512
|
# Append
|
1513
|
-
ensemble.append(model.fuse().eval() if fuse and hasattr(model, "fuse") else model.eval())
|
1513
|
+
ensemble.append((model.fuse().eval() if fuse and hasattr(model, "fuse") else model.eval()).to(device))
|
1514
1514
|
|
1515
1515
|
# Module updates
|
1516
1516
|
for m in ensemble.modules():
|
ultralytics/utils/__init__.py
CHANGED
@@ -12,6 +12,7 @@ import subprocess
|
|
12
12
|
import sys
|
13
13
|
import threading
|
14
14
|
import time
|
15
|
+
from functools import lru_cache
|
15
16
|
from pathlib import Path
|
16
17
|
from threading import Lock
|
17
18
|
from types import SimpleNamespace
|
@@ -727,14 +728,26 @@ def is_raspberrypi() -> bool:
|
|
727
728
|
return "rpi" in DEVICE_MODEL
|
728
729
|
|
729
730
|
|
730
|
-
|
731
|
+
@lru_cache(maxsize=3)
|
732
|
+
def is_jetson(jetpack=None) -> bool:
|
731
733
|
"""
|
732
734
|
Determine if the Python environment is running on an NVIDIA Jetson device.
|
733
735
|
|
736
|
+
Args:
|
737
|
+
jetpack (int | None): If specified, check for specific JetPack version (4, 5, 6).
|
738
|
+
|
734
739
|
Returns:
|
735
740
|
(bool): True if running on an NVIDIA Jetson device, False otherwise.
|
736
741
|
"""
|
737
|
-
|
742
|
+
if jetson := ("tegra" in DEVICE_MODEL):
|
743
|
+
if jetpack:
|
744
|
+
try:
|
745
|
+
content = open("/etc/nv_tegra_release").read()
|
746
|
+
version_map = {4: "R32", 5: "R35", 6: "R36"} # JetPack to L4T major version mapping
|
747
|
+
return jetpack in version_map and version_map[jetpack] in content
|
748
|
+
except Exception:
|
749
|
+
return False
|
750
|
+
return jetson
|
738
751
|
|
739
752
|
|
740
753
|
def is_online() -> bool:
|
ultralytics/utils/benchmarks.py
CHANGED
@@ -90,9 +90,13 @@ def benchmark(
|
|
90
90
|
|
91
91
|
import polars as pl # scope for faster 'import ultralytics'
|
92
92
|
|
93
|
-
pl.Config.set_tbl_cols(
|
94
|
-
pl.Config.
|
95
|
-
pl.Config.
|
93
|
+
pl.Config.set_tbl_cols(-1) # Show all columns
|
94
|
+
pl.Config.set_tbl_rows(-1) # Show all rows
|
95
|
+
pl.Config.set_tbl_width_chars(-1) # No width limit
|
96
|
+
pl.Config.set_tbl_hide_column_data_types(True) # Hide data types
|
97
|
+
pl.Config.set_tbl_hide_dataframe_shape(True) # Hide shape info
|
98
|
+
pl.Config.set_tbl_formatting("ASCII_BORDERS_ONLY_CONDENSED")
|
99
|
+
|
96
100
|
device = select_device(device, verbose=False)
|
97
101
|
if isinstance(model, (str, Path)):
|
98
102
|
model = YOLO(model)
|
@@ -194,12 +198,14 @@ def benchmark(
|
|
194
198
|
|
195
199
|
# Print results
|
196
200
|
check_yolo(device=device) # print system info
|
197
|
-
df = pl.DataFrame(y, schema=["Format", "Status❔", "Size (MB)", key, "Inference time (ms/im)", "FPS"])
|
201
|
+
df = pl.DataFrame(y, schema=["Format", "Status❔", "Size (MB)", key, "Inference time (ms/im)", "FPS"], orient="row")
|
202
|
+
df = df.with_row_index(" ", offset=1) # add index info
|
203
|
+
df_display = df.with_columns(pl.all().cast(pl.String).fill_null("-"))
|
198
204
|
|
199
205
|
name = model.model_name
|
200
206
|
dt = time.time() - t0
|
201
207
|
legend = "Benchmarks legend: - ✅ Success - ❎ Export passed but validation failed - ❌️ Export failed"
|
202
|
-
s = f"\nBenchmarks complete for {name} on {data} at imgsz={imgsz} ({dt:.2f}s)\n{legend}\n{
|
208
|
+
s = f"\nBenchmarks complete for {name} on {data} at imgsz={imgsz} ({dt:.2f}s)\n{legend}\n{df_display}\n"
|
203
209
|
LOGGER.info(s)
|
204
210
|
with open("benchmarks.log", "a", errors="ignore", encoding="utf-8") as f:
|
205
211
|
f.write(s)
|
@@ -209,7 +215,7 @@ def benchmark(
|
|
209
215
|
floor = verbose # minimum metric floor to pass, i.e. = 0.29 mAP for YOLOv5n
|
210
216
|
assert all(x > floor for x in metrics if not np.isnan(x)), f"Benchmark failure: metric(s) < floor {floor}"
|
211
217
|
|
212
|
-
return
|
218
|
+
return df_display
|
213
219
|
|
214
220
|
|
215
221
|
class RF100Benchmark:
|
ultralytics/utils/downloads.py
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import re
|
4
6
|
import shutil
|
5
7
|
import subprocess
|
6
8
|
from itertools import repeat
|
7
9
|
from multiprocessing.pool import ThreadPool
|
8
10
|
from pathlib import Path
|
9
|
-
from typing import List, Tuple
|
10
11
|
from urllib import parse, request
|
11
12
|
|
12
13
|
from ultralytics.utils import LOGGER, TQDM, checks, clean_url, emojis, is_online, url2file
|
@@ -41,7 +42,7 @@ GITHUB_ASSETS_NAMES = frozenset(
|
|
41
42
|
GITHUB_ASSETS_STEMS = frozenset(k.rpartition(".")[0] for k in GITHUB_ASSETS_NAMES)
|
42
43
|
|
43
44
|
|
44
|
-
def is_url(url, check: bool = False) -> bool:
|
45
|
+
def is_url(url: str | Path, check: bool = False) -> bool:
|
45
46
|
"""
|
46
47
|
Validate if the given string is a URL and optionally check if the URL exists online.
|
47
48
|
|
@@ -68,7 +69,7 @@ def is_url(url, check: bool = False) -> bool:
|
|
68
69
|
return False
|
69
70
|
|
70
71
|
|
71
|
-
def delete_dsstore(path, files_to_delete=(".DS_Store", "__MACOSX")):
|
72
|
+
def delete_dsstore(path: str | Path, files_to_delete: tuple[str, ...] = (".DS_Store", "__MACOSX")) -> None:
|
72
73
|
"""
|
73
74
|
Delete all specified system files in a directory.
|
74
75
|
|
@@ -91,7 +92,12 @@ def delete_dsstore(path, files_to_delete=(".DS_Store", "__MACOSX")):
|
|
91
92
|
f.unlink()
|
92
93
|
|
93
94
|
|
94
|
-
def zip_directory(
|
95
|
+
def zip_directory(
|
96
|
+
directory: str | Path,
|
97
|
+
compress: bool = True,
|
98
|
+
exclude: tuple[str, ...] = (".DS_Store", "__MACOSX"),
|
99
|
+
progress: bool = True,
|
100
|
+
) -> Path:
|
95
101
|
"""
|
96
102
|
Zip the contents of a directory, excluding specified files.
|
97
103
|
|
@@ -129,9 +135,9 @@ def zip_directory(directory, compress: bool = True, exclude=(".DS_Store", "__MAC
|
|
129
135
|
|
130
136
|
|
131
137
|
def unzip_file(
|
132
|
-
file,
|
133
|
-
path=None,
|
134
|
-
exclude=(".DS_Store", "__MACOSX"),
|
138
|
+
file: str | Path,
|
139
|
+
path: str | Path | None = None,
|
140
|
+
exclude: tuple[str, ...] = (".DS_Store", "__MACOSX"),
|
135
141
|
exist_ok: bool = False,
|
136
142
|
progress: bool = True,
|
137
143
|
) -> Path:
|
@@ -198,8 +204,8 @@ def unzip_file(
|
|
198
204
|
|
199
205
|
|
200
206
|
def check_disk_space(
|
201
|
-
|
202
|
-
path=Path.cwd(),
|
207
|
+
file_bytes: int,
|
208
|
+
path: str | Path = Path.cwd(),
|
203
209
|
sf: float = 1.5,
|
204
210
|
hard: bool = True,
|
205
211
|
) -> bool:
|
@@ -207,7 +213,7 @@ def check_disk_space(
|
|
207
213
|
Check if there is sufficient disk space to download and store a file.
|
208
214
|
|
209
215
|
Args:
|
210
|
-
|
216
|
+
file_bytes (int): The file size in bytes.
|
211
217
|
path (str | Path, optional): The path or drive to check the available free space on.
|
212
218
|
sf (float, optional): Safety factor, the multiplier for the required free space.
|
213
219
|
hard (bool, optional): Whether to throw an error or not on insufficient disk space.
|
@@ -215,26 +221,14 @@ def check_disk_space(
|
|
215
221
|
Returns:
|
216
222
|
(bool): True if there is sufficient disk space, False otherwise.
|
217
223
|
"""
|
218
|
-
|
219
|
-
|
220
|
-
try:
|
221
|
-
r = requests.head(url) # response
|
222
|
-
assert r.status_code < 400, f"URL error for {url}: {r.status_code} {r.reason}" # check response
|
223
|
-
except Exception:
|
224
|
-
return True # requests issue, default to True
|
225
|
-
|
226
|
-
# Check file size
|
227
|
-
gib = 1 << 30 # bytes per GiB
|
228
|
-
data = int(r.headers.get("Content-Length", 0)) / gib # file size (GB)
|
229
|
-
total, used, free = (x / gib for x in shutil.disk_usage(path)) # bytes
|
230
|
-
|
231
|
-
if data * sf < free:
|
224
|
+
total, used, free = shutil.disk_usage(path) # bytes
|
225
|
+
if file_bytes * sf < free:
|
232
226
|
return True # sufficient space
|
233
227
|
|
234
228
|
# Insufficient space
|
235
229
|
text = (
|
236
|
-
f"Insufficient free disk space {free:.
|
237
|
-
f"Please free {
|
230
|
+
f"Insufficient free disk space {free >> 30:.3f} GB < {int(file_bytes * sf) >> 30:.3f} GB required, "
|
231
|
+
f"Please free {int(file_bytes * sf - free) >> 30:.3f} GB additional disk space and try again."
|
238
232
|
)
|
239
233
|
if hard:
|
240
234
|
raise MemoryError(text)
|
@@ -242,7 +236,7 @@ def check_disk_space(
|
|
242
236
|
return False
|
243
237
|
|
244
238
|
|
245
|
-
def get_google_drive_file_info(link: str) ->
|
239
|
+
def get_google_drive_file_info(link: str) -> tuple[str, str | None]:
|
246
240
|
"""
|
247
241
|
Retrieve the direct download link and filename for a shareable Google Drive file link.
|
248
242
|
|
@@ -283,9 +277,9 @@ def get_google_drive_file_info(link: str) -> Tuple[str, str]:
|
|
283
277
|
|
284
278
|
|
285
279
|
def safe_download(
|
286
|
-
url,
|
287
|
-
file=None,
|
288
|
-
dir=None,
|
280
|
+
url: str | Path,
|
281
|
+
file: str | Path | None = None,
|
282
|
+
dir: str | Path | None = None,
|
289
283
|
unzip: bool = True,
|
290
284
|
delete: bool = False,
|
291
285
|
curl: bool = False,
|
@@ -293,7 +287,7 @@ def safe_download(
|
|
293
287
|
min_bytes: float = 1e0,
|
294
288
|
exist_ok: bool = False,
|
295
289
|
progress: bool = True,
|
296
|
-
):
|
290
|
+
) -> Path | str:
|
297
291
|
"""
|
298
292
|
Download files from a URL with options for retrying, unzipping, and deleting the downloaded file. Enhanced with
|
299
293
|
robust partial download detection using Content-Length validation.
|
@@ -335,7 +329,6 @@ def safe_download(
|
|
335
329
|
)
|
336
330
|
desc = f"Downloading {uri} to '{f}'"
|
337
331
|
f.parent.mkdir(parents=True, exist_ok=True) # make directory if missing
|
338
|
-
check_disk_space(url, path=f.parent)
|
339
332
|
curl_installed = shutil.which("curl")
|
340
333
|
for i in range(retry + 1):
|
341
334
|
try:
|
@@ -347,6 +340,9 @@ def safe_download(
|
|
347
340
|
else: # urllib download
|
348
341
|
with request.urlopen(url) as response:
|
349
342
|
expected_size = int(response.getheader("Content-Length", 0))
|
343
|
+
if i == 0 and expected_size > 1048576:
|
344
|
+
check_disk_space(expected_size, path=f.parent)
|
345
|
+
buffer_size = max(8192, min(1048576, expected_size // 1000)) if expected_size else 8192
|
350
346
|
with TQDM(
|
351
347
|
total=expected_size,
|
352
348
|
desc=desc,
|
@@ -356,7 +352,10 @@ def safe_download(
|
|
356
352
|
unit_divisor=1024,
|
357
353
|
) as pbar:
|
358
354
|
with open(f, "wb") as f_opened:
|
359
|
-
|
355
|
+
while True:
|
356
|
+
data = response.read(buffer_size)
|
357
|
+
if not data:
|
358
|
+
break
|
360
359
|
f_opened.write(data)
|
361
360
|
pbar.update(len(data))
|
362
361
|
|
@@ -371,6 +370,8 @@ def safe_download(
|
|
371
370
|
else:
|
372
371
|
break # success
|
373
372
|
f.unlink() # remove partial downloads
|
373
|
+
except MemoryError:
|
374
|
+
raise # Re-raise immediately - no point retrying if insufficient disk space
|
374
375
|
except Exception as e:
|
375
376
|
if i == 0 and not is_online():
|
376
377
|
raise ConnectionError(emojis(f"❌ Download failure for {uri}. Environment is not online.")) from e
|
@@ -397,7 +398,7 @@ def get_github_assets(
|
|
397
398
|
repo: str = "ultralytics/assets",
|
398
399
|
version: str = "latest",
|
399
400
|
retry: bool = False,
|
400
|
-
) ->
|
401
|
+
) -> tuple[str, list[str]]:
|
401
402
|
"""
|
402
403
|
Retrieve the specified version's tag and assets from a GitHub repository.
|
403
404
|
|
@@ -430,7 +431,12 @@ def get_github_assets(
|
|
430
431
|
return data["tag_name"], [x["name"] for x in data["assets"]] # tag, assets i.e. ['yolo11n.pt', 'yolov8s.pt', ...]
|
431
432
|
|
432
433
|
|
433
|
-
def attempt_download_asset(
|
434
|
+
def attempt_download_asset(
|
435
|
+
file: str | Path,
|
436
|
+
repo: str = "ultralytics/assets",
|
437
|
+
release: str = "v8.3.0",
|
438
|
+
**kwargs,
|
439
|
+
) -> str:
|
434
440
|
"""
|
435
441
|
Attempt to download a file from GitHub release assets if it is not found locally.
|
436
442
|
|
@@ -482,15 +488,15 @@ def attempt_download_asset(file, repo: str = "ultralytics/assets", release: str
|
|
482
488
|
|
483
489
|
|
484
490
|
def download(
|
485
|
-
url,
|
486
|
-
dir=Path.cwd(),
|
491
|
+
url: str | list[str] | Path,
|
492
|
+
dir: Path = Path.cwd(),
|
487
493
|
unzip: bool = True,
|
488
494
|
delete: bool = False,
|
489
495
|
curl: bool = False,
|
490
496
|
threads: int = 1,
|
491
497
|
retry: int = 3,
|
492
498
|
exist_ok: bool = False,
|
493
|
-
):
|
499
|
+
) -> None:
|
494
500
|
"""
|
495
501
|
Download files from specified URLs to a given directory.
|
496
502
|
|
ultralytics/utils/torch_utils.py
CHANGED
@@ -250,68 +250,71 @@ def time_sync():
|
|
250
250
|
|
251
251
|
|
252
252
|
def fuse_conv_and_bn(conv, bn):
|
253
|
-
"""
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
groups=conv.groups,
|
263
|
-
bias=True,
|
264
|
-
)
|
265
|
-
.requires_grad_(False)
|
266
|
-
.to(conv.weight.device)
|
267
|
-
)
|
253
|
+
"""
|
254
|
+
Fuse Conv2d and BatchNorm2d layers for inference optimization.
|
255
|
+
|
256
|
+
Args:
|
257
|
+
conv (nn.Conv2d): Convolutional layer to fuse.
|
258
|
+
bn (nn.BatchNorm2d): Batch normalization layer to fuse.
|
259
|
+
|
260
|
+
Returns:
|
261
|
+
(nn.Conv2d): The fused convolutional layer with gradients disabled.
|
268
262
|
|
269
|
-
|
263
|
+
Example:
|
264
|
+
>>> conv = nn.Conv2d(3, 16, 3)
|
265
|
+
>>> bn = nn.BatchNorm2d(16)
|
266
|
+
>>> fused_conv = fuse_conv_and_bn(conv, bn)
|
267
|
+
"""
|
268
|
+
# Compute fused weights
|
270
269
|
w_conv = conv.weight.view(conv.out_channels, -1)
|
271
270
|
w_bn = torch.diag(bn.weight.div(torch.sqrt(bn.eps + bn.running_var)))
|
272
|
-
|
271
|
+
conv.weight.data = torch.mm(w_bn, w_conv).view(conv.weight.shape)
|
273
272
|
|
274
|
-
#
|
275
|
-
b_conv = (
|
276
|
-
torch.zeros(conv.weight.shape[0], dtype=conv.weight.dtype, device=conv.weight.device)
|
277
|
-
if conv.bias is None
|
278
|
-
else conv.bias
|
279
|
-
)
|
273
|
+
# Compute fused bias
|
274
|
+
b_conv = torch.zeros(conv.out_channels, device=conv.weight.device) if conv.bias is None else conv.bias
|
280
275
|
b_bn = bn.bias - bn.weight.mul(bn.running_mean).div(torch.sqrt(bn.running_var + bn.eps))
|
281
|
-
|
276
|
+
fused_bias = torch.mm(w_bn, b_conv.reshape(-1, 1)).reshape(-1) + b_bn
|
277
|
+
|
278
|
+
if conv.bias is None:
|
279
|
+
conv.register_parameter("bias", nn.Parameter(fused_bias))
|
280
|
+
else:
|
281
|
+
conv.bias.data = fused_bias
|
282
282
|
|
283
|
-
return
|
283
|
+
return conv.requires_grad_(False)
|
284
284
|
|
285
285
|
|
286
286
|
def fuse_deconv_and_bn(deconv, bn):
|
287
|
-
"""
|
288
|
-
|
289
|
-
nn.ConvTranspose2d(
|
290
|
-
deconv.in_channels,
|
291
|
-
deconv.out_channels,
|
292
|
-
kernel_size=deconv.kernel_size,
|
293
|
-
stride=deconv.stride,
|
294
|
-
padding=deconv.padding,
|
295
|
-
output_padding=deconv.output_padding,
|
296
|
-
dilation=deconv.dilation,
|
297
|
-
groups=deconv.groups,
|
298
|
-
bias=True,
|
299
|
-
)
|
300
|
-
.requires_grad_(False)
|
301
|
-
.to(deconv.weight.device)
|
302
|
-
)
|
287
|
+
"""
|
288
|
+
Fuse ConvTranspose2d and BatchNorm2d layers for inference optimization.
|
303
289
|
|
304
|
-
|
290
|
+
Args:
|
291
|
+
deconv (nn.ConvTranspose2d): Transposed convolutional layer to fuse.
|
292
|
+
bn (nn.BatchNorm2d): Batch normalization layer to fuse.
|
293
|
+
|
294
|
+
Returns:
|
295
|
+
(nn.ConvTranspose2d): The fused transposed convolutional layer with gradients disabled.
|
296
|
+
|
297
|
+
Example:
|
298
|
+
>>> deconv = nn.ConvTranspose2d(16, 3, 3)
|
299
|
+
>>> bn = nn.BatchNorm2d(3)
|
300
|
+
>>> fused_deconv = fuse_deconv_and_bn(deconv, bn)
|
301
|
+
"""
|
302
|
+
# Compute fused weights
|
305
303
|
w_deconv = deconv.weight.view(deconv.out_channels, -1)
|
306
304
|
w_bn = torch.diag(bn.weight.div(torch.sqrt(bn.eps + bn.running_var)))
|
307
|
-
|
305
|
+
deconv.weight.data = torch.mm(w_bn, w_deconv).view(deconv.weight.shape)
|
308
306
|
|
309
|
-
#
|
310
|
-
b_conv = torch.zeros(deconv.
|
307
|
+
# Compute fused bias
|
308
|
+
b_conv = torch.zeros(deconv.out_channels, device=deconv.weight.device) if deconv.bias is None else deconv.bias
|
311
309
|
b_bn = bn.bias - bn.weight.mul(bn.running_mean).div(torch.sqrt(bn.running_var + bn.eps))
|
312
|
-
|
310
|
+
fused_bias = torch.mm(w_bn, b_conv.reshape(-1, 1)).reshape(-1) + b_bn
|
311
|
+
|
312
|
+
if deconv.bias is None:
|
313
|
+
deconv.register_parameter("bias", nn.Parameter(fused_bias))
|
314
|
+
else:
|
315
|
+
deconv.bias.data = fused_bias
|
313
316
|
|
314
|
-
return
|
317
|
+
return deconv.requires_grad_(False)
|
315
318
|
|
316
319
|
|
317
320
|
def model_info(model, detailed=False, verbose=True, imgsz=640):
|
ultralytics/utils/tqdm.py
CHANGED
@@ -10,7 +10,7 @@ from typing import IO, Any
|
|
10
10
|
|
11
11
|
|
12
12
|
@lru_cache(maxsize=1)
|
13
|
-
def is_noninteractive_console():
|
13
|
+
def is_noninteractive_console() -> bool:
|
14
14
|
"""Check for known non-interactive console environments."""
|
15
15
|
return "GITHUB_ACTIONS" in os.environ or "RUNPOD_POD_ID" in os.environ
|
16
16
|
|
@@ -128,7 +128,7 @@ class TQDM:
|
|
128
128
|
|
129
129
|
self.iterable = iterable
|
130
130
|
self.desc = desc or ""
|
131
|
-
self.total = total
|
131
|
+
self.total = total or (len(iterable) if hasattr(iterable, "__len__") else None) or None # prevent total=0
|
132
132
|
self.disable = disable
|
133
133
|
self.unit = unit
|
134
134
|
self.unit_scale = unit_scale
|
@@ -158,7 +158,7 @@ class TQDM:
|
|
158
158
|
if not self.disable and self.total is not None and not self.noninteractive:
|
159
159
|
self._display()
|
160
160
|
|
161
|
-
def _format_rate(self, rate):
|
161
|
+
def _format_rate(self, rate: float) -> str:
|
162
162
|
"""Format rate with proper units and reasonable precision."""
|
163
163
|
if rate <= 0:
|
164
164
|
return ""
|
@@ -180,7 +180,7 @@ class TQDM:
|
|
180
180
|
precision = ".1f" if rate >= 1 else ".2f"
|
181
181
|
return f"{rate:{precision}}{self.unit}/s"
|
182
182
|
|
183
|
-
def _format_num(self, num):
|
183
|
+
def _format_num(self, num: int) -> str:
|
184
184
|
"""Format number with optional unit scaling."""
|
185
185
|
if not self.unit_scale or self.unit not in ("B", "bytes"):
|
186
186
|
return str(num)
|
@@ -191,7 +191,7 @@ class TQDM:
|
|
191
191
|
num /= self.unit_divisor
|
192
192
|
return f"{num:.1f}PB"
|
193
193
|
|
194
|
-
def _format_time(self, seconds):
|
194
|
+
def _format_time(self, seconds: float) -> str:
|
195
195
|
"""Format time duration."""
|
196
196
|
if seconds < 60:
|
197
197
|
return f"{seconds:.1f}s"
|
@@ -201,7 +201,7 @@ class TQDM:
|
|
201
201
|
h, m = int(seconds // 3600), int((seconds % 3600) // 60)
|
202
202
|
return f"{h}:{m:02d}:{seconds % 60:02.0f}"
|
203
203
|
|
204
|
-
def _generate_bar(self, width=12):
|
204
|
+
def _generate_bar(self, width: int = 12) -> str:
|
205
205
|
"""Generate progress bar."""
|
206
206
|
if self.total is None:
|
207
207
|
return "━" * width if self.closed else "─" * width
|
@@ -213,7 +213,7 @@ class TQDM:
|
|
213
213
|
bar = bar[:filled] + "╸" + bar[filled + 1 :]
|
214
214
|
return bar
|
215
215
|
|
216
|
-
def _should_update(self, dt, dn):
|
216
|
+
def _should_update(self, dt: float, dn: int) -> bool:
|
217
217
|
"""Check if display should update."""
|
218
218
|
if self.noninteractive:
|
219
219
|
return False
|
@@ -223,7 +223,7 @@ class TQDM:
|
|
223
223
|
|
224
224
|
return dt >= self.mininterval
|
225
225
|
|
226
|
-
def _display(self, final=False):
|
226
|
+
def _display(self, final: bool = False) -> None:
|
227
227
|
"""Display progress bar."""
|
228
228
|
if self.disable or (self.closed and not final):
|
229
229
|
return
|
@@ -296,26 +296,26 @@ class TQDM:
|
|
296
296
|
except Exception:
|
297
297
|
pass
|
298
298
|
|
299
|
-
def update(self, n=1):
|
299
|
+
def update(self, n: int = 1) -> None:
|
300
300
|
"""Update progress by n steps."""
|
301
301
|
if not self.disable and not self.closed:
|
302
302
|
self.n += n
|
303
303
|
self._display()
|
304
304
|
|
305
|
-
def set_description(self, desc):
|
305
|
+
def set_description(self, desc: str | None) -> None:
|
306
306
|
"""Set description."""
|
307
307
|
self.desc = desc or ""
|
308
308
|
if not self.disable:
|
309
309
|
self._display()
|
310
310
|
|
311
|
-
def set_postfix(self, **kwargs):
|
311
|
+
def set_postfix(self, **kwargs: Any) -> None:
|
312
312
|
"""Set postfix (appends to description)."""
|
313
313
|
if kwargs:
|
314
314
|
postfix = ", ".join(f"{k}={v}" for k, v in kwargs.items())
|
315
315
|
base_desc = self.desc.split(" | ")[0] if " | " in self.desc else self.desc
|
316
316
|
self.set_description(f"{base_desc} | {postfix}")
|
317
317
|
|
318
|
-
def close(self):
|
318
|
+
def close(self) -> None:
|
319
319
|
"""Close progress bar."""
|
320
320
|
if self.closed:
|
321
321
|
return
|
@@ -339,15 +339,15 @@ class TQDM:
|
|
339
339
|
except Exception:
|
340
340
|
pass
|
341
341
|
|
342
|
-
def __enter__(self):
|
342
|
+
def __enter__(self) -> TQDM:
|
343
343
|
"""Enter context manager."""
|
344
344
|
return self
|
345
345
|
|
346
|
-
def __exit__(self, *args):
|
346
|
+
def __exit__(self, *args: Any) -> None:
|
347
347
|
"""Exit context manager and close progress bar."""
|
348
348
|
self.close()
|
349
349
|
|
350
|
-
def __iter__(self):
|
350
|
+
def __iter__(self) -> Any:
|
351
351
|
"""Iterate over the wrapped iterable with progress updates."""
|
352
352
|
if self.iterable is None:
|
353
353
|
raise TypeError("'NoneType' object is not iterable")
|
@@ -359,19 +359,19 @@ class TQDM:
|
|
359
359
|
finally:
|
360
360
|
self.close()
|
361
361
|
|
362
|
-
def __del__(self):
|
362
|
+
def __del__(self) -> None:
|
363
363
|
"""Destructor to ensure cleanup."""
|
364
364
|
try:
|
365
365
|
self.close()
|
366
366
|
except Exception:
|
367
367
|
pass
|
368
368
|
|
369
|
-
def refresh(self):
|
369
|
+
def refresh(self) -> None:
|
370
370
|
"""Refresh display."""
|
371
371
|
if not self.disable:
|
372
372
|
self._display()
|
373
373
|
|
374
|
-
def clear(self):
|
374
|
+
def clear(self) -> None:
|
375
375
|
"""Clear progress bar."""
|
376
376
|
if not self.disable:
|
377
377
|
try:
|
@@ -381,7 +381,7 @@ class TQDM:
|
|
381
381
|
pass
|
382
382
|
|
383
383
|
@staticmethod
|
384
|
-
def write(s, file=None, end="\n"):
|
384
|
+
def write(s: str, file: IO[str] | None = None, end: str = "\n") -> None:
|
385
385
|
"""Static method to write without breaking progress bar."""
|
386
386
|
file = file or sys.stdout
|
387
387
|
try:
|
@@ -394,14 +394,11 @@ class TQDM:
|
|
394
394
|
if __name__ == "__main__":
|
395
395
|
import time
|
396
396
|
|
397
|
-
# Example 1: Basic usage with known total
|
398
397
|
print("1. Basic progress bar with known total:")
|
399
|
-
for i in TQDM(range(
|
398
|
+
for i in TQDM(range(0), desc="Known total"):
|
400
399
|
time.sleep(0.05)
|
401
|
-
print()
|
402
400
|
|
403
|
-
|
404
|
-
print("2. Manual updates with known total:")
|
401
|
+
print("\n2. Manual updates with known total:")
|
405
402
|
pbar = TQDM(total=30, desc="Manual updates", unit="files")
|
406
403
|
for i in range(30):
|
407
404
|
time.sleep(0.03)
|
@@ -409,10 +406,8 @@ if __name__ == "__main__":
|
|
409
406
|
if i % 10 == 9:
|
410
407
|
pbar.set_description(f"Processing batch {i // 10 + 1}")
|
411
408
|
pbar.close()
|
412
|
-
print()
|
413
409
|
|
414
|
-
|
415
|
-
print("3. Progress bar with unknown total:")
|
410
|
+
print("\n3. Progress bar with unknown total:")
|
416
411
|
pbar = TQDM(desc="Unknown total", unit="items")
|
417
412
|
for i in range(25):
|
418
413
|
time.sleep(0.08)
|
@@ -420,18 +415,14 @@ if __name__ == "__main__":
|
|
420
415
|
if i % 5 == 4:
|
421
416
|
pbar.set_postfix(processed=i + 1, status="OK")
|
422
417
|
pbar.close()
|
423
|
-
print()
|
424
418
|
|
425
|
-
|
426
|
-
print("4. Context manager with unknown total:")
|
419
|
+
print("\n4. Context manager with unknown total:")
|
427
420
|
with TQDM(desc="Processing stream", unit="B", unit_scale=True, unit_divisor=1024) as pbar:
|
428
421
|
for i in range(30):
|
429
422
|
time.sleep(0.1)
|
430
423
|
pbar.update(1024 * 1024 * i) # Simulate processing MB of data
|
431
|
-
print()
|
432
424
|
|
433
|
-
|
434
|
-
print("5. Iterator with unknown length:")
|
425
|
+
print("\n5. Iterator with unknown length:")
|
435
426
|
|
436
427
|
def data_stream():
|
437
428
|
"""Simulate a data stream of unknown length."""
|
@@ -442,10 +433,8 @@ if __name__ == "__main__":
|
|
442
433
|
|
443
434
|
for chunk in TQDM(data_stream(), desc="Stream processing", unit="chunks"):
|
444
435
|
time.sleep(0.1)
|
445
|
-
print()
|
446
436
|
|
447
|
-
|
448
|
-
print("6. File processing simulation (unknown size):")
|
437
|
+
print("\n6. File processing simulation (unknown size):")
|
449
438
|
|
450
439
|
def process_files():
|
451
440
|
"""Simulate processing files of unknown count."""
|
@@ -459,4 +448,3 @@ if __name__ == "__main__":
|
|
459
448
|
pbar.update(1)
|
460
449
|
pbar.set_description(f"Processing {filename}")
|
461
450
|
pbar.close()
|
462
|
-
print()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|