dgenerate-ultralytics-headless 8.3.137__py3-none-any.whl → 8.3.224__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/METADATA +41 -34
- dgenerate_ultralytics_headless-8.3.224.dist-info/RECORD +285 -0
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/WHEEL +1 -1
- tests/__init__.py +7 -6
- tests/conftest.py +15 -39
- tests/test_cli.py +17 -17
- tests/test_cuda.py +17 -8
- tests/test_engine.py +36 -10
- tests/test_exports.py +98 -37
- tests/test_integrations.py +12 -15
- tests/test_python.py +126 -82
- tests/test_solutions.py +319 -135
- ultralytics/__init__.py +27 -9
- ultralytics/cfg/__init__.py +83 -87
- ultralytics/cfg/datasets/Argoverse.yaml +4 -4
- ultralytics/cfg/datasets/DOTAv1.5.yaml +2 -2
- ultralytics/cfg/datasets/DOTAv1.yaml +2 -2
- ultralytics/cfg/datasets/GlobalWheat2020.yaml +2 -2
- ultralytics/cfg/datasets/HomeObjects-3K.yaml +4 -5
- ultralytics/cfg/datasets/ImageNet.yaml +3 -3
- ultralytics/cfg/datasets/Objects365.yaml +24 -20
- ultralytics/cfg/datasets/SKU-110K.yaml +9 -9
- ultralytics/cfg/datasets/VOC.yaml +10 -13
- ultralytics/cfg/datasets/VisDrone.yaml +43 -33
- ultralytics/cfg/datasets/african-wildlife.yaml +5 -5
- ultralytics/cfg/datasets/brain-tumor.yaml +4 -5
- ultralytics/cfg/datasets/carparts-seg.yaml +5 -5
- ultralytics/cfg/datasets/coco-pose.yaml +26 -4
- ultralytics/cfg/datasets/coco.yaml +4 -4
- ultralytics/cfg/datasets/coco128-seg.yaml +2 -2
- ultralytics/cfg/datasets/coco128.yaml +2 -2
- ultralytics/cfg/datasets/coco8-grayscale.yaml +103 -0
- ultralytics/cfg/datasets/coco8-multispectral.yaml +2 -2
- ultralytics/cfg/datasets/coco8-pose.yaml +23 -2
- ultralytics/cfg/datasets/coco8-seg.yaml +2 -2
- ultralytics/cfg/datasets/coco8.yaml +2 -2
- ultralytics/cfg/datasets/construction-ppe.yaml +32 -0
- ultralytics/cfg/datasets/crack-seg.yaml +5 -5
- ultralytics/cfg/datasets/dog-pose.yaml +32 -4
- ultralytics/cfg/datasets/dota8-multispectral.yaml +2 -2
- ultralytics/cfg/datasets/dota8.yaml +2 -2
- ultralytics/cfg/datasets/hand-keypoints.yaml +29 -4
- ultralytics/cfg/datasets/lvis.yaml +9 -9
- ultralytics/cfg/datasets/medical-pills.yaml +4 -5
- ultralytics/cfg/datasets/open-images-v7.yaml +7 -10
- ultralytics/cfg/datasets/package-seg.yaml +5 -5
- ultralytics/cfg/datasets/signature.yaml +4 -4
- ultralytics/cfg/datasets/tiger-pose.yaml +20 -4
- ultralytics/cfg/datasets/xView.yaml +5 -5
- ultralytics/cfg/default.yaml +96 -93
- ultralytics/cfg/trackers/botsort.yaml +16 -17
- ultralytics/cfg/trackers/bytetrack.yaml +9 -11
- ultralytics/data/__init__.py +4 -4
- ultralytics/data/annotator.py +12 -12
- ultralytics/data/augment.py +531 -564
- ultralytics/data/base.py +76 -81
- ultralytics/data/build.py +206 -42
- ultralytics/data/converter.py +179 -78
- ultralytics/data/dataset.py +121 -121
- ultralytics/data/loaders.py +114 -91
- ultralytics/data/split.py +28 -15
- ultralytics/data/split_dota.py +67 -48
- ultralytics/data/utils.py +110 -89
- ultralytics/engine/exporter.py +422 -460
- ultralytics/engine/model.py +224 -252
- ultralytics/engine/predictor.py +94 -89
- ultralytics/engine/results.py +345 -595
- ultralytics/engine/trainer.py +231 -134
- ultralytics/engine/tuner.py +279 -73
- ultralytics/engine/validator.py +53 -46
- ultralytics/hub/__init__.py +26 -28
- ultralytics/hub/auth.py +30 -16
- ultralytics/hub/google/__init__.py +34 -36
- ultralytics/hub/session.py +53 -77
- ultralytics/hub/utils.py +23 -109
- ultralytics/models/__init__.py +1 -1
- ultralytics/models/fastsam/__init__.py +1 -1
- ultralytics/models/fastsam/model.py +36 -18
- ultralytics/models/fastsam/predict.py +33 -44
- ultralytics/models/fastsam/utils.py +4 -5
- ultralytics/models/fastsam/val.py +12 -14
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/nas/model.py +16 -20
- ultralytics/models/nas/predict.py +12 -14
- ultralytics/models/nas/val.py +4 -5
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/rtdetr/model.py +9 -9
- ultralytics/models/rtdetr/predict.py +22 -17
- ultralytics/models/rtdetr/train.py +20 -16
- ultralytics/models/rtdetr/val.py +79 -59
- ultralytics/models/sam/__init__.py +8 -2
- ultralytics/models/sam/amg.py +53 -38
- ultralytics/models/sam/build.py +29 -31
- ultralytics/models/sam/model.py +33 -38
- ultralytics/models/sam/modules/blocks.py +159 -182
- ultralytics/models/sam/modules/decoders.py +38 -47
- ultralytics/models/sam/modules/encoders.py +114 -133
- ultralytics/models/sam/modules/memory_attention.py +38 -31
- ultralytics/models/sam/modules/sam.py +114 -93
- ultralytics/models/sam/modules/tiny_encoder.py +268 -291
- ultralytics/models/sam/modules/transformer.py +59 -66
- ultralytics/models/sam/modules/utils.py +55 -72
- ultralytics/models/sam/predict.py +745 -341
- ultralytics/models/utils/loss.py +118 -107
- ultralytics/models/utils/ops.py +118 -71
- ultralytics/models/yolo/__init__.py +1 -1
- ultralytics/models/yolo/classify/predict.py +28 -26
- ultralytics/models/yolo/classify/train.py +50 -81
- ultralytics/models/yolo/classify/val.py +68 -61
- ultralytics/models/yolo/detect/predict.py +12 -15
- ultralytics/models/yolo/detect/train.py +56 -46
- ultralytics/models/yolo/detect/val.py +279 -223
- ultralytics/models/yolo/model.py +167 -86
- ultralytics/models/yolo/obb/predict.py +7 -11
- ultralytics/models/yolo/obb/train.py +23 -25
- ultralytics/models/yolo/obb/val.py +107 -99
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +12 -14
- ultralytics/models/yolo/pose/train.py +31 -69
- ultralytics/models/yolo/pose/val.py +119 -254
- ultralytics/models/yolo/segment/predict.py +21 -25
- ultralytics/models/yolo/segment/train.py +12 -66
- ultralytics/models/yolo/segment/val.py +126 -305
- ultralytics/models/yolo/world/train.py +53 -45
- ultralytics/models/yolo/world/train_world.py +51 -32
- ultralytics/models/yolo/yoloe/__init__.py +7 -7
- ultralytics/models/yolo/yoloe/predict.py +30 -37
- ultralytics/models/yolo/yoloe/train.py +89 -71
- ultralytics/models/yolo/yoloe/train_seg.py +15 -17
- ultralytics/models/yolo/yoloe/val.py +56 -41
- ultralytics/nn/__init__.py +9 -11
- ultralytics/nn/autobackend.py +179 -107
- ultralytics/nn/modules/__init__.py +67 -67
- ultralytics/nn/modules/activation.py +8 -7
- ultralytics/nn/modules/block.py +302 -323
- ultralytics/nn/modules/conv.py +61 -104
- ultralytics/nn/modules/head.py +488 -186
- ultralytics/nn/modules/transformer.py +183 -123
- ultralytics/nn/modules/utils.py +15 -20
- ultralytics/nn/tasks.py +327 -203
- ultralytics/nn/text_model.py +81 -65
- ultralytics/py.typed +1 -0
- ultralytics/solutions/__init__.py +12 -12
- ultralytics/solutions/ai_gym.py +19 -27
- ultralytics/solutions/analytics.py +36 -26
- ultralytics/solutions/config.py +29 -28
- ultralytics/solutions/distance_calculation.py +23 -24
- ultralytics/solutions/heatmap.py +17 -19
- ultralytics/solutions/instance_segmentation.py +21 -19
- ultralytics/solutions/object_blurrer.py +16 -17
- ultralytics/solutions/object_counter.py +48 -53
- ultralytics/solutions/object_cropper.py +22 -16
- ultralytics/solutions/parking_management.py +61 -58
- ultralytics/solutions/queue_management.py +19 -19
- ultralytics/solutions/region_counter.py +63 -50
- ultralytics/solutions/security_alarm.py +22 -25
- ultralytics/solutions/similarity_search.py +107 -60
- ultralytics/solutions/solutions.py +343 -262
- ultralytics/solutions/speed_estimation.py +35 -31
- ultralytics/solutions/streamlit_inference.py +104 -40
- ultralytics/solutions/templates/similarity-search.html +31 -24
- ultralytics/solutions/trackzone.py +24 -24
- ultralytics/solutions/vision_eye.py +11 -12
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/basetrack.py +18 -27
- ultralytics/trackers/bot_sort.py +48 -39
- ultralytics/trackers/byte_tracker.py +94 -94
- ultralytics/trackers/track.py +7 -16
- ultralytics/trackers/utils/gmc.py +37 -69
- ultralytics/trackers/utils/kalman_filter.py +68 -76
- ultralytics/trackers/utils/matching.py +13 -17
- ultralytics/utils/__init__.py +251 -275
- ultralytics/utils/autobatch.py +19 -7
- ultralytics/utils/autodevice.py +68 -38
- ultralytics/utils/benchmarks.py +169 -130
- ultralytics/utils/callbacks/base.py +12 -13
- ultralytics/utils/callbacks/clearml.py +14 -15
- ultralytics/utils/callbacks/comet.py +139 -66
- ultralytics/utils/callbacks/dvc.py +19 -27
- ultralytics/utils/callbacks/hub.py +8 -6
- ultralytics/utils/callbacks/mlflow.py +6 -10
- ultralytics/utils/callbacks/neptune.py +11 -19
- ultralytics/utils/callbacks/platform.py +73 -0
- ultralytics/utils/callbacks/raytune.py +3 -4
- ultralytics/utils/callbacks/tensorboard.py +9 -12
- ultralytics/utils/callbacks/wb.py +33 -30
- ultralytics/utils/checks.py +163 -114
- ultralytics/utils/cpu.py +89 -0
- ultralytics/utils/dist.py +24 -20
- ultralytics/utils/downloads.py +176 -146
- ultralytics/utils/errors.py +11 -13
- ultralytics/utils/events.py +113 -0
- ultralytics/utils/export/__init__.py +7 -0
- ultralytics/utils/{export.py → export/engine.py} +81 -63
- ultralytics/utils/export/imx.py +294 -0
- ultralytics/utils/export/tensorflow.py +217 -0
- ultralytics/utils/files.py +33 -36
- ultralytics/utils/git.py +137 -0
- ultralytics/utils/instance.py +105 -120
- ultralytics/utils/logger.py +404 -0
- ultralytics/utils/loss.py +99 -61
- ultralytics/utils/metrics.py +649 -478
- ultralytics/utils/nms.py +337 -0
- ultralytics/utils/ops.py +263 -451
- ultralytics/utils/patches.py +70 -31
- ultralytics/utils/plotting.py +253 -223
- ultralytics/utils/tal.py +48 -61
- ultralytics/utils/torch_utils.py +244 -251
- ultralytics/utils/tqdm.py +438 -0
- ultralytics/utils/triton.py +22 -23
- ultralytics/utils/tuner.py +11 -10
- dgenerate_ultralytics_headless-8.3.137.dist-info/RECORD +0 -272
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/top_level.txt +0 -0
ultralytics/nn/autobackend.py
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import ast
|
|
4
6
|
import json
|
|
5
7
|
import platform
|
|
6
8
|
import zipfile
|
|
7
9
|
from collections import OrderedDict, namedtuple
|
|
8
10
|
from pathlib import Path
|
|
9
|
-
from typing import
|
|
11
|
+
from typing import Any
|
|
10
12
|
|
|
11
13
|
import cv2
|
|
12
14
|
import numpy as np
|
|
@@ -14,13 +16,24 @@ import torch
|
|
|
14
16
|
import torch.nn as nn
|
|
15
17
|
from PIL import Image
|
|
16
18
|
|
|
17
|
-
from ultralytics.utils import ARM64, IS_JETSON, LINUX, LOGGER, PYTHON_VERSION, ROOT, YAML
|
|
19
|
+
from ultralytics.utils import ARM64, IS_JETSON, LINUX, LOGGER, PYTHON_VERSION, ROOT, YAML, is_jetson
|
|
18
20
|
from ultralytics.utils.checks import check_requirements, check_suffix, check_version, check_yaml, is_rockchip
|
|
19
21
|
from ultralytics.utils.downloads import attempt_download_asset, is_url
|
|
22
|
+
from ultralytics.utils.nms import non_max_suppression
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def check_class_names(names: list | dict) -> dict[int, str]:
|
|
26
|
+
"""Check class names and convert to dict format if needed.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
names (list | dict): Class names as list or dict format.
|
|
20
30
|
|
|
31
|
+
Returns:
|
|
32
|
+
(dict): Class names in dict format with integer keys and string values.
|
|
21
33
|
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
Raises:
|
|
35
|
+
KeyError: If class indices are invalid for the dataset size.
|
|
36
|
+
"""
|
|
24
37
|
if isinstance(names, list): # names is a list
|
|
25
38
|
names = dict(enumerate(names)) # convert to dict
|
|
26
39
|
if isinstance(names, dict):
|
|
@@ -38,8 +51,15 @@ def check_class_names(names):
|
|
|
38
51
|
return names
|
|
39
52
|
|
|
40
53
|
|
|
41
|
-
def default_class_names(data=None):
|
|
42
|
-
"""
|
|
54
|
+
def default_class_names(data: str | Path | None = None) -> dict[int, str]:
|
|
55
|
+
"""Apply default class names to an input YAML file or return numerical class names.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
data (str | Path, optional): Path to YAML file containing class names.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
(dict): Dictionary mapping class indices to class names.
|
|
62
|
+
"""
|
|
43
63
|
if data:
|
|
44
64
|
try:
|
|
45
65
|
return YAML.load(check_yaml(data))["names"]
|
|
@@ -49,8 +69,7 @@ def default_class_names(data=None):
|
|
|
49
69
|
|
|
50
70
|
|
|
51
71
|
class AutoBackend(nn.Module):
|
|
52
|
-
"""
|
|
53
|
-
Handles dynamic backend selection for running inference using Ultralytics YOLO models.
|
|
72
|
+
"""Handle dynamic backend selection for running inference using Ultralytics YOLO models.
|
|
54
73
|
|
|
55
74
|
The AutoBackend class is designed to provide an abstraction layer for various inference engines. It supports a wide
|
|
56
75
|
range of formats, each with specific naming conventions as outlined below:
|
|
@@ -74,6 +93,8 @@ class AutoBackend(nn.Module):
|
|
|
74
93
|
| NCNN | *_ncnn_model/ |
|
|
75
94
|
| IMX | *_imx_model/ |
|
|
76
95
|
| RKNN | *_rknn_model/ |
|
|
96
|
+
| Triton Inference | triton://model |
|
|
97
|
+
| ExecuTorch | *.pte |
|
|
77
98
|
|
|
78
99
|
Attributes:
|
|
79
100
|
model (torch.nn.Module): The loaded YOLO model.
|
|
@@ -82,6 +103,25 @@ class AutoBackend(nn.Module):
|
|
|
82
103
|
names (dict): A dictionary of class names that the model can detect.
|
|
83
104
|
stride (int): The model stride, typically 32 for YOLO models.
|
|
84
105
|
fp16 (bool): Whether the model uses half-precision (FP16) inference.
|
|
106
|
+
nhwc (bool): Whether the model expects NHWC input format instead of NCHW.
|
|
107
|
+
pt (bool): Whether the model is a PyTorch model.
|
|
108
|
+
jit (bool): Whether the model is a TorchScript model.
|
|
109
|
+
onnx (bool): Whether the model is an ONNX model.
|
|
110
|
+
xml (bool): Whether the model is an OpenVINO model.
|
|
111
|
+
engine (bool): Whether the model is a TensorRT engine.
|
|
112
|
+
coreml (bool): Whether the model is a CoreML model.
|
|
113
|
+
saved_model (bool): Whether the model is a TensorFlow SavedModel.
|
|
114
|
+
pb (bool): Whether the model is a TensorFlow GraphDef.
|
|
115
|
+
tflite (bool): Whether the model is a TensorFlow Lite model.
|
|
116
|
+
edgetpu (bool): Whether the model is a TensorFlow Edge TPU model.
|
|
117
|
+
tfjs (bool): Whether the model is a TensorFlow.js model.
|
|
118
|
+
paddle (bool): Whether the model is a PaddlePaddle model.
|
|
119
|
+
mnn (bool): Whether the model is an MNN model.
|
|
120
|
+
ncnn (bool): Whether the model is an NCNN model.
|
|
121
|
+
imx (bool): Whether the model is an IMX model.
|
|
122
|
+
rknn (bool): Whether the model is an RKNN model.
|
|
123
|
+
triton (bool): Whether the model is a Triton Inference Server model.
|
|
124
|
+
pte (bool): Whether the model is a PyTorch ExecuTorch model.
|
|
85
125
|
|
|
86
126
|
Methods:
|
|
87
127
|
forward: Run inference on an input image.
|
|
@@ -90,38 +130,34 @@ class AutoBackend(nn.Module):
|
|
|
90
130
|
_model_type: Determine the model type from file path.
|
|
91
131
|
|
|
92
132
|
Examples:
|
|
93
|
-
>>> model = AutoBackend(
|
|
133
|
+
>>> model = AutoBackend(model="yolo11n.pt", device="cuda")
|
|
94
134
|
>>> results = model(img)
|
|
95
135
|
"""
|
|
96
136
|
|
|
97
137
|
@torch.no_grad()
|
|
98
138
|
def __init__(
|
|
99
139
|
self,
|
|
100
|
-
|
|
140
|
+
model: str | torch.nn.Module = "yolo11n.pt",
|
|
101
141
|
device: torch.device = torch.device("cpu"),
|
|
102
142
|
dnn: bool = False,
|
|
103
|
-
data:
|
|
143
|
+
data: str | Path | None = None,
|
|
104
144
|
fp16: bool = False,
|
|
105
|
-
batch: int = 1,
|
|
106
145
|
fuse: bool = True,
|
|
107
146
|
verbose: bool = True,
|
|
108
147
|
):
|
|
109
|
-
"""
|
|
110
|
-
Initialize the AutoBackend for inference.
|
|
148
|
+
"""Initialize the AutoBackend for inference.
|
|
111
149
|
|
|
112
150
|
Args:
|
|
113
|
-
|
|
151
|
+
model (str | torch.nn.Module): Path to the model weights file or a module instance.
|
|
114
152
|
device (torch.device): Device to run the model on.
|
|
115
153
|
dnn (bool): Use OpenCV DNN module for ONNX inference.
|
|
116
|
-
data (str | Path
|
|
154
|
+
data (str | Path, optional): Path to the additional data.yaml file containing class names.
|
|
117
155
|
fp16 (bool): Enable half-precision inference. Supported only on specific backends.
|
|
118
|
-
batch (int): Batch-size to assume for inference.
|
|
119
156
|
fuse (bool): Fuse Conv2D + BatchNorm layers for optimization.
|
|
120
157
|
verbose (bool): Enable verbose logging.
|
|
121
158
|
"""
|
|
122
159
|
super().__init__()
|
|
123
|
-
|
|
124
|
-
nn_module = isinstance(weights, torch.nn.Module)
|
|
160
|
+
nn_module = isinstance(model, torch.nn.Module)
|
|
125
161
|
(
|
|
126
162
|
pt,
|
|
127
163
|
jit,
|
|
@@ -139,13 +175,14 @@ class AutoBackend(nn.Module):
|
|
|
139
175
|
ncnn,
|
|
140
176
|
imx,
|
|
141
177
|
rknn,
|
|
178
|
+
pte,
|
|
142
179
|
triton,
|
|
143
|
-
) = self._model_type(
|
|
180
|
+
) = self._model_type("" if nn_module else model)
|
|
144
181
|
fp16 &= pt or jit or onnx or xml or engine or nn_module or triton # FP16
|
|
145
182
|
nhwc = coreml or saved_model or pb or tflite or edgetpu or rknn # BHWC formats (vs torch BCWH)
|
|
146
183
|
stride, ch = 32, 3 # default stride and channels
|
|
147
184
|
end2end, dynamic = False, False
|
|
148
|
-
|
|
185
|
+
metadata, task = None, None
|
|
149
186
|
|
|
150
187
|
# Set device
|
|
151
188
|
cuda = isinstance(device, torch.device) and torch.cuda.is_available() and device.type != "cpu" # use CUDA
|
|
@@ -154,36 +191,32 @@ class AutoBackend(nn.Module):
|
|
|
154
191
|
cuda = False
|
|
155
192
|
|
|
156
193
|
# Download if not local
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
elif pt:
|
|
176
|
-
from ultralytics.nn.tasks import attempt_load_weights
|
|
177
|
-
|
|
178
|
-
model = attempt_load_weights(
|
|
179
|
-
weights if isinstance(weights, list) else w, device=device, inplace=True, fuse=fuse
|
|
180
|
-
)
|
|
194
|
+
w = attempt_download_asset(model) if pt else model # weights path
|
|
195
|
+
|
|
196
|
+
# PyTorch (in-memory or file)
|
|
197
|
+
if nn_module or pt:
|
|
198
|
+
if nn_module:
|
|
199
|
+
pt = True
|
|
200
|
+
if fuse:
|
|
201
|
+
if IS_JETSON and is_jetson(jetpack=5):
|
|
202
|
+
# Jetson Jetpack5 requires device before fuse https://github.com/ultralytics/ultralytics/pull/21028
|
|
203
|
+
model = model.to(device)
|
|
204
|
+
model = model.fuse(verbose=verbose)
|
|
205
|
+
model = model.to(device)
|
|
206
|
+
else: # pt file
|
|
207
|
+
from ultralytics.nn.tasks import load_checkpoint
|
|
208
|
+
|
|
209
|
+
model, _ = load_checkpoint(model, device=device, fuse=fuse) # load model, ckpt
|
|
210
|
+
|
|
211
|
+
# Common PyTorch model processing
|
|
181
212
|
if hasattr(model, "kpt_shape"):
|
|
182
213
|
kpt_shape = model.kpt_shape # pose-only
|
|
183
214
|
stride = max(int(model.stride.max()), 32) # model stride
|
|
184
215
|
names = model.module.names if hasattr(model, "module") else model.names # get class names
|
|
185
216
|
model.half() if fp16 else model.float()
|
|
186
217
|
ch = model.yaml.get("channels", 3)
|
|
218
|
+
for p in model.parameters():
|
|
219
|
+
p.requires_grad = False
|
|
187
220
|
self.model = model # explicitly assign for to(), cpu(), cuda(), half()
|
|
188
221
|
|
|
189
222
|
# TorchScript
|
|
@@ -212,17 +245,17 @@ class AutoBackend(nn.Module):
|
|
|
212
245
|
providers = ["CPUExecutionProvider"]
|
|
213
246
|
if cuda:
|
|
214
247
|
if "CUDAExecutionProvider" in onnxruntime.get_available_providers():
|
|
215
|
-
providers.insert(0, "CUDAExecutionProvider")
|
|
248
|
+
providers.insert(0, ("CUDAExecutionProvider", {"device_id": device.index}))
|
|
216
249
|
else: # Only log warning if CUDA was requested but unavailable
|
|
217
250
|
LOGGER.warning("Failed to start ONNX Runtime with CUDA. Using CPU...")
|
|
218
251
|
device = torch.device("cpu")
|
|
219
252
|
cuda = False
|
|
220
|
-
LOGGER.info(f"Using ONNX Runtime {providers[0]}")
|
|
253
|
+
LOGGER.info(f"Using ONNX Runtime {onnxruntime.__version__} {providers[0]}")
|
|
221
254
|
if onnx:
|
|
222
255
|
session = onnxruntime.InferenceSession(w, providers=providers)
|
|
223
256
|
else:
|
|
224
257
|
check_requirements(
|
|
225
|
-
|
|
258
|
+
("model-compression-toolkit>=2.4.1", "sony-custom-layers[torch]>=0.3.0", "onnxruntime-extensions")
|
|
226
259
|
)
|
|
227
260
|
w = next(Path(w).glob("*.onnx"))
|
|
228
261
|
LOGGER.info(f"Loading {w} for ONNX IMX inference...")
|
|
@@ -232,7 +265,6 @@ class AutoBackend(nn.Module):
|
|
|
232
265
|
session_options = mctq.get_ort_session_options()
|
|
233
266
|
session_options.enable_mem_reuse = False # fix the shape mismatch from onnxruntime
|
|
234
267
|
session = onnxruntime.InferenceSession(w, session_options, providers=["CPUExecutionProvider"])
|
|
235
|
-
task = "detect"
|
|
236
268
|
|
|
237
269
|
output_names = [x.name for x in session.get_outputs()]
|
|
238
270
|
metadata = session.get_modelmeta().custom_metadata_map
|
|
@@ -275,16 +307,22 @@ class AutoBackend(nn.Module):
|
|
|
275
307
|
if ov_model.get_parameters()[0].get_layout().empty:
|
|
276
308
|
ov_model.get_parameters()[0].set_layout(ov.Layout("NCHW"))
|
|
277
309
|
|
|
310
|
+
metadata = w.parent / "metadata.yaml"
|
|
311
|
+
if metadata.exists():
|
|
312
|
+
metadata = YAML.load(metadata)
|
|
313
|
+
batch = metadata["batch"]
|
|
314
|
+
dynamic = metadata.get("args", {}).get("dynamic", dynamic)
|
|
278
315
|
# OpenVINO inference modes are 'LATENCY', 'THROUGHPUT' (not recommended), or 'CUMULATIVE_THROUGHPUT'
|
|
279
|
-
inference_mode = "CUMULATIVE_THROUGHPUT" if batch > 1 else "LATENCY"
|
|
280
|
-
LOGGER.info(f"Using OpenVINO {inference_mode} mode for batch={batch} inference...")
|
|
316
|
+
inference_mode = "CUMULATIVE_THROUGHPUT" if batch > 1 and dynamic else "LATENCY"
|
|
281
317
|
ov_compiled_model = core.compile_model(
|
|
282
318
|
ov_model,
|
|
283
319
|
device_name=device_name,
|
|
284
320
|
config={"PERFORMANCE_HINT": inference_mode},
|
|
285
321
|
)
|
|
322
|
+
LOGGER.info(
|
|
323
|
+
f"Using OpenVINO {inference_mode} mode for batch={batch} inference on {', '.join(ov_compiled_model.get_property('EXECUTION_DEVICES'))}..."
|
|
324
|
+
)
|
|
286
325
|
input_name = ov_compiled_model.input().get_any_name()
|
|
287
|
-
metadata = w.parent / "metadata.yaml"
|
|
288
326
|
|
|
289
327
|
# TensorRT
|
|
290
328
|
elif engine:
|
|
@@ -295,11 +333,11 @@ class AutoBackend(nn.Module):
|
|
|
295
333
|
check_requirements("numpy==1.23.5")
|
|
296
334
|
|
|
297
335
|
try: # https://developer.nvidia.com/nvidia-tensorrt-download
|
|
298
|
-
import tensorrt as trt
|
|
336
|
+
import tensorrt as trt
|
|
299
337
|
except ImportError:
|
|
300
338
|
if LINUX:
|
|
301
339
|
check_requirements("tensorrt>7.0.0,!=10.1.0")
|
|
302
|
-
import tensorrt as trt
|
|
340
|
+
import tensorrt as trt
|
|
303
341
|
check_version(trt.__version__, ">=7.0.0", hard=True)
|
|
304
342
|
check_version(trt.__version__, "!=10.1.0", msg="https://github.com/ultralytics/ultralytics/pull/14239")
|
|
305
343
|
if device.type == "cpu":
|
|
@@ -361,14 +399,15 @@ class AutoBackend(nn.Module):
|
|
|
361
399
|
im = torch.from_numpy(np.empty(shape, dtype=dtype)).to(device)
|
|
362
400
|
bindings[name] = Binding(name, dtype, shape, im, int(im.data_ptr()))
|
|
363
401
|
binding_addrs = OrderedDict((n, d.ptr) for n, d in bindings.items())
|
|
364
|
-
batch_size = bindings["images"].shape[0] # if dynamic, this is instead max batch size
|
|
365
402
|
|
|
366
403
|
# CoreML
|
|
367
404
|
elif coreml:
|
|
405
|
+
check_requirements("coremltools>=8.0")
|
|
368
406
|
LOGGER.info(f"Loading {w} for CoreML inference...")
|
|
369
407
|
import coremltools as ct
|
|
370
408
|
|
|
371
409
|
model = ct.models.MLModel(w)
|
|
410
|
+
dynamic = model.get_spec().description.input[0].type.HasField("multiArrayType")
|
|
372
411
|
metadata = dict(model.user_defined_metadata)
|
|
373
412
|
|
|
374
413
|
# TF SavedModel
|
|
@@ -385,7 +424,7 @@ class AutoBackend(nn.Module):
|
|
|
385
424
|
LOGGER.info(f"Loading {w} for TensorFlow GraphDef inference...")
|
|
386
425
|
import tensorflow as tf
|
|
387
426
|
|
|
388
|
-
from ultralytics.
|
|
427
|
+
from ultralytics.utils.export.tensorflow import gd_outputs
|
|
389
428
|
|
|
390
429
|
def wrap_frozen_graph(gd, inputs, outputs):
|
|
391
430
|
"""Wrap frozen graphs for deployment."""
|
|
@@ -441,13 +480,19 @@ class AutoBackend(nn.Module):
|
|
|
441
480
|
|
|
442
481
|
# TF.js
|
|
443
482
|
elif tfjs:
|
|
444
|
-
raise NotImplementedError("
|
|
483
|
+
raise NotImplementedError("Ultralytics TF.js inference is not currently supported.")
|
|
445
484
|
|
|
446
485
|
# PaddlePaddle
|
|
447
486
|
elif paddle:
|
|
448
487
|
LOGGER.info(f"Loading {w} for PaddlePaddle inference...")
|
|
449
|
-
check_requirements(
|
|
450
|
-
|
|
488
|
+
check_requirements(
|
|
489
|
+
"paddlepaddle-gpu"
|
|
490
|
+
if torch.cuda.is_available()
|
|
491
|
+
else "paddlepaddle==3.0.0" # pin 3.0.0 for ARM64
|
|
492
|
+
if ARM64
|
|
493
|
+
else "paddlepaddle>=3.0.0"
|
|
494
|
+
)
|
|
495
|
+
import paddle.inference as pdi
|
|
451
496
|
|
|
452
497
|
w = Path(w)
|
|
453
498
|
model_file, params_file = None, None
|
|
@@ -489,7 +534,7 @@ class AutoBackend(nn.Module):
|
|
|
489
534
|
# NCNN
|
|
490
535
|
elif ncnn:
|
|
491
536
|
LOGGER.info(f"Loading {w} for NCNN inference...")
|
|
492
|
-
check_requirements("git+https://github.com/Tencent/ncnn.git" if ARM64 else "ncnn")
|
|
537
|
+
check_requirements("git+https://github.com/Tencent/ncnn.git" if ARM64 else "ncnn", cmds="--no-deps")
|
|
493
538
|
import ncnn as pyncnn
|
|
494
539
|
|
|
495
540
|
net = pyncnn.Net()
|
|
@@ -525,6 +570,25 @@ class AutoBackend(nn.Module):
|
|
|
525
570
|
rknn_model.init_runtime()
|
|
526
571
|
metadata = w.parent / "metadata.yaml"
|
|
527
572
|
|
|
573
|
+
# ExecuTorch
|
|
574
|
+
elif pte:
|
|
575
|
+
LOGGER.info(f"Loading {w} for ExecuTorch inference...")
|
|
576
|
+
# TorchAO release compatibility table bug https://github.com/pytorch/ao/issues/2919
|
|
577
|
+
check_requirements("setuptools<71.0.0") # Setuptools bug: https://github.com/pypa/setuptools/issues/4483
|
|
578
|
+
check_requirements(("executorch==1.0.0", "flatbuffers"))
|
|
579
|
+
from executorch.runtime import Runtime
|
|
580
|
+
|
|
581
|
+
w = Path(w)
|
|
582
|
+
if w.is_dir():
|
|
583
|
+
model_file = next(w.rglob("*.pte"))
|
|
584
|
+
metadata = w / "metadata.yaml"
|
|
585
|
+
else:
|
|
586
|
+
model_file = w
|
|
587
|
+
metadata = w.parent / "metadata.yaml"
|
|
588
|
+
|
|
589
|
+
program = Runtime.get().load_program(str(model_file))
|
|
590
|
+
model = program.load_method("forward")
|
|
591
|
+
|
|
528
592
|
# Any other format (unsupported)
|
|
529
593
|
else:
|
|
530
594
|
from ultralytics.engine.exporter import export_formats
|
|
@@ -541,7 +605,7 @@ class AutoBackend(nn.Module):
|
|
|
541
605
|
for k, v in metadata.items():
|
|
542
606
|
if k in {"stride", "batch", "channels"}:
|
|
543
607
|
metadata[k] = int(v)
|
|
544
|
-
elif k in {"imgsz", "names", "kpt_shape", "args"} and isinstance(v, str):
|
|
608
|
+
elif k in {"imgsz", "names", "kpt_shape", "kpt_names", "args"} and isinstance(v, str):
|
|
545
609
|
metadata[k] = eval(v)
|
|
546
610
|
stride = metadata["stride"]
|
|
547
611
|
task = metadata["task"]
|
|
@@ -549,39 +613,41 @@ class AutoBackend(nn.Module):
|
|
|
549
613
|
imgsz = metadata["imgsz"]
|
|
550
614
|
names = metadata["names"]
|
|
551
615
|
kpt_shape = metadata.get("kpt_shape")
|
|
616
|
+
kpt_names = metadata.get("kpt_names")
|
|
552
617
|
end2end = metadata.get("args", {}).get("nms", False)
|
|
553
618
|
dynamic = metadata.get("args", {}).get("dynamic", dynamic)
|
|
554
619
|
ch = metadata.get("channels", 3)
|
|
555
620
|
elif not (pt or triton or nn_module):
|
|
556
|
-
LOGGER.warning(f"Metadata not found for 'model={
|
|
621
|
+
LOGGER.warning(f"Metadata not found for 'model={w}'")
|
|
557
622
|
|
|
558
623
|
# Check names
|
|
559
624
|
if "names" not in locals(): # names missing
|
|
560
625
|
names = default_class_names(data)
|
|
561
626
|
names = check_class_names(names)
|
|
562
627
|
|
|
563
|
-
# Disable gradients
|
|
564
|
-
if pt:
|
|
565
|
-
for p in model.parameters():
|
|
566
|
-
p.requires_grad = False
|
|
567
|
-
|
|
568
628
|
self.__dict__.update(locals()) # assign all variables to self
|
|
569
629
|
|
|
570
|
-
def forward(
|
|
571
|
-
|
|
572
|
-
|
|
630
|
+
def forward(
|
|
631
|
+
self,
|
|
632
|
+
im: torch.Tensor,
|
|
633
|
+
augment: bool = False,
|
|
634
|
+
visualize: bool = False,
|
|
635
|
+
embed: list | None = None,
|
|
636
|
+
**kwargs: Any,
|
|
637
|
+
) -> torch.Tensor | list[torch.Tensor]:
|
|
638
|
+
"""Run inference on an AutoBackend model.
|
|
573
639
|
|
|
574
640
|
Args:
|
|
575
641
|
im (torch.Tensor): The image tensor to perform inference on.
|
|
576
642
|
augment (bool): Whether to perform data augmentation during inference.
|
|
577
643
|
visualize (bool): Whether to visualize the output predictions.
|
|
578
|
-
embed (list
|
|
644
|
+
embed (list, optional): A list of feature vectors/embeddings to return.
|
|
579
645
|
**kwargs (Any): Additional keyword arguments for model configuration.
|
|
580
646
|
|
|
581
647
|
Returns:
|
|
582
|
-
(torch.Tensor |
|
|
648
|
+
(torch.Tensor | list[torch.Tensor]): The raw output tensor(s) from the model.
|
|
583
649
|
"""
|
|
584
|
-
|
|
650
|
+
_b, _ch, h, w = im.shape # batch, channel, height, width
|
|
585
651
|
if self.fp16 and im.dtype != torch.float16:
|
|
586
652
|
im = im.half() # to FP16
|
|
587
653
|
if self.nhwc:
|
|
@@ -620,8 +686,12 @@ class AutoBackend(nn.Module):
|
|
|
620
686
|
self.session.run_with_iobinding(self.io)
|
|
621
687
|
y = self.bindings
|
|
622
688
|
if self.imx:
|
|
623
|
-
|
|
624
|
-
|
|
689
|
+
if self.task == "detect":
|
|
690
|
+
# boxes, conf, cls
|
|
691
|
+
y = np.concatenate([y[0], y[1][:, :, None], y[2][:, :, None]], axis=-1)
|
|
692
|
+
elif self.task == "pose":
|
|
693
|
+
# boxes, conf, kpts
|
|
694
|
+
y = np.concatenate([y[0], y[1][:, :, None], y[2][:, :, None], y[3]], axis=-1)
|
|
625
695
|
|
|
626
696
|
# OpenVINO
|
|
627
697
|
elif self.xml:
|
|
@@ -632,7 +702,7 @@ class AutoBackend(nn.Module):
|
|
|
632
702
|
results = [None] * n # preallocate list with None to match the number of images
|
|
633
703
|
|
|
634
704
|
def callback(request, userdata):
|
|
635
|
-
"""
|
|
705
|
+
"""Place result in preallocated list using userdata index."""
|
|
636
706
|
results[userdata] = request.results
|
|
637
707
|
|
|
638
708
|
# Create AsyncInferQueue, set the callback and start asynchronous inference for each input image
|
|
@@ -642,8 +712,8 @@ class AutoBackend(nn.Module):
|
|
|
642
712
|
# Start async inference with userdata=i to specify the position in results list
|
|
643
713
|
async_queue.start_async(inputs={self.input_name: im[i : i + 1]}, userdata=i) # keep image as BCHW
|
|
644
714
|
async_queue.wait_all() # wait for all inference requests to complete
|
|
645
|
-
y =
|
|
646
|
-
|
|
715
|
+
y = [list(r.values()) for r in results]
|
|
716
|
+
y = [np.concatenate(x) for x in zip(*y)]
|
|
647
717
|
else: # inference_mode = "LATENCY", optimized for fastest first result at batch-size 1
|
|
648
718
|
y = list(self.ov_compiled_model(im).values())
|
|
649
719
|
|
|
@@ -671,21 +741,21 @@ class AutoBackend(nn.Module):
|
|
|
671
741
|
|
|
672
742
|
# CoreML
|
|
673
743
|
elif self.coreml:
|
|
674
|
-
im = im
|
|
675
|
-
|
|
744
|
+
im = im.cpu().numpy()
|
|
745
|
+
if self.dynamic:
|
|
746
|
+
im = im.transpose(0, 3, 1, 2)
|
|
747
|
+
else:
|
|
748
|
+
im = Image.fromarray((im[0] * 255).astype("uint8"))
|
|
676
749
|
# im = im.resize((192, 320), Image.BILINEAR)
|
|
677
|
-
y = self.model.predict({"image":
|
|
678
|
-
if "confidence" in y:
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
)
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
# conf, cls = y['confidence'].max(1), y['confidence'].argmax(1).astype(np.float32)
|
|
687
|
-
# y = np.concatenate((box, conf.reshape(-1, 1), cls.reshape(-1, 1)), 1)
|
|
688
|
-
y = list(y.values())
|
|
750
|
+
y = self.model.predict({"image": im}) # coordinates are xywh normalized
|
|
751
|
+
if "confidence" in y: # NMS included
|
|
752
|
+
from ultralytics.utils.ops import xywh2xyxy
|
|
753
|
+
|
|
754
|
+
box = xywh2xyxy(y["coordinates"] * [[w, h, w, h]]) # xyxy pixels
|
|
755
|
+
cls = y["confidence"].argmax(1, keepdims=True)
|
|
756
|
+
y = np.concatenate((box, np.take_along_axis(y["confidence"], cls, axis=1), cls), 1)[None]
|
|
757
|
+
else:
|
|
758
|
+
y = list(y.values())
|
|
689
759
|
if len(y) == 2 and len(y[1].shape) != 4: # segmentation model
|
|
690
760
|
y = list(reversed(y)) # reversed for segmentation models (pred, proto)
|
|
691
761
|
|
|
@@ -721,6 +791,10 @@ class AutoBackend(nn.Module):
|
|
|
721
791
|
im = im if isinstance(im, (list, tuple)) else [im]
|
|
722
792
|
y = self.rknn_model.inference(inputs=im)
|
|
723
793
|
|
|
794
|
+
# ExecuTorch
|
|
795
|
+
elif self.pte:
|
|
796
|
+
y = self.model.execute([im])
|
|
797
|
+
|
|
724
798
|
# TensorFlow (SavedModel, GraphDef, Lite, Edge TPU)
|
|
725
799
|
else:
|
|
726
800
|
im = im.cpu().numpy()
|
|
@@ -780,9 +854,8 @@ class AutoBackend(nn.Module):
|
|
|
780
854
|
else:
|
|
781
855
|
return self.from_numpy(y)
|
|
782
856
|
|
|
783
|
-
def from_numpy(self, x):
|
|
784
|
-
"""
|
|
785
|
-
Convert a numpy array to a tensor.
|
|
857
|
+
def from_numpy(self, x: np.ndarray) -> torch.Tensor:
|
|
858
|
+
"""Convert a numpy array to a tensor.
|
|
786
859
|
|
|
787
860
|
Args:
|
|
788
861
|
x (np.ndarray): The array to be converted.
|
|
@@ -792,34 +865,33 @@ class AutoBackend(nn.Module):
|
|
|
792
865
|
"""
|
|
793
866
|
return torch.tensor(x).to(self.device) if isinstance(x, np.ndarray) else x
|
|
794
867
|
|
|
795
|
-
def warmup(self, imgsz=(1, 3, 640, 640)):
|
|
796
|
-
"""
|
|
797
|
-
Warm up the model by running one forward pass with a dummy input.
|
|
868
|
+
def warmup(self, imgsz: tuple[int, int, int, int] = (1, 3, 640, 640)) -> None:
|
|
869
|
+
"""Warm up the model by running one forward pass with a dummy input.
|
|
798
870
|
|
|
799
871
|
Args:
|
|
800
872
|
imgsz (tuple): The shape of the dummy input tensor in the format (batch_size, channels, height, width)
|
|
801
873
|
"""
|
|
802
|
-
import torchvision # noqa (import here so torchvision import time not recorded in postprocess time)
|
|
803
|
-
|
|
804
874
|
warmup_types = self.pt, self.jit, self.onnx, self.engine, self.saved_model, self.pb, self.triton, self.nn_module
|
|
805
875
|
if any(warmup_types) and (self.device.type != "cpu" or self.triton):
|
|
806
876
|
im = torch.empty(*imgsz, dtype=torch.half if self.fp16 else torch.float, device=self.device) # input
|
|
807
877
|
for _ in range(2 if self.jit else 1):
|
|
808
|
-
self.forward(im) # warmup
|
|
878
|
+
self.forward(im) # warmup model
|
|
879
|
+
warmup_boxes = torch.rand(1, 84, 16, device=self.device) # 16 boxes works best empirically
|
|
880
|
+
warmup_boxes[:, :4] *= imgsz[-1]
|
|
881
|
+
non_max_suppression(warmup_boxes) # warmup NMS
|
|
809
882
|
|
|
810
883
|
@staticmethod
|
|
811
|
-
def _model_type(p="path/to/model.pt"):
|
|
812
|
-
"""
|
|
813
|
-
Takes a path to a model file and returns the model type.
|
|
884
|
+
def _model_type(p: str = "path/to/model.pt") -> list[bool]:
|
|
885
|
+
"""Take a path to a model file and return the model type.
|
|
814
886
|
|
|
815
887
|
Args:
|
|
816
888
|
p (str): Path to the model file.
|
|
817
889
|
|
|
818
890
|
Returns:
|
|
819
|
-
(
|
|
891
|
+
(list[bool]): List of booleans indicating the model type.
|
|
820
892
|
|
|
821
893
|
Examples:
|
|
822
|
-
>>> model = AutoBackend(
|
|
894
|
+
>>> model = AutoBackend(model="path/to/model.onnx")
|
|
823
895
|
>>> model_type = model._model_type() # returns "onnx"
|
|
824
896
|
"""
|
|
825
897
|
from ultralytics.engine.exporter import export_formats
|
|
@@ -839,4 +911,4 @@ class AutoBackend(nn.Module):
|
|
|
839
911
|
url = urlsplit(p)
|
|
840
912
|
triton = bool(url.netloc) and bool(url.path) and url.scheme in {"http", "grpc"}
|
|
841
913
|
|
|
842
|
-
return types
|
|
914
|
+
return [*types, triton]
|