ultralytics 8.0.238__py3-none-any.whl → 8.0.239__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.
Potentially problematic release.
This version of ultralytics might be problematic. Click here for more details.
- ultralytics/__init__.py +2 -2
- ultralytics/cfg/__init__.py +241 -138
- ultralytics/data/__init__.py +9 -2
- ultralytics/data/annotator.py +4 -4
- ultralytics/data/augment.py +186 -169
- ultralytics/data/base.py +54 -48
- ultralytics/data/build.py +34 -23
- ultralytics/data/converter.py +242 -70
- ultralytics/data/dataset.py +117 -95
- ultralytics/data/explorer/__init__.py +3 -1
- ultralytics/data/explorer/explorer.py +120 -100
- ultralytics/data/explorer/gui/__init__.py +1 -0
- ultralytics/data/explorer/gui/dash.py +123 -89
- ultralytics/data/explorer/utils.py +37 -39
- ultralytics/data/loaders.py +75 -62
- ultralytics/data/split_dota.py +44 -36
- ultralytics/data/utils.py +160 -142
- ultralytics/engine/exporter.py +348 -292
- ultralytics/engine/model.py +102 -66
- ultralytics/engine/predictor.py +74 -55
- ultralytics/engine/results.py +61 -41
- ultralytics/engine/trainer.py +192 -144
- ultralytics/engine/tuner.py +66 -59
- ultralytics/engine/validator.py +31 -26
- ultralytics/hub/__init__.py +54 -31
- ultralytics/hub/auth.py +28 -25
- ultralytics/hub/session.py +282 -133
- ultralytics/hub/utils.py +64 -42
- ultralytics/models/__init__.py +1 -1
- ultralytics/models/fastsam/__init__.py +1 -1
- ultralytics/models/fastsam/model.py +6 -6
- ultralytics/models/fastsam/predict.py +3 -2
- ultralytics/models/fastsam/prompt.py +55 -48
- ultralytics/models/fastsam/val.py +1 -1
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/nas/model.py +9 -8
- ultralytics/models/nas/predict.py +8 -6
- ultralytics/models/nas/val.py +11 -9
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/rtdetr/model.py +11 -9
- ultralytics/models/rtdetr/train.py +18 -16
- ultralytics/models/rtdetr/val.py +25 -19
- ultralytics/models/sam/__init__.py +1 -1
- ultralytics/models/sam/amg.py +13 -14
- ultralytics/models/sam/build.py +44 -42
- ultralytics/models/sam/model.py +6 -6
- ultralytics/models/sam/modules/decoders.py +6 -4
- ultralytics/models/sam/modules/encoders.py +37 -35
- ultralytics/models/sam/modules/sam.py +5 -4
- ultralytics/models/sam/modules/tiny_encoder.py +95 -73
- ultralytics/models/sam/modules/transformer.py +3 -2
- ultralytics/models/sam/predict.py +39 -27
- ultralytics/models/utils/loss.py +99 -95
- ultralytics/models/utils/ops.py +34 -31
- ultralytics/models/yolo/__init__.py +1 -1
- ultralytics/models/yolo/classify/__init__.py +1 -1
- ultralytics/models/yolo/classify/predict.py +8 -6
- ultralytics/models/yolo/classify/train.py +37 -31
- ultralytics/models/yolo/classify/val.py +26 -24
- ultralytics/models/yolo/detect/__init__.py +1 -1
- ultralytics/models/yolo/detect/predict.py +8 -6
- ultralytics/models/yolo/detect/train.py +47 -37
- ultralytics/models/yolo/detect/val.py +100 -82
- ultralytics/models/yolo/model.py +31 -25
- ultralytics/models/yolo/obb/__init__.py +1 -1
- ultralytics/models/yolo/obb/predict.py +13 -11
- ultralytics/models/yolo/obb/train.py +3 -3
- ultralytics/models/yolo/obb/val.py +70 -59
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +17 -12
- ultralytics/models/yolo/pose/train.py +28 -25
- ultralytics/models/yolo/pose/val.py +91 -64
- ultralytics/models/yolo/segment/__init__.py +1 -1
- ultralytics/models/yolo/segment/predict.py +10 -8
- ultralytics/models/yolo/segment/train.py +16 -15
- ultralytics/models/yolo/segment/val.py +90 -68
- ultralytics/nn/__init__.py +26 -6
- ultralytics/nn/autobackend.py +144 -112
- ultralytics/nn/modules/__init__.py +96 -13
- ultralytics/nn/modules/block.py +28 -7
- ultralytics/nn/modules/conv.py +41 -23
- ultralytics/nn/modules/head.py +60 -52
- ultralytics/nn/modules/transformer.py +49 -32
- ultralytics/nn/modules/utils.py +20 -15
- ultralytics/nn/tasks.py +215 -141
- ultralytics/solutions/ai_gym.py +59 -47
- ultralytics/solutions/distance_calculation.py +17 -14
- ultralytics/solutions/heatmap.py +57 -55
- ultralytics/solutions/object_counter.py +46 -39
- ultralytics/solutions/speed_estimation.py +13 -16
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/basetrack.py +1 -0
- ultralytics/trackers/bot_sort.py +2 -1
- ultralytics/trackers/byte_tracker.py +10 -7
- ultralytics/trackers/track.py +7 -7
- ultralytics/trackers/utils/gmc.py +25 -25
- ultralytics/trackers/utils/kalman_filter.py +85 -42
- ultralytics/trackers/utils/matching.py +8 -7
- ultralytics/utils/__init__.py +173 -152
- ultralytics/utils/autobatch.py +10 -10
- ultralytics/utils/benchmarks.py +76 -86
- ultralytics/utils/callbacks/__init__.py +1 -1
- ultralytics/utils/callbacks/base.py +29 -29
- ultralytics/utils/callbacks/clearml.py +51 -43
- ultralytics/utils/callbacks/comet.py +81 -66
- ultralytics/utils/callbacks/dvc.py +33 -26
- ultralytics/utils/callbacks/hub.py +44 -26
- ultralytics/utils/callbacks/mlflow.py +31 -24
- ultralytics/utils/callbacks/neptune.py +35 -25
- ultralytics/utils/callbacks/raytune.py +9 -4
- ultralytics/utils/callbacks/tensorboard.py +16 -11
- ultralytics/utils/callbacks/wb.py +39 -33
- ultralytics/utils/checks.py +189 -141
- ultralytics/utils/dist.py +15 -12
- ultralytics/utils/downloads.py +112 -96
- ultralytics/utils/errors.py +1 -1
- ultralytics/utils/files.py +11 -11
- ultralytics/utils/instance.py +22 -22
- ultralytics/utils/loss.py +117 -67
- ultralytics/utils/metrics.py +224 -158
- ultralytics/utils/ops.py +38 -28
- ultralytics/utils/patches.py +3 -3
- ultralytics/utils/plotting.py +217 -120
- ultralytics/utils/tal.py +19 -13
- ultralytics/utils/torch_utils.py +138 -109
- ultralytics/utils/triton.py +12 -10
- ultralytics/utils/tuner.py +49 -47
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/METADATA +2 -1
- ultralytics-8.0.239.dist-info/RECORD +188 -0
- ultralytics-8.0.238.dist-info/RECORD +0 -188
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/LICENSE +0 -0
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/WHEEL +0 -0
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/top_level.txt +0 -0
ultralytics/nn/__init__.py
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
|
2
2
|
|
|
3
|
-
from .tasks import (
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
from .tasks import (
|
|
4
|
+
BaseModel,
|
|
5
|
+
ClassificationModel,
|
|
6
|
+
DetectionModel,
|
|
7
|
+
SegmentationModel,
|
|
8
|
+
attempt_load_one_weight,
|
|
9
|
+
attempt_load_weights,
|
|
10
|
+
guess_model_scale,
|
|
11
|
+
guess_model_task,
|
|
12
|
+
parse_model,
|
|
13
|
+
torch_safe_load,
|
|
14
|
+
yaml_model_load,
|
|
15
|
+
)
|
|
6
16
|
|
|
7
|
-
__all__ = (
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
__all__ = (
|
|
18
|
+
"attempt_load_one_weight",
|
|
19
|
+
"attempt_load_weights",
|
|
20
|
+
"parse_model",
|
|
21
|
+
"yaml_model_load",
|
|
22
|
+
"guess_model_task",
|
|
23
|
+
"guess_model_scale",
|
|
24
|
+
"torch_safe_load",
|
|
25
|
+
"DetectionModel",
|
|
26
|
+
"SegmentationModel",
|
|
27
|
+
"ClassificationModel",
|
|
28
|
+
"BaseModel",
|
|
29
|
+
)
|
ultralytics/nn/autobackend.py
CHANGED
|
@@ -32,10 +32,12 @@ def check_class_names(names):
|
|
|
32
32
|
names = {int(k): str(v) for k, v in names.items()}
|
|
33
33
|
n = len(names)
|
|
34
34
|
if max(names.keys()) >= n:
|
|
35
|
-
raise KeyError(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
raise KeyError(
|
|
36
|
+
f"{n}-class dataset requires class indices 0-{n - 1}, but you have invalid class indices "
|
|
37
|
+
f"{min(names.keys())}-{max(names.keys())} defined in your dataset YAML."
|
|
38
|
+
)
|
|
39
|
+
if isinstance(names[0], str) and names[0].startswith("n0"): # imagenet class codes, i.e. 'n01440764'
|
|
40
|
+
names_map = yaml_load(ROOT / "cfg/datasets/ImageNet.yaml")["map"] # human-readable names
|
|
39
41
|
names = {k: names_map[v] for k, v in names.items()}
|
|
40
42
|
return names
|
|
41
43
|
|
|
@@ -44,8 +46,8 @@ def default_class_names(data=None):
|
|
|
44
46
|
"""Applies default class names to an input YAML file or returns numerical class names."""
|
|
45
47
|
if data:
|
|
46
48
|
with contextlib.suppress(Exception):
|
|
47
|
-
return yaml_load(check_yaml(data))[
|
|
48
|
-
return {i: f
|
|
49
|
+
return yaml_load(check_yaml(data))["names"]
|
|
50
|
+
return {i: f"class{i}" for i in range(999)} # return default if above errors
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
class AutoBackend(nn.Module):
|
|
@@ -77,14 +79,16 @@ class AutoBackend(nn.Module):
|
|
|
77
79
|
"""
|
|
78
80
|
|
|
79
81
|
@torch.no_grad()
|
|
80
|
-
def __init__(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
weights="yolov8n.pt",
|
|
85
|
+
device=torch.device("cpu"),
|
|
86
|
+
dnn=False,
|
|
87
|
+
data=None,
|
|
88
|
+
fp16=False,
|
|
89
|
+
fuse=True,
|
|
90
|
+
verbose=True,
|
|
91
|
+
):
|
|
88
92
|
"""
|
|
89
93
|
Initialize the AutoBackend for inference.
|
|
90
94
|
|
|
@@ -100,17 +104,31 @@ class AutoBackend(nn.Module):
|
|
|
100
104
|
super().__init__()
|
|
101
105
|
w = str(weights[0] if isinstance(weights, list) else weights)
|
|
102
106
|
nn_module = isinstance(weights, torch.nn.Module)
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
(
|
|
108
|
+
pt,
|
|
109
|
+
jit,
|
|
110
|
+
onnx,
|
|
111
|
+
xml,
|
|
112
|
+
engine,
|
|
113
|
+
coreml,
|
|
114
|
+
saved_model,
|
|
115
|
+
pb,
|
|
116
|
+
tflite,
|
|
117
|
+
edgetpu,
|
|
118
|
+
tfjs,
|
|
119
|
+
paddle,
|
|
120
|
+
ncnn,
|
|
121
|
+
triton,
|
|
122
|
+
) = self._model_type(w)
|
|
105
123
|
fp16 &= pt or jit or onnx or xml or engine or nn_module or triton # FP16
|
|
106
124
|
nhwc = coreml or saved_model or pb or tflite or edgetpu # BHWC formats (vs torch BCWH)
|
|
107
125
|
stride = 32 # default stride
|
|
108
126
|
model, metadata = None, None
|
|
109
127
|
|
|
110
128
|
# Set device
|
|
111
|
-
cuda = torch.cuda.is_available() and device.type !=
|
|
129
|
+
cuda = torch.cuda.is_available() and device.type != "cpu" # use CUDA
|
|
112
130
|
if cuda and not any([nn_module, pt, jit, engine, onnx]): # GPU dataloader formats
|
|
113
|
-
device = torch.device(
|
|
131
|
+
device = torch.device("cpu")
|
|
114
132
|
cuda = False
|
|
115
133
|
|
|
116
134
|
# Download if not local
|
|
@@ -121,77 +139,79 @@ class AutoBackend(nn.Module):
|
|
|
121
139
|
if nn_module: # in-memory PyTorch model
|
|
122
140
|
model = weights.to(device)
|
|
123
141
|
model = model.fuse(verbose=verbose) if fuse else model
|
|
124
|
-
if hasattr(model,
|
|
142
|
+
if hasattr(model, "kpt_shape"):
|
|
125
143
|
kpt_shape = model.kpt_shape # pose-only
|
|
126
144
|
stride = max(int(model.stride.max()), 32) # model stride
|
|
127
|
-
names = model.module.names if hasattr(model,
|
|
145
|
+
names = model.module.names if hasattr(model, "module") else model.names # get class names
|
|
128
146
|
model.half() if fp16 else model.float()
|
|
129
147
|
self.model = model # explicitly assign for to(), cpu(), cuda(), half()
|
|
130
148
|
pt = True
|
|
131
149
|
elif pt: # PyTorch
|
|
132
150
|
from ultralytics.nn.tasks import attempt_load_weights
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if hasattr(model,
|
|
151
|
+
|
|
152
|
+
model = attempt_load_weights(
|
|
153
|
+
weights if isinstance(weights, list) else w, device=device, inplace=True, fuse=fuse
|
|
154
|
+
)
|
|
155
|
+
if hasattr(model, "kpt_shape"):
|
|
138
156
|
kpt_shape = model.kpt_shape # pose-only
|
|
139
157
|
stride = max(int(model.stride.max()), 32) # model stride
|
|
140
|
-
names = model.module.names if hasattr(model,
|
|
158
|
+
names = model.module.names if hasattr(model, "module") else model.names # get class names
|
|
141
159
|
model.half() if fp16 else model.float()
|
|
142
160
|
self.model = model # explicitly assign for to(), cpu(), cuda(), half()
|
|
143
161
|
elif jit: # TorchScript
|
|
144
|
-
LOGGER.info(f
|
|
145
|
-
extra_files = {
|
|
162
|
+
LOGGER.info(f"Loading {w} for TorchScript inference...")
|
|
163
|
+
extra_files = {"config.txt": ""} # model metadata
|
|
146
164
|
model = torch.jit.load(w, _extra_files=extra_files, map_location=device)
|
|
147
165
|
model.half() if fp16 else model.float()
|
|
148
|
-
if extra_files[
|
|
149
|
-
metadata = json.loads(extra_files[
|
|
166
|
+
if extra_files["config.txt"]: # load metadata dict
|
|
167
|
+
metadata = json.loads(extra_files["config.txt"], object_hook=lambda x: dict(x.items()))
|
|
150
168
|
elif dnn: # ONNX OpenCV DNN
|
|
151
|
-
LOGGER.info(f
|
|
152
|
-
check_requirements(
|
|
169
|
+
LOGGER.info(f"Loading {w} for ONNX OpenCV DNN inference...")
|
|
170
|
+
check_requirements("opencv-python>=4.5.4")
|
|
153
171
|
net = cv2.dnn.readNetFromONNX(w)
|
|
154
172
|
elif onnx: # ONNX Runtime
|
|
155
|
-
LOGGER.info(f
|
|
156
|
-
check_requirements((
|
|
173
|
+
LOGGER.info(f"Loading {w} for ONNX Runtime inference...")
|
|
174
|
+
check_requirements(("onnx", "onnxruntime-gpu" if cuda else "onnxruntime"))
|
|
157
175
|
import onnxruntime
|
|
158
|
-
|
|
176
|
+
|
|
177
|
+
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] if cuda else ["CPUExecutionProvider"]
|
|
159
178
|
session = onnxruntime.InferenceSession(w, providers=providers)
|
|
160
179
|
output_names = [x.name for x in session.get_outputs()]
|
|
161
180
|
metadata = session.get_modelmeta().custom_metadata_map # metadata
|
|
162
181
|
elif xml: # OpenVINO
|
|
163
|
-
LOGGER.info(f
|
|
164
|
-
check_requirements(
|
|
182
|
+
LOGGER.info(f"Loading {w} for OpenVINO inference...")
|
|
183
|
+
check_requirements("openvino>=2023.0") # requires openvino-dev: https://pypi.org/project/openvino-dev/
|
|
165
184
|
from openvino.runtime import Core, Layout, get_batch # noqa
|
|
185
|
+
|
|
166
186
|
core = Core()
|
|
167
187
|
w = Path(w)
|
|
168
188
|
if not w.is_file(): # if not *.xml
|
|
169
|
-
w = next(w.glob(
|
|
170
|
-
ov_model = core.read_model(model=str(w), weights=w.with_suffix(
|
|
189
|
+
w = next(w.glob("*.xml")) # get *.xml file from *_openvino_model dir
|
|
190
|
+
ov_model = core.read_model(model=str(w), weights=w.with_suffix(".bin"))
|
|
171
191
|
if ov_model.get_parameters()[0].get_layout().empty:
|
|
172
|
-
ov_model.get_parameters()[0].set_layout(Layout(
|
|
192
|
+
ov_model.get_parameters()[0].set_layout(Layout("NCHW"))
|
|
173
193
|
batch_dim = get_batch(ov_model)
|
|
174
194
|
if batch_dim.is_static:
|
|
175
195
|
batch_size = batch_dim.get_length()
|
|
176
|
-
ov_compiled_model = core.compile_model(ov_model, device_name=
|
|
177
|
-
metadata = w.parent /
|
|
196
|
+
ov_compiled_model = core.compile_model(ov_model, device_name="AUTO") # AUTO selects best available device
|
|
197
|
+
metadata = w.parent / "metadata.yaml"
|
|
178
198
|
elif engine: # TensorRT
|
|
179
|
-
LOGGER.info(f
|
|
199
|
+
LOGGER.info(f"Loading {w} for TensorRT inference...")
|
|
180
200
|
try:
|
|
181
201
|
import tensorrt as trt # noqa https://developer.nvidia.com/nvidia-tensorrt-download
|
|
182
202
|
except ImportError:
|
|
183
203
|
if LINUX:
|
|
184
|
-
check_requirements(
|
|
204
|
+
check_requirements("nvidia-tensorrt", cmds="-U --index-url https://pypi.ngc.nvidia.com")
|
|
185
205
|
import tensorrt as trt # noqa
|
|
186
|
-
check_version(trt.__version__,
|
|
187
|
-
if device.type ==
|
|
188
|
-
device = torch.device(
|
|
189
|
-
Binding = namedtuple(
|
|
206
|
+
check_version(trt.__version__, "7.0.0", hard=True) # require tensorrt>=7.0.0
|
|
207
|
+
if device.type == "cpu":
|
|
208
|
+
device = torch.device("cuda:0")
|
|
209
|
+
Binding = namedtuple("Binding", ("name", "dtype", "shape", "data", "ptr"))
|
|
190
210
|
logger = trt.Logger(trt.Logger.INFO)
|
|
191
211
|
# Read file
|
|
192
|
-
with open(w,
|
|
193
|
-
meta_len = int.from_bytes(f.read(4), byteorder=
|
|
194
|
-
metadata = json.loads(f.read(meta_len).decode(
|
|
212
|
+
with open(w, "rb") as f, trt.Runtime(logger) as runtime:
|
|
213
|
+
meta_len = int.from_bytes(f.read(4), byteorder="little") # read metadata length
|
|
214
|
+
metadata = json.loads(f.read(meta_len).decode("utf-8")) # read metadata
|
|
195
215
|
model = runtime.deserialize_cuda_engine(f.read()) # read engine
|
|
196
216
|
context = model.create_execution_context()
|
|
197
217
|
bindings = OrderedDict()
|
|
@@ -213,116 +233,124 @@ class AutoBackend(nn.Module):
|
|
|
213
233
|
im = torch.from_numpy(np.empty(shape, dtype=dtype)).to(device)
|
|
214
234
|
bindings[name] = Binding(name, dtype, shape, im, int(im.data_ptr()))
|
|
215
235
|
binding_addrs = OrderedDict((n, d.ptr) for n, d in bindings.items())
|
|
216
|
-
batch_size = bindings[
|
|
236
|
+
batch_size = bindings["images"].shape[0] # if dynamic, this is instead max batch size
|
|
217
237
|
elif coreml: # CoreML
|
|
218
|
-
LOGGER.info(f
|
|
238
|
+
LOGGER.info(f"Loading {w} for CoreML inference...")
|
|
219
239
|
import coremltools as ct
|
|
240
|
+
|
|
220
241
|
model = ct.models.MLModel(w)
|
|
221
242
|
metadata = dict(model.user_defined_metadata)
|
|
222
243
|
elif saved_model: # TF SavedModel
|
|
223
|
-
LOGGER.info(f
|
|
244
|
+
LOGGER.info(f"Loading {w} for TensorFlow SavedModel inference...")
|
|
224
245
|
import tensorflow as tf
|
|
246
|
+
|
|
225
247
|
keras = False # assume TF1 saved_model
|
|
226
248
|
model = tf.keras.models.load_model(w) if keras else tf.saved_model.load(w)
|
|
227
|
-
metadata = Path(w) /
|
|
249
|
+
metadata = Path(w) / "metadata.yaml"
|
|
228
250
|
elif pb: # GraphDef https://www.tensorflow.org/guide/migrate#a_graphpb_or_graphpbtxt
|
|
229
|
-
LOGGER.info(f
|
|
251
|
+
LOGGER.info(f"Loading {w} for TensorFlow GraphDef inference...")
|
|
230
252
|
import tensorflow as tf
|
|
231
253
|
|
|
232
254
|
from ultralytics.engine.exporter import gd_outputs
|
|
233
255
|
|
|
234
256
|
def wrap_frozen_graph(gd, inputs, outputs):
|
|
235
257
|
"""Wrap frozen graphs for deployment."""
|
|
236
|
-
x = tf.compat.v1.wrap_function(lambda: tf.compat.v1.import_graph_def(gd, name=
|
|
258
|
+
x = tf.compat.v1.wrap_function(lambda: tf.compat.v1.import_graph_def(gd, name=""), []) # wrapped
|
|
237
259
|
ge = x.graph.as_graph_element
|
|
238
260
|
return x.prune(tf.nest.map_structure(ge, inputs), tf.nest.map_structure(ge, outputs))
|
|
239
261
|
|
|
240
262
|
gd = tf.Graph().as_graph_def() # TF GraphDef
|
|
241
|
-
with open(w,
|
|
263
|
+
with open(w, "rb") as f:
|
|
242
264
|
gd.ParseFromString(f.read())
|
|
243
|
-
frozen_func = wrap_frozen_graph(gd, inputs=
|
|
265
|
+
frozen_func = wrap_frozen_graph(gd, inputs="x:0", outputs=gd_outputs(gd))
|
|
244
266
|
elif tflite or edgetpu: # https://www.tensorflow.org/lite/guide/python#install_tensorflow_lite_for_python
|
|
245
267
|
try: # https://coral.ai/docs/edgetpu/tflite-python/#update-existing-tf-lite-code-for-the-edge-tpu
|
|
246
268
|
from tflite_runtime.interpreter import Interpreter, load_delegate
|
|
247
269
|
except ImportError:
|
|
248
270
|
import tensorflow as tf
|
|
271
|
+
|
|
249
272
|
Interpreter, load_delegate = tf.lite.Interpreter, tf.lite.experimental.load_delegate
|
|
250
273
|
if edgetpu: # TF Edge TPU https://coral.ai/software/#edgetpu-runtime
|
|
251
|
-
LOGGER.info(f
|
|
252
|
-
delegate = {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
'Windows': 'edgetpu.dll'}[platform.system()]
|
|
274
|
+
LOGGER.info(f"Loading {w} for TensorFlow Lite Edge TPU inference...")
|
|
275
|
+
delegate = {"Linux": "libedgetpu.so.1", "Darwin": "libedgetpu.1.dylib", "Windows": "edgetpu.dll"}[
|
|
276
|
+
platform.system()
|
|
277
|
+
]
|
|
256
278
|
interpreter = Interpreter(model_path=w, experimental_delegates=[load_delegate(delegate)])
|
|
257
279
|
else: # TFLite
|
|
258
|
-
LOGGER.info(f
|
|
280
|
+
LOGGER.info(f"Loading {w} for TensorFlow Lite inference...")
|
|
259
281
|
interpreter = Interpreter(model_path=w) # load TFLite model
|
|
260
282
|
interpreter.allocate_tensors() # allocate
|
|
261
283
|
input_details = interpreter.get_input_details() # inputs
|
|
262
284
|
output_details = interpreter.get_output_details() # outputs
|
|
263
285
|
# Load metadata
|
|
264
286
|
with contextlib.suppress(zipfile.BadZipFile):
|
|
265
|
-
with zipfile.ZipFile(w,
|
|
287
|
+
with zipfile.ZipFile(w, "r") as model:
|
|
266
288
|
meta_file = model.namelist()[0]
|
|
267
|
-
metadata = ast.literal_eval(model.read(meta_file).decode(
|
|
289
|
+
metadata = ast.literal_eval(model.read(meta_file).decode("utf-8"))
|
|
268
290
|
elif tfjs: # TF.js
|
|
269
|
-
raise NotImplementedError(
|
|
291
|
+
raise NotImplementedError("YOLOv8 TF.js inference is not currently supported.")
|
|
270
292
|
elif paddle: # PaddlePaddle
|
|
271
|
-
LOGGER.info(f
|
|
272
|
-
check_requirements(
|
|
293
|
+
LOGGER.info(f"Loading {w} for PaddlePaddle inference...")
|
|
294
|
+
check_requirements("paddlepaddle-gpu" if cuda else "paddlepaddle")
|
|
273
295
|
import paddle.inference as pdi # noqa
|
|
296
|
+
|
|
274
297
|
w = Path(w)
|
|
275
298
|
if not w.is_file(): # if not *.pdmodel
|
|
276
|
-
w = next(w.rglob(
|
|
277
|
-
config = pdi.Config(str(w), str(w.with_suffix(
|
|
299
|
+
w = next(w.rglob("*.pdmodel")) # get *.pdmodel file from *_paddle_model dir
|
|
300
|
+
config = pdi.Config(str(w), str(w.with_suffix(".pdiparams")))
|
|
278
301
|
if cuda:
|
|
279
302
|
config.enable_use_gpu(memory_pool_init_size_mb=2048, device_id=0)
|
|
280
303
|
predictor = pdi.create_predictor(config)
|
|
281
304
|
input_handle = predictor.get_input_handle(predictor.get_input_names()[0])
|
|
282
305
|
output_names = predictor.get_output_names()
|
|
283
|
-
metadata = w.parents[1] /
|
|
306
|
+
metadata = w.parents[1] / "metadata.yaml"
|
|
284
307
|
elif ncnn: # ncnn
|
|
285
|
-
LOGGER.info(f
|
|
286
|
-
check_requirements(
|
|
308
|
+
LOGGER.info(f"Loading {w} for ncnn inference...")
|
|
309
|
+
check_requirements("git+https://github.com/Tencent/ncnn.git" if ARM64 else "ncnn") # requires ncnn
|
|
287
310
|
import ncnn as pyncnn
|
|
311
|
+
|
|
288
312
|
net = pyncnn.Net()
|
|
289
313
|
net.opt.use_vulkan_compute = cuda
|
|
290
314
|
w = Path(w)
|
|
291
315
|
if not w.is_file(): # if not *.param
|
|
292
|
-
w = next(w.glob(
|
|
316
|
+
w = next(w.glob("*.param")) # get *.param file from *_ncnn_model dir
|
|
293
317
|
net.load_param(str(w))
|
|
294
|
-
net.load_model(str(w.with_suffix(
|
|
295
|
-
metadata = w.parent /
|
|
318
|
+
net.load_model(str(w.with_suffix(".bin")))
|
|
319
|
+
metadata = w.parent / "metadata.yaml"
|
|
296
320
|
elif triton: # NVIDIA Triton Inference Server
|
|
297
|
-
check_requirements(
|
|
321
|
+
check_requirements("tritonclient[all]")
|
|
298
322
|
from ultralytics.utils.triton import TritonRemoteModel
|
|
323
|
+
|
|
299
324
|
model = TritonRemoteModel(w)
|
|
300
325
|
else:
|
|
301
326
|
from ultralytics.engine.exporter import export_formats
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
327
|
+
|
|
328
|
+
raise TypeError(
|
|
329
|
+
f"model='{w}' is not a supported model format. "
|
|
330
|
+
"See https://docs.ultralytics.com/modes/predict for help."
|
|
331
|
+
f"\n\n{export_formats()}"
|
|
332
|
+
)
|
|
305
333
|
|
|
306
334
|
# Load external metadata YAML
|
|
307
335
|
if isinstance(metadata, (str, Path)) and Path(metadata).exists():
|
|
308
336
|
metadata = yaml_load(metadata)
|
|
309
337
|
if metadata:
|
|
310
338
|
for k, v in metadata.items():
|
|
311
|
-
if k in (
|
|
339
|
+
if k in ("stride", "batch"):
|
|
312
340
|
metadata[k] = int(v)
|
|
313
|
-
elif k in (
|
|
341
|
+
elif k in ("imgsz", "names", "kpt_shape") and isinstance(v, str):
|
|
314
342
|
metadata[k] = eval(v)
|
|
315
|
-
stride = metadata[
|
|
316
|
-
task = metadata[
|
|
317
|
-
batch = metadata[
|
|
318
|
-
imgsz = metadata[
|
|
319
|
-
names = metadata[
|
|
320
|
-
kpt_shape = metadata.get(
|
|
343
|
+
stride = metadata["stride"]
|
|
344
|
+
task = metadata["task"]
|
|
345
|
+
batch = metadata["batch"]
|
|
346
|
+
imgsz = metadata["imgsz"]
|
|
347
|
+
names = metadata["names"]
|
|
348
|
+
kpt_shape = metadata.get("kpt_shape")
|
|
321
349
|
elif not (pt or triton or nn_module):
|
|
322
350
|
LOGGER.warning(f"WARNING ⚠️ Metadata not found for 'model={weights}'")
|
|
323
351
|
|
|
324
352
|
# Check names
|
|
325
|
-
if
|
|
353
|
+
if "names" not in locals(): # names missing
|
|
326
354
|
names = default_class_names(data)
|
|
327
355
|
names = check_class_names(names)
|
|
328
356
|
|
|
@@ -367,26 +395,28 @@ class AutoBackend(nn.Module):
|
|
|
367
395
|
im = im.cpu().numpy() # FP32
|
|
368
396
|
y = list(self.ov_compiled_model(im).values())
|
|
369
397
|
elif self.engine: # TensorRT
|
|
370
|
-
if self.dynamic and im.shape != self.bindings[
|
|
371
|
-
i = self.model.get_binding_index(
|
|
398
|
+
if self.dynamic and im.shape != self.bindings["images"].shape:
|
|
399
|
+
i = self.model.get_binding_index("images")
|
|
372
400
|
self.context.set_binding_shape(i, im.shape) # reshape if dynamic
|
|
373
|
-
self.bindings[
|
|
401
|
+
self.bindings["images"] = self.bindings["images"]._replace(shape=im.shape)
|
|
374
402
|
for name in self.output_names:
|
|
375
403
|
i = self.model.get_binding_index(name)
|
|
376
404
|
self.bindings[name].data.resize_(tuple(self.context.get_binding_shape(i)))
|
|
377
|
-
s = self.bindings[
|
|
405
|
+
s = self.bindings["images"].shape
|
|
378
406
|
assert im.shape == s, f"input size {im.shape} {'>' if self.dynamic else 'not equal to'} max model size {s}"
|
|
379
|
-
self.binding_addrs[
|
|
407
|
+
self.binding_addrs["images"] = int(im.data_ptr())
|
|
380
408
|
self.context.execute_v2(list(self.binding_addrs.values()))
|
|
381
409
|
y = [self.bindings[x].data for x in sorted(self.output_names)]
|
|
382
410
|
elif self.coreml: # CoreML
|
|
383
411
|
im = im[0].cpu().numpy()
|
|
384
|
-
im_pil = Image.fromarray((im * 255).astype(
|
|
412
|
+
im_pil = Image.fromarray((im * 255).astype("uint8"))
|
|
385
413
|
# im = im.resize((192, 320), Image.BILINEAR)
|
|
386
|
-
y = self.model.predict({
|
|
387
|
-
if
|
|
388
|
-
raise TypeError(
|
|
389
|
-
|
|
414
|
+
y = self.model.predict({"image": im_pil}) # coordinates are xywh normalized
|
|
415
|
+
if "confidence" in y:
|
|
416
|
+
raise TypeError(
|
|
417
|
+
"Ultralytics only supports inference of non-pipelined CoreML models exported with "
|
|
418
|
+
f"'nms=False', but 'model={w}' has an NMS pipeline created by an 'nms=True' export."
|
|
419
|
+
)
|
|
390
420
|
# TODO: CoreML NMS inference handling
|
|
391
421
|
# from ultralytics.utils.ops import xywh2xyxy
|
|
392
422
|
# box = xywh2xyxy(y['coordinates'] * [[w, h, w, h]]) # xyxy pixels
|
|
@@ -425,20 +455,20 @@ class AutoBackend(nn.Module):
|
|
|
425
455
|
if len(y) == 2 and len(self.names) == 999: # segments and names not defined
|
|
426
456
|
ip, ib = (0, 1) if len(y[0].shape) == 4 else (1, 0) # index of protos, boxes
|
|
427
457
|
nc = y[ib].shape[1] - y[ip].shape[3] - 4 # y = (1, 160, 160, 32), (1, 116, 8400)
|
|
428
|
-
self.names = {i: f
|
|
458
|
+
self.names = {i: f"class{i}" for i in range(nc)}
|
|
429
459
|
else: # Lite or Edge TPU
|
|
430
460
|
details = self.input_details[0]
|
|
431
|
-
integer = details[
|
|
461
|
+
integer = details["dtype"] in (np.int8, np.int16) # is TFLite quantized int8 or int16 model
|
|
432
462
|
if integer:
|
|
433
|
-
scale, zero_point = details[
|
|
434
|
-
im = (im / scale + zero_point).astype(details[
|
|
435
|
-
self.interpreter.set_tensor(details[
|
|
463
|
+
scale, zero_point = details["quantization"]
|
|
464
|
+
im = (im / scale + zero_point).astype(details["dtype"]) # de-scale
|
|
465
|
+
self.interpreter.set_tensor(details["index"], im)
|
|
436
466
|
self.interpreter.invoke()
|
|
437
467
|
y = []
|
|
438
468
|
for output in self.output_details:
|
|
439
|
-
x = self.interpreter.get_tensor(output[
|
|
469
|
+
x = self.interpreter.get_tensor(output["index"])
|
|
440
470
|
if integer:
|
|
441
|
-
scale, zero_point = output[
|
|
471
|
+
scale, zero_point = output["quantization"]
|
|
442
472
|
x = (x.astype(np.float32) - zero_point) * scale # re-scale
|
|
443
473
|
if x.ndim > 2: # if task is not classification
|
|
444
474
|
# Denormalize xywh by image size. See https://github.com/ultralytics/ultralytics/pull/1695
|
|
@@ -483,13 +513,13 @@ class AutoBackend(nn.Module):
|
|
|
483
513
|
(None): This method runs the forward pass and don't return any value
|
|
484
514
|
"""
|
|
485
515
|
warmup_types = self.pt, self.jit, self.onnx, self.engine, self.saved_model, self.pb, self.triton, self.nn_module
|
|
486
|
-
if any(warmup_types) and (self.device.type !=
|
|
516
|
+
if any(warmup_types) and (self.device.type != "cpu" or self.triton):
|
|
487
517
|
im = torch.empty(*imgsz, dtype=torch.half if self.fp16 else torch.float, device=self.device) # input
|
|
488
518
|
for _ in range(2 if self.jit else 1):
|
|
489
519
|
self.forward(im) # warmup
|
|
490
520
|
|
|
491
521
|
@staticmethod
|
|
492
|
-
def _model_type(p=
|
|
522
|
+
def _model_type(p="path/to/model.pt"):
|
|
493
523
|
"""
|
|
494
524
|
This function takes a path to a model file and returns the model type.
|
|
495
525
|
|
|
@@ -499,18 +529,20 @@ class AutoBackend(nn.Module):
|
|
|
499
529
|
# Return model type from model path, i.e. path='path/to/model.onnx' -> type=onnx
|
|
500
530
|
# types = [pt, jit, onnx, xml, engine, coreml, saved_model, pb, tflite, edgetpu, tfjs, paddle]
|
|
501
531
|
from ultralytics.engine.exporter import export_formats
|
|
532
|
+
|
|
502
533
|
sf = list(export_formats().Suffix) # export suffixes
|
|
503
534
|
if not is_url(p, check=False) and not isinstance(p, str):
|
|
504
535
|
check_suffix(p, sf) # checks
|
|
505
536
|
name = Path(p).name
|
|
506
537
|
types = [s in name for s in sf]
|
|
507
|
-
types[5] |= name.endswith(
|
|
538
|
+
types[5] |= name.endswith(".mlmodel") # retain support for older Apple CoreML *.mlmodel formats
|
|
508
539
|
types[8] &= not types[9] # tflite &= not edgetpu
|
|
509
540
|
if any(types):
|
|
510
541
|
triton = False
|
|
511
542
|
else:
|
|
512
543
|
from urllib.parse import urlsplit
|
|
544
|
+
|
|
513
545
|
url = urlsplit(p)
|
|
514
|
-
triton = url.netloc and url.path and url.scheme in {
|
|
546
|
+
triton = url.netloc and url.path and url.scheme in {"http", "grpc"}
|
|
515
547
|
|
|
516
548
|
return types + [triton]
|
|
@@ -17,18 +17,101 @@ Example:
|
|
|
17
17
|
```
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
from .block import (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
from .block import (
|
|
21
|
+
C1,
|
|
22
|
+
C2,
|
|
23
|
+
C3,
|
|
24
|
+
C3TR,
|
|
25
|
+
DFL,
|
|
26
|
+
SPP,
|
|
27
|
+
SPPF,
|
|
28
|
+
Bottleneck,
|
|
29
|
+
BottleneckCSP,
|
|
30
|
+
C2f,
|
|
31
|
+
C3Ghost,
|
|
32
|
+
C3x,
|
|
33
|
+
GhostBottleneck,
|
|
34
|
+
HGBlock,
|
|
35
|
+
HGStem,
|
|
36
|
+
Proto,
|
|
37
|
+
RepC3,
|
|
38
|
+
ResNetLayer,
|
|
39
|
+
)
|
|
40
|
+
from .conv import (
|
|
41
|
+
CBAM,
|
|
42
|
+
ChannelAttention,
|
|
43
|
+
Concat,
|
|
44
|
+
Conv,
|
|
45
|
+
Conv2,
|
|
46
|
+
ConvTranspose,
|
|
47
|
+
DWConv,
|
|
48
|
+
DWConvTranspose2d,
|
|
49
|
+
Focus,
|
|
50
|
+
GhostConv,
|
|
51
|
+
LightConv,
|
|
52
|
+
RepConv,
|
|
53
|
+
SpatialAttention,
|
|
54
|
+
)
|
|
24
55
|
from .head import OBB, Classify, Detect, Pose, RTDETRDecoder, Segment
|
|
25
|
-
from .transformer import (
|
|
26
|
-
|
|
56
|
+
from .transformer import (
|
|
57
|
+
AIFI,
|
|
58
|
+
MLP,
|
|
59
|
+
DeformableTransformerDecoder,
|
|
60
|
+
DeformableTransformerDecoderLayer,
|
|
61
|
+
LayerNorm2d,
|
|
62
|
+
MLPBlock,
|
|
63
|
+
MSDeformAttn,
|
|
64
|
+
TransformerBlock,
|
|
65
|
+
TransformerEncoderLayer,
|
|
66
|
+
TransformerLayer,
|
|
67
|
+
)
|
|
27
68
|
|
|
28
|
-
__all__ = (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
69
|
+
__all__ = (
|
|
70
|
+
"Conv",
|
|
71
|
+
"Conv2",
|
|
72
|
+
"LightConv",
|
|
73
|
+
"RepConv",
|
|
74
|
+
"DWConv",
|
|
75
|
+
"DWConvTranspose2d",
|
|
76
|
+
"ConvTranspose",
|
|
77
|
+
"Focus",
|
|
78
|
+
"GhostConv",
|
|
79
|
+
"ChannelAttention",
|
|
80
|
+
"SpatialAttention",
|
|
81
|
+
"CBAM",
|
|
82
|
+
"Concat",
|
|
83
|
+
"TransformerLayer",
|
|
84
|
+
"TransformerBlock",
|
|
85
|
+
"MLPBlock",
|
|
86
|
+
"LayerNorm2d",
|
|
87
|
+
"DFL",
|
|
88
|
+
"HGBlock",
|
|
89
|
+
"HGStem",
|
|
90
|
+
"SPP",
|
|
91
|
+
"SPPF",
|
|
92
|
+
"C1",
|
|
93
|
+
"C2",
|
|
94
|
+
"C3",
|
|
95
|
+
"C2f",
|
|
96
|
+
"C3x",
|
|
97
|
+
"C3TR",
|
|
98
|
+
"C3Ghost",
|
|
99
|
+
"GhostBottleneck",
|
|
100
|
+
"Bottleneck",
|
|
101
|
+
"BottleneckCSP",
|
|
102
|
+
"Proto",
|
|
103
|
+
"Detect",
|
|
104
|
+
"Segment",
|
|
105
|
+
"Pose",
|
|
106
|
+
"Classify",
|
|
107
|
+
"TransformerEncoderLayer",
|
|
108
|
+
"RepC3",
|
|
109
|
+
"RTDETRDecoder",
|
|
110
|
+
"AIFI",
|
|
111
|
+
"DeformableTransformerDecoder",
|
|
112
|
+
"DeformableTransformerDecoderLayer",
|
|
113
|
+
"MSDeformAttn",
|
|
114
|
+
"MLP",
|
|
115
|
+
"ResNetLayer",
|
|
116
|
+
"OBB",
|
|
117
|
+
)
|