ultralytics 8.1.29__py3-none-any.whl → 8.3.63__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.
- tests/__init__.py +22 -0
- tests/conftest.py +83 -0
- tests/test_cli.py +122 -0
- tests/test_cuda.py +155 -0
- tests/test_engine.py +131 -0
- tests/test_exports.py +216 -0
- tests/test_integrations.py +150 -0
- tests/test_python.py +615 -0
- tests/test_solutions.py +94 -0
- ultralytics/__init__.py +11 -8
- ultralytics/cfg/__init__.py +569 -131
- ultralytics/cfg/datasets/Argoverse.yaml +2 -1
- ultralytics/cfg/datasets/DOTAv1.5.yaml +3 -2
- ultralytics/cfg/datasets/DOTAv1.yaml +3 -2
- ultralytics/cfg/datasets/GlobalWheat2020.yaml +3 -2
- ultralytics/cfg/datasets/ImageNet.yaml +2 -1
- ultralytics/cfg/datasets/Objects365.yaml +5 -4
- ultralytics/cfg/datasets/SKU-110K.yaml +2 -1
- ultralytics/cfg/datasets/VOC.yaml +3 -2
- ultralytics/cfg/datasets/VisDrone.yaml +6 -5
- ultralytics/cfg/datasets/african-wildlife.yaml +25 -0
- ultralytics/cfg/datasets/brain-tumor.yaml +23 -0
- ultralytics/cfg/datasets/carparts-seg.yaml +3 -2
- ultralytics/cfg/datasets/coco-pose.yaml +7 -6
- ultralytics/cfg/datasets/coco.yaml +3 -2
- ultralytics/cfg/datasets/coco128-seg.yaml +4 -3
- ultralytics/cfg/datasets/coco128.yaml +4 -3
- ultralytics/cfg/datasets/coco8-pose.yaml +3 -2
- ultralytics/cfg/datasets/coco8-seg.yaml +3 -2
- ultralytics/cfg/datasets/coco8.yaml +3 -2
- ultralytics/cfg/datasets/crack-seg.yaml +3 -2
- ultralytics/cfg/datasets/dog-pose.yaml +24 -0
- ultralytics/cfg/datasets/dota8.yaml +3 -2
- ultralytics/cfg/datasets/hand-keypoints.yaml +26 -0
- ultralytics/cfg/datasets/lvis.yaml +1236 -0
- ultralytics/cfg/datasets/medical-pills.yaml +22 -0
- ultralytics/cfg/datasets/open-images-v7.yaml +2 -1
- ultralytics/cfg/datasets/package-seg.yaml +5 -4
- ultralytics/cfg/datasets/signature.yaml +21 -0
- ultralytics/cfg/datasets/tiger-pose.yaml +3 -2
- ultralytics/cfg/datasets/xView.yaml +2 -1
- ultralytics/cfg/default.yaml +14 -11
- ultralytics/cfg/models/11/yolo11-cls-resnet18.yaml +24 -0
- ultralytics/cfg/models/11/yolo11-cls.yaml +33 -0
- ultralytics/cfg/models/11/yolo11-obb.yaml +50 -0
- ultralytics/cfg/models/11/yolo11-pose.yaml +51 -0
- ultralytics/cfg/models/11/yolo11-seg.yaml +50 -0
- ultralytics/cfg/models/11/yolo11.yaml +50 -0
- ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +5 -2
- ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +5 -2
- ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +5 -2
- ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +5 -2
- ultralytics/cfg/models/v10/yolov10b.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10l.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10m.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10n.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10s.yaml +45 -0
- ultralytics/cfg/models/v10/yolov10x.yaml +45 -0
- ultralytics/cfg/models/v3/yolov3-spp.yaml +5 -2
- ultralytics/cfg/models/v3/yolov3-tiny.yaml +5 -2
- ultralytics/cfg/models/v3/yolov3.yaml +5 -2
- ultralytics/cfg/models/v5/yolov5-p6.yaml +5 -2
- ultralytics/cfg/models/v5/yolov5.yaml +5 -2
- ultralytics/cfg/models/v6/yolov6.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-cls.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +6 -2
- ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +6 -2
- ultralytics/cfg/models/v8/yolov8-ghost.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-obb.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-p2.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-p6.yaml +10 -7
- ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-pose.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-seg.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-world.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8-worldv2.yaml +5 -2
- ultralytics/cfg/models/v8/yolov8.yaml +5 -2
- ultralytics/cfg/models/v9/yolov9c-seg.yaml +41 -0
- ultralytics/cfg/models/v9/yolov9c.yaml +30 -25
- ultralytics/cfg/models/v9/yolov9e-seg.yaml +64 -0
- ultralytics/cfg/models/v9/yolov9e.yaml +46 -42
- ultralytics/cfg/models/v9/yolov9m.yaml +41 -0
- ultralytics/cfg/models/v9/yolov9s.yaml +41 -0
- ultralytics/cfg/models/v9/yolov9t.yaml +41 -0
- ultralytics/cfg/solutions/default.yaml +24 -0
- ultralytics/cfg/trackers/botsort.yaml +8 -5
- ultralytics/cfg/trackers/bytetrack.yaml +8 -5
- ultralytics/data/__init__.py +14 -3
- ultralytics/data/annotator.py +37 -15
- ultralytics/data/augment.py +1783 -289
- ultralytics/data/base.py +62 -27
- ultralytics/data/build.py +37 -8
- ultralytics/data/converter.py +196 -36
- ultralytics/data/dataset.py +233 -94
- ultralytics/data/loaders.py +199 -96
- ultralytics/data/split_dota.py +39 -29
- ultralytics/data/utils.py +111 -41
- ultralytics/engine/__init__.py +1 -1
- ultralytics/engine/exporter.py +579 -244
- ultralytics/engine/model.py +604 -252
- ultralytics/engine/predictor.py +22 -11
- ultralytics/engine/results.py +1228 -218
- ultralytics/engine/trainer.py +191 -129
- ultralytics/engine/tuner.py +18 -18
- ultralytics/engine/validator.py +18 -15
- ultralytics/hub/__init__.py +31 -13
- ultralytics/hub/auth.py +11 -7
- ultralytics/hub/google/__init__.py +159 -0
- ultralytics/hub/session.py +128 -94
- ultralytics/hub/utils.py +20 -21
- ultralytics/models/__init__.py +4 -2
- ultralytics/models/fastsam/__init__.py +2 -3
- ultralytics/models/fastsam/model.py +26 -4
- ultralytics/models/fastsam/predict.py +127 -63
- ultralytics/models/fastsam/utils.py +1 -44
- ultralytics/models/fastsam/val.py +1 -1
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/nas/model.py +21 -10
- ultralytics/models/nas/predict.py +3 -6
- ultralytics/models/nas/val.py +4 -4
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/rtdetr/model.py +1 -1
- ultralytics/models/rtdetr/predict.py +6 -8
- ultralytics/models/rtdetr/train.py +6 -2
- ultralytics/models/rtdetr/val.py +3 -3
- ultralytics/models/sam/__init__.py +3 -3
- ultralytics/models/sam/amg.py +29 -23
- ultralytics/models/sam/build.py +211 -13
- ultralytics/models/sam/model.py +91 -30
- ultralytics/models/sam/modules/__init__.py +1 -1
- ultralytics/models/sam/modules/blocks.py +1129 -0
- ultralytics/models/sam/modules/decoders.py +381 -53
- ultralytics/models/sam/modules/encoders.py +515 -324
- ultralytics/models/sam/modules/memory_attention.py +237 -0
- ultralytics/models/sam/modules/sam.py +969 -21
- ultralytics/models/sam/modules/tiny_encoder.py +425 -154
- ultralytics/models/sam/modules/transformer.py +159 -60
- ultralytics/models/sam/modules/utils.py +293 -0
- ultralytics/models/sam/predict.py +1263 -132
- ultralytics/models/utils/__init__.py +1 -1
- ultralytics/models/utils/loss.py +36 -24
- ultralytics/models/utils/ops.py +3 -7
- ultralytics/models/yolo/__init__.py +3 -3
- ultralytics/models/yolo/classify/__init__.py +1 -1
- ultralytics/models/yolo/classify/predict.py +7 -8
- ultralytics/models/yolo/classify/train.py +17 -22
- ultralytics/models/yolo/classify/val.py +8 -4
- ultralytics/models/yolo/detect/__init__.py +1 -1
- ultralytics/models/yolo/detect/predict.py +3 -5
- ultralytics/models/yolo/detect/train.py +11 -4
- ultralytics/models/yolo/detect/val.py +90 -52
- ultralytics/models/yolo/model.py +14 -9
- ultralytics/models/yolo/obb/__init__.py +1 -1
- ultralytics/models/yolo/obb/predict.py +2 -2
- ultralytics/models/yolo/obb/train.py +5 -3
- ultralytics/models/yolo/obb/val.py +41 -23
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +3 -5
- ultralytics/models/yolo/pose/train.py +2 -2
- ultralytics/models/yolo/pose/val.py +51 -17
- ultralytics/models/yolo/segment/__init__.py +1 -1
- ultralytics/models/yolo/segment/predict.py +3 -5
- ultralytics/models/yolo/segment/train.py +2 -2
- ultralytics/models/yolo/segment/val.py +60 -19
- ultralytics/models/yolo/world/__init__.py +5 -0
- ultralytics/models/yolo/world/train.py +92 -0
- ultralytics/models/yolo/world/train_world.py +109 -0
- ultralytics/nn/__init__.py +1 -1
- ultralytics/nn/autobackend.py +228 -93
- ultralytics/nn/modules/__init__.py +39 -14
- ultralytics/nn/modules/activation.py +21 -0
- ultralytics/nn/modules/block.py +526 -66
- ultralytics/nn/modules/conv.py +24 -7
- ultralytics/nn/modules/head.py +177 -34
- ultralytics/nn/modules/transformer.py +6 -5
- ultralytics/nn/modules/utils.py +1 -2
- ultralytics/nn/tasks.py +226 -82
- ultralytics/solutions/__init__.py +30 -1
- ultralytics/solutions/ai_gym.py +96 -143
- ultralytics/solutions/analytics.py +247 -0
- ultralytics/solutions/distance_calculation.py +78 -135
- ultralytics/solutions/heatmap.py +93 -247
- ultralytics/solutions/object_counter.py +184 -259
- ultralytics/solutions/parking_management.py +246 -0
- ultralytics/solutions/queue_management.py +112 -0
- ultralytics/solutions/region_counter.py +116 -0
- ultralytics/solutions/security_alarm.py +144 -0
- ultralytics/solutions/solutions.py +178 -0
- ultralytics/solutions/speed_estimation.py +86 -174
- ultralytics/solutions/streamlit_inference.py +190 -0
- ultralytics/solutions/trackzone.py +68 -0
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/basetrack.py +32 -13
- ultralytics/trackers/bot_sort.py +61 -28
- ultralytics/trackers/byte_tracker.py +83 -51
- ultralytics/trackers/track.py +21 -6
- ultralytics/trackers/utils/__init__.py +1 -1
- ultralytics/trackers/utils/gmc.py +62 -48
- ultralytics/trackers/utils/kalman_filter.py +166 -35
- ultralytics/trackers/utils/matching.py +40 -21
- ultralytics/utils/__init__.py +511 -239
- ultralytics/utils/autobatch.py +40 -22
- ultralytics/utils/benchmarks.py +266 -85
- ultralytics/utils/callbacks/__init__.py +1 -1
- ultralytics/utils/callbacks/base.py +1 -3
- ultralytics/utils/callbacks/clearml.py +7 -6
- ultralytics/utils/callbacks/comet.py +39 -17
- ultralytics/utils/callbacks/dvc.py +1 -1
- ultralytics/utils/callbacks/hub.py +16 -16
- ultralytics/utils/callbacks/mlflow.py +28 -24
- ultralytics/utils/callbacks/neptune.py +6 -2
- ultralytics/utils/callbacks/raytune.py +3 -4
- ultralytics/utils/callbacks/tensorboard.py +18 -18
- ultralytics/utils/callbacks/wb.py +27 -20
- ultralytics/utils/checks.py +172 -100
- ultralytics/utils/dist.py +2 -1
- ultralytics/utils/downloads.py +40 -34
- ultralytics/utils/errors.py +1 -1
- ultralytics/utils/files.py +72 -38
- ultralytics/utils/instance.py +41 -19
- ultralytics/utils/loss.py +83 -55
- ultralytics/utils/metrics.py +61 -56
- ultralytics/utils/ops.py +94 -89
- ultralytics/utils/patches.py +30 -14
- ultralytics/utils/plotting.py +600 -269
- ultralytics/utils/tal.py +67 -26
- ultralytics/utils/torch_utils.py +305 -112
- ultralytics/utils/triton.py +2 -1
- ultralytics/utils/tuner.py +21 -12
- ultralytics-8.3.63.dist-info/METADATA +370 -0
- ultralytics-8.3.63.dist-info/RECORD +241 -0
- {ultralytics-8.1.29.dist-info → ultralytics-8.3.63.dist-info}/WHEEL +1 -1
- ultralytics/data/explorer/__init__.py +0 -5
- ultralytics/data/explorer/explorer.py +0 -472
- ultralytics/data/explorer/gui/__init__.py +0 -1
- ultralytics/data/explorer/gui/dash.py +0 -268
- ultralytics/data/explorer/utils.py +0 -166
- ultralytics/models/fastsam/prompt.py +0 -357
- ultralytics-8.1.29.dist-info/METADATA +0 -373
- ultralytics-8.1.29.dist-info/RECORD +0 -197
- {ultralytics-8.1.29.dist-info → ultralytics-8.3.63.dist-info}/LICENSE +0 -0
- {ultralytics-8.1.29.dist-info → ultralytics-8.3.63.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.1.29.dist-info → ultralytics-8.3.63.dist-info}/top_level.txt +0 -0
ultralytics/nn/autobackend.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
# Ultralytics
|
1
|
+
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
3
|
import ast
|
4
|
-
import contextlib
|
5
4
|
import json
|
6
5
|
import platform
|
7
6
|
import zipfile
|
@@ -14,7 +13,7 @@ import torch
|
|
14
13
|
import torch.nn as nn
|
15
14
|
from PIL import Image
|
16
15
|
|
17
|
-
from ultralytics.utils import ARM64, LINUX, LOGGER, ROOT, yaml_load
|
16
|
+
from ultralytics.utils import ARM64, IS_JETSON, IS_RASPBERRYPI, LINUX, LOGGER, ROOT, yaml_load
|
18
17
|
from ultralytics.utils.checks import check_requirements, check_suffix, check_version, check_yaml
|
19
18
|
from ultralytics.utils.downloads import attempt_download_asset, is_url
|
20
19
|
|
@@ -45,8 +44,10 @@ def check_class_names(names):
|
|
45
44
|
def default_class_names(data=None):
|
46
45
|
"""Applies default class names to an input YAML file or returns numerical class names."""
|
47
46
|
if data:
|
48
|
-
|
47
|
+
try:
|
49
48
|
return yaml_load(check_yaml(data))["names"]
|
49
|
+
except Exception:
|
50
|
+
pass
|
50
51
|
return {i: f"class{i}" for i in range(999)} # return default if above errors
|
51
52
|
|
52
53
|
|
@@ -58,21 +59,22 @@ class AutoBackend(nn.Module):
|
|
58
59
|
range of formats, each with specific naming conventions as outlined below:
|
59
60
|
|
60
61
|
Supported Formats and Naming Conventions:
|
61
|
-
| Format | File Suffix
|
62
|
-
|
63
|
-
| PyTorch | *.pt
|
64
|
-
| TorchScript | *.torchscript
|
65
|
-
| ONNX Runtime | *.onnx
|
66
|
-
| ONNX OpenCV DNN | *.onnx (dnn=True)|
|
67
|
-
| OpenVINO | *openvino_model/
|
68
|
-
| CoreML | *.mlpackage
|
69
|
-
| TensorRT | *.engine
|
70
|
-
| TensorFlow SavedModel | *_saved_model |
|
71
|
-
| TensorFlow GraphDef | *.pb
|
72
|
-
| TensorFlow Lite | *.tflite
|
73
|
-
| TensorFlow Edge TPU | *_edgetpu.tflite
|
74
|
-
| PaddlePaddle | *_paddle_model |
|
75
|
-
|
|
62
|
+
| Format | File Suffix |
|
63
|
+
|-----------------------|-------------------|
|
64
|
+
| PyTorch | *.pt |
|
65
|
+
| TorchScript | *.torchscript |
|
66
|
+
| ONNX Runtime | *.onnx |
|
67
|
+
| ONNX OpenCV DNN | *.onnx (dnn=True) |
|
68
|
+
| OpenVINO | *openvino_model/ |
|
69
|
+
| CoreML | *.mlpackage |
|
70
|
+
| TensorRT | *.engine |
|
71
|
+
| TensorFlow SavedModel | *_saved_model/ |
|
72
|
+
| TensorFlow GraphDef | *.pb |
|
73
|
+
| TensorFlow Lite | *.tflite |
|
74
|
+
| TensorFlow Edge TPU | *_edgetpu.tflite |
|
75
|
+
| PaddlePaddle | *_paddle_model/ |
|
76
|
+
| MNN | *.mnn |
|
77
|
+
| NCNN | *_ncnn_model/ |
|
76
78
|
|
77
79
|
This class offers dynamic backend switching capabilities based on the input model format, making it easier to deploy
|
78
80
|
models across various platforms.
|
@@ -81,7 +83,7 @@ class AutoBackend(nn.Module):
|
|
81
83
|
@torch.no_grad()
|
82
84
|
def __init__(
|
83
85
|
self,
|
84
|
-
weights="
|
86
|
+
weights="yolo11n.pt",
|
85
87
|
device=torch.device("cpu"),
|
86
88
|
dnn=False,
|
87
89
|
data=None,
|
@@ -94,7 +96,7 @@ class AutoBackend(nn.Module):
|
|
94
96
|
Initialize the AutoBackend for inference.
|
95
97
|
|
96
98
|
Args:
|
97
|
-
weights (str): Path to the model weights file. Defaults to '
|
99
|
+
weights (str | torch.nn.Module): Path to the model weights file or a module instance. Defaults to 'yolo11n.pt'.
|
98
100
|
device (torch.device): Device to run the model on. Defaults to CPU.
|
99
101
|
dnn (bool): Use OpenCV DNN module for ONNX inference. Defaults to False.
|
100
102
|
data (str | Path | optional): Path to the additional data.yaml file containing class names. Optional.
|
@@ -119,17 +121,19 @@ class AutoBackend(nn.Module):
|
|
119
121
|
edgetpu,
|
120
122
|
tfjs,
|
121
123
|
paddle,
|
124
|
+
mnn,
|
122
125
|
ncnn,
|
126
|
+
imx,
|
123
127
|
triton,
|
124
128
|
) = self._model_type(w)
|
125
129
|
fp16 &= pt or jit or onnx or xml or engine or nn_module or triton # FP16
|
126
130
|
nhwc = coreml or saved_model or pb or tflite or edgetpu # BHWC formats (vs torch BCWH)
|
127
131
|
stride = 32 # default stride
|
128
|
-
model, metadata = None, None
|
132
|
+
model, metadata, task = None, None, None
|
129
133
|
|
130
134
|
# Set device
|
131
135
|
cuda = torch.cuda.is_available() and device.type != "cpu" # use CUDA
|
132
|
-
if cuda and not any([nn_module, pt, jit, engine, onnx]): # GPU dataloader formats
|
136
|
+
if cuda and not any([nn_module, pt, jit, engine, onnx, paddle]): # GPU dataloader formats
|
133
137
|
device = torch.device("cpu")
|
134
138
|
cuda = False
|
135
139
|
|
@@ -140,7 +144,8 @@ class AutoBackend(nn.Module):
|
|
140
144
|
# In-memory PyTorch model
|
141
145
|
if nn_module:
|
142
146
|
model = weights.to(device)
|
143
|
-
|
147
|
+
if fuse:
|
148
|
+
model = model.fuse(verbose=verbose)
|
144
149
|
if hasattr(model, "kpt_shape"):
|
145
150
|
kpt_shape = model.kpt_shape # pose-only
|
146
151
|
stride = max(int(model.stride.max()), 32) # model stride
|
@@ -178,16 +183,56 @@ class AutoBackend(nn.Module):
|
|
178
183
|
check_requirements("opencv-python>=4.5.4")
|
179
184
|
net = cv2.dnn.readNetFromONNX(w)
|
180
185
|
|
181
|
-
# ONNX Runtime
|
182
|
-
elif onnx:
|
186
|
+
# ONNX Runtime and IMX
|
187
|
+
elif onnx or imx:
|
183
188
|
LOGGER.info(f"Loading {w} for ONNX Runtime inference...")
|
184
189
|
check_requirements(("onnx", "onnxruntime-gpu" if cuda else "onnxruntime"))
|
190
|
+
if IS_RASPBERRYPI or IS_JETSON:
|
191
|
+
# Fix 'numpy.linalg._umath_linalg' has no attribute '_ilp64' for TF SavedModel on RPi and Jetson
|
192
|
+
check_requirements("numpy==1.23.5")
|
185
193
|
import onnxruntime
|
186
194
|
|
187
|
-
providers = ["
|
188
|
-
|
195
|
+
providers = ["CPUExecutionProvider"]
|
196
|
+
if cuda and "CUDAExecutionProvider" in onnxruntime.get_available_providers():
|
197
|
+
providers.insert(0, "CUDAExecutionProvider")
|
198
|
+
elif cuda: # Only log warning if CUDA was requested but unavailable
|
199
|
+
LOGGER.warning("WARNING ⚠️ Failed to start ONNX Runtime with CUDA. Using CPU...")
|
200
|
+
device = torch.device("cpu")
|
201
|
+
cuda = False
|
202
|
+
LOGGER.info(f"Using ONNX Runtime {providers[0]}")
|
203
|
+
if onnx:
|
204
|
+
session = onnxruntime.InferenceSession(w, providers=providers)
|
205
|
+
else:
|
206
|
+
check_requirements(
|
207
|
+
["model-compression-toolkit==2.1.1", "sony-custom-layers[torch]==0.2.0", "onnxruntime-extensions"]
|
208
|
+
)
|
209
|
+
w = next(Path(w).glob("*.onnx"))
|
210
|
+
LOGGER.info(f"Loading {w} for ONNX IMX inference...")
|
211
|
+
import mct_quantizers as mctq
|
212
|
+
from sony_custom_layers.pytorch.object_detection import nms_ort # noqa
|
213
|
+
|
214
|
+
session = onnxruntime.InferenceSession(
|
215
|
+
w, mctq.get_ort_session_options(), providers=["CPUExecutionProvider"]
|
216
|
+
)
|
217
|
+
task = "detect"
|
218
|
+
|
189
219
|
output_names = [x.name for x in session.get_outputs()]
|
190
220
|
metadata = session.get_modelmeta().custom_metadata_map
|
221
|
+
dynamic = isinstance(session.get_outputs()[0].shape[0], str)
|
222
|
+
if not dynamic:
|
223
|
+
io = session.io_binding()
|
224
|
+
bindings = []
|
225
|
+
for output in session.get_outputs():
|
226
|
+
y_tensor = torch.empty(output.shape, dtype=torch.float16 if fp16 else torch.float32).to(device)
|
227
|
+
io.bind_output(
|
228
|
+
name=output.name,
|
229
|
+
device_type=device.type,
|
230
|
+
device_id=device.index if cuda else 0,
|
231
|
+
element_type=np.float16 if fp16 else np.float32,
|
232
|
+
shape=tuple(y_tensor.shape),
|
233
|
+
buffer_ptr=y_tensor.data_ptr(),
|
234
|
+
)
|
235
|
+
bindings.append(y_tensor)
|
191
236
|
|
192
237
|
# OpenVINO
|
193
238
|
elif xml:
|
@@ -202,13 +247,10 @@ class AutoBackend(nn.Module):
|
|
202
247
|
ov_model = core.read_model(model=str(w), weights=w.with_suffix(".bin"))
|
203
248
|
if ov_model.get_parameters()[0].get_layout().empty:
|
204
249
|
ov_model.get_parameters()[0].set_layout(ov.Layout("NCHW"))
|
205
|
-
batch_dim = ov.get_batch(ov_model)
|
206
|
-
if batch_dim.is_static:
|
207
|
-
batch_size = batch_dim.get_length()
|
208
250
|
|
209
251
|
# OpenVINO inference modes are 'LATENCY', 'THROUGHPUT' (not recommended), or 'CUMULATIVE_THROUGHPUT'
|
210
252
|
inference_mode = "CUMULATIVE_THROUGHPUT" if batch > 1 else "LATENCY"
|
211
|
-
LOGGER.info(f"Using OpenVINO {inference_mode} mode for batch
|
253
|
+
LOGGER.info(f"Using OpenVINO {inference_mode} mode for batch={batch} inference...")
|
212
254
|
ov_compiled_model = core.compile_model(
|
213
255
|
ov_model,
|
214
256
|
device_name="AUTO", # AUTO selects best available device, do not modify
|
@@ -224,35 +266,63 @@ class AutoBackend(nn.Module):
|
|
224
266
|
import tensorrt as trt # noqa https://developer.nvidia.com/nvidia-tensorrt-download
|
225
267
|
except ImportError:
|
226
268
|
if LINUX:
|
227
|
-
check_requirements("
|
269
|
+
check_requirements("tensorrt>7.0.0,!=10.1.0")
|
228
270
|
import tensorrt as trt # noqa
|
229
|
-
check_version(trt.__version__, "7.0.0", hard=True)
|
271
|
+
check_version(trt.__version__, ">=7.0.0", hard=True)
|
272
|
+
check_version(trt.__version__, "!=10.1.0", msg="https://github.com/ultralytics/ultralytics/pull/14239")
|
230
273
|
if device.type == "cpu":
|
231
274
|
device = torch.device("cuda:0")
|
232
275
|
Binding = namedtuple("Binding", ("name", "dtype", "shape", "data", "ptr"))
|
233
276
|
logger = trt.Logger(trt.Logger.INFO)
|
234
277
|
# Read file
|
235
278
|
with open(w, "rb") as f, trt.Runtime(logger) as runtime:
|
236
|
-
|
237
|
-
|
279
|
+
try:
|
280
|
+
meta_len = int.from_bytes(f.read(4), byteorder="little") # read metadata length
|
281
|
+
metadata = json.loads(f.read(meta_len).decode("utf-8")) # read metadata
|
282
|
+
except UnicodeDecodeError:
|
283
|
+
f.seek(0) # engine file may lack embedded Ultralytics metadata
|
238
284
|
model = runtime.deserialize_cuda_engine(f.read()) # read engine
|
239
|
-
|
285
|
+
|
286
|
+
# Model context
|
287
|
+
try:
|
288
|
+
context = model.create_execution_context()
|
289
|
+
except Exception as e: # model is None
|
290
|
+
LOGGER.error(f"ERROR: TensorRT model exported with a different version than {trt.__version__}\n")
|
291
|
+
raise e
|
292
|
+
|
240
293
|
bindings = OrderedDict()
|
241
294
|
output_names = []
|
242
295
|
fp16 = False # default updated below
|
243
296
|
dynamic = False
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
if
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
if
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
297
|
+
is_trt10 = not hasattr(model, "num_bindings")
|
298
|
+
num = range(model.num_io_tensors) if is_trt10 else range(model.num_bindings)
|
299
|
+
for i in num:
|
300
|
+
if is_trt10:
|
301
|
+
name = model.get_tensor_name(i)
|
302
|
+
dtype = trt.nptype(model.get_tensor_dtype(name))
|
303
|
+
is_input = model.get_tensor_mode(name) == trt.TensorIOMode.INPUT
|
304
|
+
if is_input:
|
305
|
+
if -1 in tuple(model.get_tensor_shape(name)):
|
306
|
+
dynamic = True
|
307
|
+
context.set_input_shape(name, tuple(model.get_tensor_profile_shape(name, 0)[1]))
|
308
|
+
if dtype == np.float16:
|
309
|
+
fp16 = True
|
310
|
+
else:
|
311
|
+
output_names.append(name)
|
312
|
+
shape = tuple(context.get_tensor_shape(name))
|
313
|
+
else: # TensorRT < 10.0
|
314
|
+
name = model.get_binding_name(i)
|
315
|
+
dtype = trt.nptype(model.get_binding_dtype(i))
|
316
|
+
is_input = model.binding_is_input(i)
|
317
|
+
if model.binding_is_input(i):
|
318
|
+
if -1 in tuple(model.get_binding_shape(i)): # dynamic
|
319
|
+
dynamic = True
|
320
|
+
context.set_binding_shape(i, tuple(model.get_profile_shape(0, i)[1]))
|
321
|
+
if dtype == np.float16:
|
322
|
+
fp16 = True
|
323
|
+
else:
|
324
|
+
output_names.append(name)
|
325
|
+
shape = tuple(context.get_binding_shape(i))
|
256
326
|
im = torch.from_numpy(np.empty(shape, dtype=dtype)).to(device)
|
257
327
|
bindings[name] = Binding(name, dtype, shape, im, int(im.data_ptr()))
|
258
328
|
binding_addrs = OrderedDict((n, d.ptr) for n, d in bindings.items())
|
@@ -292,6 +362,10 @@ class AutoBackend(nn.Module):
|
|
292
362
|
with open(w, "rb") as f:
|
293
363
|
gd.ParseFromString(f.read())
|
294
364
|
frozen_func = wrap_frozen_graph(gd, inputs="x:0", outputs=gd_outputs(gd))
|
365
|
+
try: # find metadata in SavedModel alongside GraphDef
|
366
|
+
metadata = next(Path(w).resolve().parent.rglob(f"{Path(w).stem}_saved_model*/metadata.yaml"))
|
367
|
+
except StopIteration:
|
368
|
+
pass
|
295
369
|
|
296
370
|
# TFLite or TFLite Edge TPU
|
297
371
|
elif tflite or edgetpu: # https://www.tensorflow.org/lite/guide/python#install_tensorflow_lite_for_python
|
@@ -302,11 +376,16 @@ class AutoBackend(nn.Module):
|
|
302
376
|
|
303
377
|
Interpreter, load_delegate = tf.lite.Interpreter, tf.lite.experimental.load_delegate
|
304
378
|
if edgetpu: # TF Edge TPU https://coral.ai/software/#edgetpu-runtime
|
305
|
-
|
379
|
+
device = device[3:] if str(device).startswith("tpu") else ":0"
|
380
|
+
LOGGER.info(f"Loading {w} on device {device[1:]} for TensorFlow Lite Edge TPU inference...")
|
306
381
|
delegate = {"Linux": "libedgetpu.so.1", "Darwin": "libedgetpu.1.dylib", "Windows": "edgetpu.dll"}[
|
307
382
|
platform.system()
|
308
383
|
]
|
309
|
-
interpreter = Interpreter(
|
384
|
+
interpreter = Interpreter(
|
385
|
+
model_path=w,
|
386
|
+
experimental_delegates=[load_delegate(delegate, options={"device": device})],
|
387
|
+
)
|
388
|
+
device = "cpu" # Required, otherwise PyTorch will try to use the wrong device
|
310
389
|
else: # TFLite
|
311
390
|
LOGGER.info(f"Loading {w} for TensorFlow Lite inference...")
|
312
391
|
interpreter = Interpreter(model_path=w) # load TFLite model
|
@@ -314,10 +393,12 @@ class AutoBackend(nn.Module):
|
|
314
393
|
input_details = interpreter.get_input_details() # inputs
|
315
394
|
output_details = interpreter.get_output_details() # outputs
|
316
395
|
# Load metadata
|
317
|
-
|
396
|
+
try:
|
318
397
|
with zipfile.ZipFile(w, "r") as model:
|
319
398
|
meta_file = model.namelist()[0]
|
320
399
|
metadata = ast.literal_eval(model.read(meta_file).decode("utf-8"))
|
400
|
+
except zipfile.BadZipFile:
|
401
|
+
pass
|
321
402
|
|
322
403
|
# TF.js
|
323
404
|
elif tfjs:
|
@@ -340,6 +421,23 @@ class AutoBackend(nn.Module):
|
|
340
421
|
output_names = predictor.get_output_names()
|
341
422
|
metadata = w.parents[1] / "metadata.yaml"
|
342
423
|
|
424
|
+
# MNN
|
425
|
+
elif mnn:
|
426
|
+
LOGGER.info(f"Loading {w} for MNN inference...")
|
427
|
+
check_requirements("MNN") # requires MNN
|
428
|
+
import os
|
429
|
+
|
430
|
+
import MNN
|
431
|
+
|
432
|
+
config = {"precision": "low", "backend": "CPU", "numThread": (os.cpu_count() + 1) // 2}
|
433
|
+
rt = MNN.nn.create_runtime_manager((config,))
|
434
|
+
net = MNN.nn.load_module_from_file(w, [], [], runtime_manager=rt, rearrange=True)
|
435
|
+
|
436
|
+
def torch_to_mnn(x):
|
437
|
+
return MNN.expr.const(x.data_ptr(), x.shape)
|
438
|
+
|
439
|
+
metadata = json.loads(net.get_info()["bizCode"])
|
440
|
+
|
343
441
|
# NCNN
|
344
442
|
elif ncnn:
|
345
443
|
LOGGER.info(f"Loading {w} for NCNN inference...")
|
@@ -361,24 +459,25 @@ class AutoBackend(nn.Module):
|
|
361
459
|
from ultralytics.utils.triton import TritonRemoteModel
|
362
460
|
|
363
461
|
model = TritonRemoteModel(w)
|
462
|
+
metadata = model.metadata
|
364
463
|
|
365
464
|
# Any other format (unsupported)
|
366
465
|
else:
|
367
466
|
from ultralytics.engine.exporter import export_formats
|
368
467
|
|
369
468
|
raise TypeError(
|
370
|
-
f"model='{w}' is not a supported model format. "
|
371
|
-
f"See https://docs.ultralytics.com/modes/predict for help
|
469
|
+
f"model='{w}' is not a supported model format. Ultralytics supports: {export_formats()['Format']}\n"
|
470
|
+
f"See https://docs.ultralytics.com/modes/predict for help."
|
372
471
|
)
|
373
472
|
|
374
473
|
# Load external metadata YAML
|
375
474
|
if isinstance(metadata, (str, Path)) and Path(metadata).exists():
|
376
475
|
metadata = yaml_load(metadata)
|
377
|
-
if metadata:
|
476
|
+
if metadata and isinstance(metadata, dict):
|
378
477
|
for k, v in metadata.items():
|
379
|
-
if k in
|
478
|
+
if k in {"stride", "batch"}:
|
380
479
|
metadata[k] = int(v)
|
381
|
-
elif k in
|
480
|
+
elif k in {"imgsz", "names", "kpt_shape"} and isinstance(v, str):
|
382
481
|
metadata[k] = eval(v)
|
383
482
|
stride = metadata["stride"]
|
384
483
|
task = metadata["task"]
|
@@ -435,9 +534,26 @@ class AutoBackend(nn.Module):
|
|
435
534
|
y = self.net.forward()
|
436
535
|
|
437
536
|
# ONNX Runtime
|
438
|
-
elif self.onnx:
|
439
|
-
|
440
|
-
|
537
|
+
elif self.onnx or self.imx:
|
538
|
+
if self.dynamic:
|
539
|
+
im = im.cpu().numpy() # torch to numpy
|
540
|
+
y = self.session.run(self.output_names, {self.session.get_inputs()[0].name: im})
|
541
|
+
else:
|
542
|
+
if not self.cuda:
|
543
|
+
im = im.cpu()
|
544
|
+
self.io.bind_input(
|
545
|
+
name="images",
|
546
|
+
device_type=im.device.type,
|
547
|
+
device_id=im.device.index if im.device.type == "cuda" else 0,
|
548
|
+
element_type=np.float16 if self.fp16 else np.float32,
|
549
|
+
shape=tuple(im.shape),
|
550
|
+
buffer_ptr=im.data_ptr(),
|
551
|
+
)
|
552
|
+
self.session.run_with_iobinding(self.io)
|
553
|
+
y = self.bindings
|
554
|
+
if self.imx:
|
555
|
+
# boxes, conf, cls
|
556
|
+
y = np.concatenate([y[0], y[1][:, :, None], y[2][:, :, None]], axis=-1)
|
441
557
|
|
442
558
|
# OpenVINO
|
443
559
|
elif self.xml:
|
@@ -466,12 +582,19 @@ class AutoBackend(nn.Module):
|
|
466
582
|
# TensorRT
|
467
583
|
elif self.engine:
|
468
584
|
if self.dynamic and im.shape != self.bindings["images"].shape:
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
585
|
+
if self.is_trt10:
|
586
|
+
self.context.set_input_shape("images", im.shape)
|
587
|
+
self.bindings["images"] = self.bindings["images"]._replace(shape=im.shape)
|
588
|
+
for name in self.output_names:
|
589
|
+
self.bindings[name].data.resize_(tuple(self.context.get_tensor_shape(name)))
|
590
|
+
else:
|
591
|
+
i = self.model.get_binding_index("images")
|
592
|
+
self.context.set_binding_shape(i, im.shape)
|
593
|
+
self.bindings["images"] = self.bindings["images"]._replace(shape=im.shape)
|
594
|
+
for name in self.output_names:
|
595
|
+
i = self.model.get_binding_index(name)
|
596
|
+
self.bindings[name].data.resize_(tuple(self.context.get_binding_shape(i)))
|
597
|
+
|
475
598
|
s = self.bindings["images"].shape
|
476
599
|
assert im.shape == s, f"input size {im.shape} {'>' if self.dynamic else 'not equal to'} max model size {s}"
|
477
600
|
self.binding_addrs["images"] = int(im.data_ptr())
|
@@ -494,10 +617,9 @@ class AutoBackend(nn.Module):
|
|
494
617
|
# box = xywh2xyxy(y['coordinates'] * [[w, h, w, h]]) # xyxy pixels
|
495
618
|
# conf, cls = y['confidence'].max(1), y['confidence'].argmax(1).astype(np.float32)
|
496
619
|
# y = np.concatenate((box, conf.reshape(-1, 1), cls.reshape(-1, 1)), 1)
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
y = list(reversed(y.values())) # reversed for segmentation models (pred, proto)
|
620
|
+
y = list(y.values())
|
621
|
+
if len(y) == 2 and len(y[1].shape) != 4: # segmentation model
|
622
|
+
y = list(reversed(y)) # reversed for segmentation models (pred, proto)
|
501
623
|
|
502
624
|
# PaddlePaddle
|
503
625
|
elif self.paddle:
|
@@ -506,17 +628,19 @@ class AutoBackend(nn.Module):
|
|
506
628
|
self.predictor.run()
|
507
629
|
y = [self.predictor.get_output_handle(x).copy_to_cpu() for x in self.output_names]
|
508
630
|
|
631
|
+
# MNN
|
632
|
+
elif self.mnn:
|
633
|
+
input_var = self.torch_to_mnn(im)
|
634
|
+
output_var = self.net.onForward([input_var])
|
635
|
+
y = [x.read() for x in output_var]
|
636
|
+
|
509
637
|
# NCNN
|
510
638
|
elif self.ncnn:
|
511
639
|
mat_in = self.pyncnn.Mat(im[0].cpu().numpy())
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
for output_name in output_names:
|
517
|
-
mat_out = self.pyncnn.Mat()
|
518
|
-
ex.extract(output_name, mat_out)
|
519
|
-
y.append(np.array(mat_out)[None])
|
640
|
+
with self.net.create_extractor() as ex:
|
641
|
+
ex.input(self.net.input_names()[0], mat_in)
|
642
|
+
# WARNING: 'output_names' sorted as a temporary fix for https://github.com/pnnx/pnnx/issues/130
|
643
|
+
y = [np.array(ex.extract(x)[1])[None] for x in sorted(self.net.output_names())]
|
520
644
|
|
521
645
|
# NVIDIA Triton Inference Server
|
522
646
|
elif self.triton:
|
@@ -532,14 +656,10 @@ class AutoBackend(nn.Module):
|
|
532
656
|
y = [y]
|
533
657
|
elif self.pb: # GraphDef
|
534
658
|
y = self.frozen_func(x=self.tf.constant(im))
|
535
|
-
if len(y) == 2 and len(self.names) == 999: # segments and names not defined
|
536
|
-
ip, ib = (0, 1) if len(y[0].shape) == 4 else (1, 0) # index of protos, boxes
|
537
|
-
nc = y[ib].shape[1] - y[ip].shape[3] - 4 # y = (1, 160, 160, 32), (1, 116, 8400)
|
538
|
-
self.names = {i: f"class{i}" for i in range(nc)}
|
539
659
|
else: # Lite or Edge TPU
|
540
660
|
details = self.input_details[0]
|
541
|
-
|
542
|
-
if
|
661
|
+
is_int = details["dtype"] in {np.int8, np.int16} # is TFLite quantized int8 or int16 model
|
662
|
+
if is_int:
|
543
663
|
scale, zero_point = details["quantization"]
|
544
664
|
im = (im / scale + zero_point).astype(details["dtype"]) # de-scale
|
545
665
|
self.interpreter.set_tensor(details["index"], im)
|
@@ -547,25 +667,38 @@ class AutoBackend(nn.Module):
|
|
547
667
|
y = []
|
548
668
|
for output in self.output_details:
|
549
669
|
x = self.interpreter.get_tensor(output["index"])
|
550
|
-
if
|
670
|
+
if is_int:
|
551
671
|
scale, zero_point = output["quantization"]
|
552
672
|
x = (x.astype(np.float32) - zero_point) * scale # re-scale
|
553
|
-
if x.ndim
|
673
|
+
if x.ndim == 3: # if task is not classification, excluding masks (ndim=4) as well
|
554
674
|
# Denormalize xywh by image size. See https://github.com/ultralytics/ultralytics/pull/1695
|
555
675
|
# xywh are normalized in TFLite/EdgeTPU to mitigate quantization error of integer models
|
556
|
-
x[
|
557
|
-
|
676
|
+
if x.shape[-1] == 6: # end-to-end model
|
677
|
+
x[:, :, [0, 2]] *= w
|
678
|
+
x[:, :, [1, 3]] *= h
|
679
|
+
else:
|
680
|
+
x[:, [0, 2]] *= w
|
681
|
+
x[:, [1, 3]] *= h
|
682
|
+
if self.task == "pose":
|
683
|
+
x[:, 5::3] *= w
|
684
|
+
x[:, 6::3] *= h
|
558
685
|
y.append(x)
|
559
686
|
# TF segment fixes: export is reversed vs ONNX export and protos are transposed
|
560
687
|
if len(y) == 2: # segment with (det, proto) output order reversed
|
561
688
|
if len(y[1].shape) != 4:
|
562
689
|
y = list(reversed(y)) # should be y = (1, 116, 8400), (1, 160, 160, 32)
|
563
|
-
y[1]
|
690
|
+
if y[1].shape[-1] == 6: # end-to-end model
|
691
|
+
y = [y[1]]
|
692
|
+
else:
|
693
|
+
y[1] = np.transpose(y[1], (0, 3, 1, 2)) # should be y = (1, 116, 8400), (1, 32, 160, 160)
|
564
694
|
y = [x if isinstance(x, np.ndarray) else x.numpy() for x in y]
|
565
695
|
|
566
696
|
# for x in y:
|
567
697
|
# print(type(x), len(x)) if isinstance(x, (list, tuple)) else print(type(x), x.shape) # debug shapes
|
568
698
|
if isinstance(y, (list, tuple)):
|
699
|
+
if len(self.names) == 999 and (self.task == "segment" or len(y) == 2): # segments and names not defined
|
700
|
+
nc = y[0].shape[1] - y[1].shape[1] - 4 # y = (1, 32, 160, 160), (1, 116, 8400)
|
701
|
+
self.names = {i: f"class{i}" for i in range(nc)}
|
569
702
|
return self.from_numpy(y[0]) if len(y) == 1 else [self.from_numpy(x) for x in y]
|
570
703
|
else:
|
571
704
|
return self.from_numpy(y)
|
@@ -589,6 +722,8 @@ class AutoBackend(nn.Module):
|
|
589
722
|
Args:
|
590
723
|
imgsz (tuple): The shape of the dummy input tensor in the format (batch_size, channels, height, width)
|
591
724
|
"""
|
725
|
+
import torchvision # noqa (import here so torchvision import time not recorded in postprocess time)
|
726
|
+
|
592
727
|
warmup_types = self.pt, self.jit, self.onnx, self.engine, self.saved_model, self.pb, self.triton, self.nn_module
|
593
728
|
if any(warmup_types) and (self.device.type != "cpu" or self.triton):
|
594
729
|
im = torch.empty(*imgsz, dtype=torch.half if self.fp16 else torch.float, device=self.device) # input
|
@@ -598,8 +733,8 @@ class AutoBackend(nn.Module):
|
|
598
733
|
@staticmethod
|
599
734
|
def _model_type(p="path/to/model.pt"):
|
600
735
|
"""
|
601
|
-
|
602
|
-
|
736
|
+
Takes a path to a model file and returns the model type. Possibles types are pt, jit, onnx, xml, engine, coreml,
|
737
|
+
saved_model, pb, tflite, edgetpu, tfjs, ncnn or paddle.
|
603
738
|
|
604
739
|
Args:
|
605
740
|
p: path to the model file. Defaults to path/to/model.pt
|
@@ -610,8 +745,8 @@ class AutoBackend(nn.Module):
|
|
610
745
|
"""
|
611
746
|
from ultralytics.engine.exporter import export_formats
|
612
747
|
|
613
|
-
sf =
|
614
|
-
if not is_url(p
|
748
|
+
sf = export_formats()["Suffix"] # export suffixes
|
749
|
+
if not is_url(p) and not isinstance(p, str):
|
615
750
|
check_suffix(p, sf) # checks
|
616
751
|
name = Path(p).name
|
617
752
|
types = [s in name for s in sf]
|