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/utils/checks.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import functools
|
|
4
6
|
import glob
|
|
5
7
|
import inspect
|
|
@@ -13,7 +15,6 @@ import time
|
|
|
13
15
|
from importlib import metadata
|
|
14
16
|
from pathlib import Path
|
|
15
17
|
from types import SimpleNamespace
|
|
16
|
-
from typing import Optional
|
|
17
18
|
|
|
18
19
|
import cv2
|
|
19
20
|
import numpy as np
|
|
@@ -22,9 +23,10 @@ import torch
|
|
|
22
23
|
from ultralytics.utils import (
|
|
23
24
|
ARM64,
|
|
24
25
|
ASSETS,
|
|
26
|
+
ASSETS_URL,
|
|
25
27
|
AUTOINSTALL,
|
|
28
|
+
GIT,
|
|
26
29
|
IS_COLAB,
|
|
27
|
-
IS_GIT_DIR,
|
|
28
30
|
IS_JETSON,
|
|
29
31
|
IS_KAGGLE,
|
|
30
32
|
IS_PIP_PACKAGE,
|
|
@@ -35,6 +37,7 @@ from ultralytics.utils import (
|
|
|
35
37
|
PYTHON_VERSION,
|
|
36
38
|
RKNN_CHIPS,
|
|
37
39
|
ROOT,
|
|
40
|
+
TORCH_VERSION,
|
|
38
41
|
TORCHVISION_VERSION,
|
|
39
42
|
USER_CONFIG_DIR,
|
|
40
43
|
WINDOWS,
|
|
@@ -50,15 +53,15 @@ from ultralytics.utils import (
|
|
|
50
53
|
|
|
51
54
|
|
|
52
55
|
def parse_requirements(file_path=ROOT.parent / "requirements.txt", package=""):
|
|
53
|
-
"""
|
|
54
|
-
Parse a requirements.txt file, ignoring lines that start with '#' and any text after '#'.
|
|
56
|
+
"""Parse a requirements.txt file, ignoring lines that start with '#' and any text after '#'.
|
|
55
57
|
|
|
56
58
|
Args:
|
|
57
59
|
file_path (Path): Path to the requirements.txt file.
|
|
58
60
|
package (str, optional): Python package to use instead of requirements.txt file.
|
|
59
61
|
|
|
60
62
|
Returns:
|
|
61
|
-
(
|
|
63
|
+
requirements (list[SimpleNamespace]): List of parsed requirements as SimpleNamespace objects with `name` and
|
|
64
|
+
`specifier` attributes.
|
|
62
65
|
|
|
63
66
|
Examples:
|
|
64
67
|
>>> from ultralytics.utils.checks import parse_requirements
|
|
@@ -73,7 +76,7 @@ def parse_requirements(file_path=ROOT.parent / "requirements.txt", package=""):
|
|
|
73
76
|
for line in requires:
|
|
74
77
|
line = line.strip()
|
|
75
78
|
if line and not line.startswith("#"):
|
|
76
|
-
line = line.
|
|
79
|
+
line = line.partition("#")[0].strip() # ignore inline comments
|
|
77
80
|
if match := re.match(r"([a-zA-Z0-9-_]+)\s*([<>!=~]+.*)?", line):
|
|
78
81
|
requirements.append(SimpleNamespace(name=match[1], specifier=match[2].strip() if match[2] else ""))
|
|
79
82
|
|
|
@@ -82,14 +85,13 @@ def parse_requirements(file_path=ROOT.parent / "requirements.txt", package=""):
|
|
|
82
85
|
|
|
83
86
|
@functools.lru_cache
|
|
84
87
|
def parse_version(version="0.0.0") -> tuple:
|
|
85
|
-
"""
|
|
86
|
-
Convert a version string to a tuple of integers, ignoring any extra non-numeric string attached to the version.
|
|
88
|
+
"""Convert a version string to a tuple of integers, ignoring any extra non-numeric string attached to the version.
|
|
87
89
|
|
|
88
90
|
Args:
|
|
89
91
|
version (str): Version string, i.e. '2.0.1+cpu'
|
|
90
92
|
|
|
91
93
|
Returns:
|
|
92
|
-
(
|
|
94
|
+
(tuple): Tuple of integers representing the numeric part of the version, i.e. (2, 0, 1)
|
|
93
95
|
"""
|
|
94
96
|
try:
|
|
95
97
|
return tuple(map(int, re.findall(r"\d+", version)[:3])) # '2.0.1+cpu' -> (2, 0, 1)
|
|
@@ -99,8 +101,7 @@ def parse_version(version="0.0.0") -> tuple:
|
|
|
99
101
|
|
|
100
102
|
|
|
101
103
|
def is_ascii(s) -> bool:
|
|
102
|
-
"""
|
|
103
|
-
Check if a string is composed of only ASCII characters.
|
|
104
|
+
"""Check if a string is composed of only ASCII characters.
|
|
104
105
|
|
|
105
106
|
Args:
|
|
106
107
|
s (str | list | tuple | dict): Input to be checked (all are converted to string for checking).
|
|
@@ -112,19 +113,18 @@ def is_ascii(s) -> bool:
|
|
|
112
113
|
|
|
113
114
|
|
|
114
115
|
def check_imgsz(imgsz, stride=32, min_dim=1, max_dim=2, floor=0):
|
|
115
|
-
"""
|
|
116
|
-
Verify image size is a multiple of the given stride in each dimension. If the image size is not a multiple of the
|
|
116
|
+
"""Verify image size is a multiple of the given stride in each dimension. If the image size is not a multiple of the
|
|
117
117
|
stride, update it to the nearest multiple of the stride that is greater than or equal to the given floor value.
|
|
118
118
|
|
|
119
119
|
Args:
|
|
120
|
-
imgsz (int |
|
|
120
|
+
imgsz (int | list[int]): Image size.
|
|
121
121
|
stride (int): Stride value.
|
|
122
122
|
min_dim (int): Minimum number of dimensions.
|
|
123
123
|
max_dim (int): Maximum number of dimensions.
|
|
124
124
|
floor (int): Minimum allowed value for image size.
|
|
125
125
|
|
|
126
126
|
Returns:
|
|
127
|
-
(
|
|
127
|
+
(list[int] | int): Updated image size.
|
|
128
128
|
"""
|
|
129
129
|
# Convert stride to integer if it is a tensor
|
|
130
130
|
stride = int(stride.max() if isinstance(stride, torch.Tensor) else stride)
|
|
@@ -165,6 +165,15 @@ def check_imgsz(imgsz, stride=32, min_dim=1, max_dim=2, floor=0):
|
|
|
165
165
|
return sz
|
|
166
166
|
|
|
167
167
|
|
|
168
|
+
@functools.lru_cache
|
|
169
|
+
def check_uv():
|
|
170
|
+
"""Check if uv package manager is installed and can run successfully."""
|
|
171
|
+
try:
|
|
172
|
+
return subprocess.run(["uv", "-V"], capture_output=True).returncode == 0
|
|
173
|
+
except FileNotFoundError:
|
|
174
|
+
return False
|
|
175
|
+
|
|
176
|
+
|
|
168
177
|
@functools.lru_cache
|
|
169
178
|
def check_version(
|
|
170
179
|
current: str = "0.0.0",
|
|
@@ -174,8 +183,7 @@ def check_version(
|
|
|
174
183
|
verbose: bool = False,
|
|
175
184
|
msg: str = "",
|
|
176
185
|
) -> bool:
|
|
177
|
-
"""
|
|
178
|
-
Check current version against the required version or range.
|
|
186
|
+
"""Check current version against the required version or range.
|
|
179
187
|
|
|
180
188
|
Args:
|
|
181
189
|
current (str): Current version or package name to get version from.
|
|
@@ -255,8 +263,7 @@ def check_version(
|
|
|
255
263
|
|
|
256
264
|
|
|
257
265
|
def check_latest_pypi_version(package_name="ultralytics"):
|
|
258
|
-
"""
|
|
259
|
-
Returns the latest version of a PyPI package without downloading or installing it.
|
|
266
|
+
"""Return the latest version of a PyPI package without downloading or installing it.
|
|
260
267
|
|
|
261
268
|
Args:
|
|
262
269
|
package_name (str): The name of the package to find the latest version for.
|
|
@@ -264,7 +271,7 @@ def check_latest_pypi_version(package_name="ultralytics"):
|
|
|
264
271
|
Returns:
|
|
265
272
|
(str): The latest version of the package.
|
|
266
273
|
"""
|
|
267
|
-
import requests # slow import
|
|
274
|
+
import requests # scoped as slow import
|
|
268
275
|
|
|
269
276
|
try:
|
|
270
277
|
requests.packages.urllib3.disable_warnings() # Disable the InsecureRequestWarning
|
|
@@ -276,8 +283,7 @@ def check_latest_pypi_version(package_name="ultralytics"):
|
|
|
276
283
|
|
|
277
284
|
|
|
278
285
|
def check_pip_update_available():
|
|
279
|
-
"""
|
|
280
|
-
Checks if a new version of the ultralytics package is available on PyPI.
|
|
286
|
+
"""Check if a new version of the ultralytics package is available on PyPI.
|
|
281
287
|
|
|
282
288
|
Returns:
|
|
283
289
|
(bool): True if an update is available, False otherwise.
|
|
@@ -301,8 +307,7 @@ def check_pip_update_available():
|
|
|
301
307
|
@ThreadingLocked()
|
|
302
308
|
@functools.lru_cache
|
|
303
309
|
def check_font(font="Arial.ttf"):
|
|
304
|
-
"""
|
|
305
|
-
Find font locally or download to user's configuration directory if it does not already exist.
|
|
310
|
+
"""Find font locally or download to user's configuration directory if it does not already exist.
|
|
306
311
|
|
|
307
312
|
Args:
|
|
308
313
|
font (str): Path or name of font.
|
|
@@ -324,15 +329,14 @@ def check_font(font="Arial.ttf"):
|
|
|
324
329
|
return matches[0]
|
|
325
330
|
|
|
326
331
|
# Download to USER_CONFIG_DIR if missing
|
|
327
|
-
url = f"
|
|
332
|
+
url = f"{ASSETS_URL}/{name}"
|
|
328
333
|
if downloads.is_url(url, check=True):
|
|
329
334
|
downloads.safe_download(url=url, file=file)
|
|
330
335
|
return file
|
|
331
336
|
|
|
332
337
|
|
|
333
338
|
def check_python(minimum: str = "3.8.0", hard: bool = True, verbose: bool = False) -> bool:
|
|
334
|
-
"""
|
|
335
|
-
Check current python version against the required minimum version.
|
|
339
|
+
"""Check current python version against the required minimum version.
|
|
336
340
|
|
|
337
341
|
Args:
|
|
338
342
|
minimum (str): Required minimum version of python.
|
|
@@ -347,13 +351,13 @@ def check_python(minimum: str = "3.8.0", hard: bool = True, verbose: bool = Fals
|
|
|
347
351
|
|
|
348
352
|
@TryExcept()
|
|
349
353
|
def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=(), install=True, cmds=""):
|
|
350
|
-
"""
|
|
351
|
-
Check if installed dependencies meet Ultralytics YOLO models requirements and attempt to auto-update if needed.
|
|
354
|
+
"""Check if installed dependencies meet Ultralytics YOLO models requirements and attempt to auto-update if needed.
|
|
352
355
|
|
|
353
356
|
Args:
|
|
354
|
-
requirements (
|
|
355
|
-
string,
|
|
356
|
-
|
|
357
|
+
requirements (Path | str | list[str|tuple] | tuple[str]): Path to a requirements.txt file, a single package
|
|
358
|
+
requirement as a string, a list of package requirements as strings, or a list containing strings and tuples
|
|
359
|
+
of interchangeable packages.
|
|
360
|
+
exclude (tuple): Tuple of package names to exclude from checking.
|
|
357
361
|
install (bool): If True, attempt to auto-update packages that don't meet requirements.
|
|
358
362
|
cmds (str): Additional commands to pass to the pip install command when auto-updating.
|
|
359
363
|
|
|
@@ -364,10 +368,13 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
|
|
|
364
368
|
>>> check_requirements("path/to/requirements.txt")
|
|
365
369
|
|
|
366
370
|
Check a single package
|
|
367
|
-
>>> check_requirements("ultralytics>=8.
|
|
371
|
+
>>> check_requirements("ultralytics>=8.3.200", cmds="--index-url https://download.pytorch.org/whl/cpu")
|
|
368
372
|
|
|
369
373
|
Check multiple packages
|
|
370
|
-
>>> check_requirements(["numpy", "ultralytics
|
|
374
|
+
>>> check_requirements(["numpy", "ultralytics"])
|
|
375
|
+
|
|
376
|
+
Check with interchangeable packages
|
|
377
|
+
>>> check_requirements([("onnxruntime", "onnxruntime-gpu"), "numpy"])
|
|
371
378
|
"""
|
|
372
379
|
prefix = colorstr("red", "bold", "requirements:")
|
|
373
380
|
if isinstance(requirements, Path): # requirements.txt file
|
|
@@ -379,30 +386,56 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
|
|
|
379
386
|
|
|
380
387
|
pkgs = []
|
|
381
388
|
for r in requirements:
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
+
candidates = r if isinstance(r, (list, tuple)) else [r]
|
|
390
|
+
satisfied = False
|
|
391
|
+
|
|
392
|
+
for candidate in candidates:
|
|
393
|
+
r_stripped = candidate.rpartition("/")[-1].replace(".git", "") # replace git+https://org/repo.git -> 'repo'
|
|
394
|
+
match = re.match(r"([a-zA-Z0-9-_]+)([<>!=~]+.*)?", r_stripped)
|
|
395
|
+
name, required = match[1], match[2].strip() if match[2] else ""
|
|
396
|
+
try:
|
|
397
|
+
if check_version(metadata.version(name), required):
|
|
398
|
+
satisfied = True
|
|
399
|
+
break
|
|
400
|
+
except (AssertionError, metadata.PackageNotFoundError):
|
|
401
|
+
continue
|
|
402
|
+
|
|
403
|
+
if not satisfied:
|
|
404
|
+
pkgs.append(candidates[0])
|
|
389
405
|
|
|
390
406
|
@Retry(times=2, delay=1)
|
|
391
|
-
def attempt_install(packages, commands):
|
|
392
|
-
"""Attempt
|
|
393
|
-
|
|
407
|
+
def attempt_install(packages, commands, use_uv):
|
|
408
|
+
"""Attempt package installation with uv if available, falling back to pip."""
|
|
409
|
+
if use_uv:
|
|
410
|
+
base = (
|
|
411
|
+
f"uv pip install --no-cache-dir {packages} {commands} "
|
|
412
|
+
f"--index-strategy=unsafe-best-match --break-system-packages --prerelease=allow"
|
|
413
|
+
)
|
|
414
|
+
try:
|
|
415
|
+
return subprocess.check_output(base, shell=True, stderr=subprocess.PIPE, text=True)
|
|
416
|
+
except subprocess.CalledProcessError as e:
|
|
417
|
+
if e.stderr and "No virtual environment found" in e.stderr:
|
|
418
|
+
return subprocess.check_output(
|
|
419
|
+
base.replace("uv pip install", "uv pip install --system"),
|
|
420
|
+
shell=True,
|
|
421
|
+
stderr=subprocess.PIPE,
|
|
422
|
+
text=True,
|
|
423
|
+
)
|
|
424
|
+
raise
|
|
425
|
+
return subprocess.check_output(f"pip install --no-cache-dir {packages} {commands}", shell=True, text=True)
|
|
394
426
|
|
|
395
427
|
s = " ".join(f'"{x}"' for x in pkgs) # console string
|
|
396
428
|
if s:
|
|
397
429
|
if install and AUTOINSTALL: # check environment variable
|
|
430
|
+
# Note uv fails on arm64 macOS and Raspberry Pi runners
|
|
398
431
|
n = len(pkgs) # number of packages updates
|
|
399
432
|
LOGGER.info(f"{prefix} Ultralytics requirement{'s' * (n > 1)} {pkgs} not found, attempting AutoUpdate...")
|
|
400
433
|
try:
|
|
401
434
|
t = time.time()
|
|
402
435
|
assert ONLINE, "AutoUpdate skipped (offline)"
|
|
403
|
-
LOGGER.info(attempt_install(s, cmds))
|
|
436
|
+
LOGGER.info(attempt_install(s, cmds, use_uv=not ARM64 and check_uv()))
|
|
404
437
|
dt = time.time() - t
|
|
405
|
-
LOGGER.info(f"{prefix} AutoUpdate success ✅ {dt:.1f}s
|
|
438
|
+
LOGGER.info(f"{prefix} AutoUpdate success ✅ {dt:.1f}s")
|
|
406
439
|
LOGGER.warning(
|
|
407
440
|
f"{prefix} {colorstr('bold', 'Restart runtime or rerun command for updates to take effect')}\n"
|
|
408
441
|
)
|
|
@@ -416,13 +449,15 @@ def check_requirements(requirements=ROOT.parent / "requirements.txt", exclude=()
|
|
|
416
449
|
|
|
417
450
|
|
|
418
451
|
def check_torchvision():
|
|
419
|
-
"""
|
|
420
|
-
Checks the installed versions of PyTorch and Torchvision to ensure they're compatible.
|
|
452
|
+
"""Check the installed versions of PyTorch and Torchvision to ensure they're compatible.
|
|
421
453
|
|
|
422
454
|
This function checks the installed versions of PyTorch and Torchvision, and warns if they're incompatible according
|
|
423
455
|
to the compatibility table based on: https://github.com/pytorch/vision#installation.
|
|
424
456
|
"""
|
|
425
457
|
compatibility_table = {
|
|
458
|
+
"2.9": ["0.24"],
|
|
459
|
+
"2.8": ["0.23"],
|
|
460
|
+
"2.7": ["0.22"],
|
|
426
461
|
"2.6": ["0.21"],
|
|
427
462
|
"2.5": ["0.20"],
|
|
428
463
|
"2.4": ["0.19"],
|
|
@@ -435,10 +470,10 @@ def check_torchvision():
|
|
|
435
470
|
}
|
|
436
471
|
|
|
437
472
|
# Check major and minor versions
|
|
438
|
-
v_torch = ".".join(
|
|
473
|
+
v_torch = ".".join(TORCH_VERSION.split("+", 1)[0].split(".")[:2])
|
|
439
474
|
if v_torch in compatibility_table:
|
|
440
475
|
compatible_versions = compatibility_table[v_torch]
|
|
441
|
-
v_torchvision = ".".join(TORCHVISION_VERSION.split("+")[0].split(".")[:2])
|
|
476
|
+
v_torchvision = ".".join(TORCHVISION_VERSION.split("+", 1)[0].split(".")[:2])
|
|
442
477
|
if all(v_torchvision != v for v in compatible_versions):
|
|
443
478
|
LOGGER.warning(
|
|
444
479
|
f"torchvision=={v_torchvision} is incompatible with torch=={v_torch}.\n"
|
|
@@ -449,26 +484,23 @@ def check_torchvision():
|
|
|
449
484
|
|
|
450
485
|
|
|
451
486
|
def check_suffix(file="yolo11n.pt", suffix=".pt", msg=""):
|
|
452
|
-
"""
|
|
453
|
-
Check file(s) for acceptable suffix.
|
|
487
|
+
"""Check file(s) for acceptable suffix.
|
|
454
488
|
|
|
455
489
|
Args:
|
|
456
|
-
file (str |
|
|
457
|
-
suffix (str |
|
|
490
|
+
file (str | list[str]): File or list of files to check.
|
|
491
|
+
suffix (str | tuple): Acceptable suffix or tuple of suffixes.
|
|
458
492
|
msg (str): Additional message to display in case of error.
|
|
459
493
|
"""
|
|
460
494
|
if file and suffix:
|
|
461
495
|
if isinstance(suffix, str):
|
|
462
496
|
suffix = {suffix}
|
|
463
497
|
for f in file if isinstance(file, (list, tuple)) else [file]:
|
|
464
|
-
s
|
|
465
|
-
|
|
466
|
-
assert s in suffix, f"{msg}{f} acceptable suffix is {suffix}, not {s}"
|
|
498
|
+
if s := str(f).rpartition(".")[-1].lower().strip(): # file suffix
|
|
499
|
+
assert f".{s}" in suffix, f"{msg}{f} acceptable suffix is {suffix}, not .{s}"
|
|
467
500
|
|
|
468
501
|
|
|
469
502
|
def check_yolov5u_filename(file: str, verbose: bool = True):
|
|
470
|
-
"""
|
|
471
|
-
Replace legacy YOLOv5 filenames with updated YOLOv5u filenames.
|
|
503
|
+
"""Replace legacy YOLOv5 filenames with updated YOLOv5u filenames.
|
|
472
504
|
|
|
473
505
|
Args:
|
|
474
506
|
file (str): Filename to check and potentially update.
|
|
@@ -495,8 +527,7 @@ def check_yolov5u_filename(file: str, verbose: bool = True):
|
|
|
495
527
|
|
|
496
528
|
|
|
497
529
|
def check_model_file_from_stem(model="yolo11n"):
|
|
498
|
-
"""
|
|
499
|
-
Return a model filename from a valid model stem.
|
|
530
|
+
"""Return a model filename from a valid model stem.
|
|
500
531
|
|
|
501
532
|
Args:
|
|
502
533
|
model (str): Model stem to check.
|
|
@@ -504,19 +535,18 @@ def check_model_file_from_stem(model="yolo11n"):
|
|
|
504
535
|
Returns:
|
|
505
536
|
(str | Path): Model filename with appropriate suffix.
|
|
506
537
|
"""
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
538
|
+
path = Path(model)
|
|
539
|
+
if not path.suffix and path.stem in downloads.GITHUB_ASSETS_STEMS:
|
|
540
|
+
return path.with_suffix(".pt") # add suffix, i.e. yolo11n -> yolo11n.pt
|
|
541
|
+
return model
|
|
511
542
|
|
|
512
543
|
|
|
513
544
|
def check_file(file, suffix="", download=True, download_dir=".", hard=True):
|
|
514
|
-
"""
|
|
515
|
-
Search/download file (if necessary), check suffix (if provided), and return path.
|
|
545
|
+
"""Search/download file (if necessary), check suffix (if provided), and return path.
|
|
516
546
|
|
|
517
547
|
Args:
|
|
518
548
|
file (str): File name or path.
|
|
519
|
-
suffix (str |
|
|
549
|
+
suffix (str | tuple): Acceptable suffix or tuple of suffixes to validate against the file.
|
|
520
550
|
download (bool): Whether to download the file if it doesn't exist locally.
|
|
521
551
|
download_dir (str): Directory to download the file to.
|
|
522
552
|
hard (bool): Whether to raise an error if the file is not found.
|
|
@@ -551,12 +581,11 @@ def check_file(file, suffix="", download=True, download_dir=".", hard=True):
|
|
|
551
581
|
|
|
552
582
|
|
|
553
583
|
def check_yaml(file, suffix=(".yaml", ".yml"), hard=True):
|
|
554
|
-
"""
|
|
555
|
-
Search/download YAML file (if necessary) and return path, checking suffix.
|
|
584
|
+
"""Search/download YAML file (if necessary) and return path, checking suffix.
|
|
556
585
|
|
|
557
586
|
Args:
|
|
558
587
|
file (str | Path): File name or path.
|
|
559
|
-
suffix (
|
|
588
|
+
suffix (tuple): Tuple of acceptable YAML file suffixes.
|
|
560
589
|
hard (bool): Whether to raise an error if the file is not found or multiple files are found.
|
|
561
590
|
|
|
562
591
|
Returns:
|
|
@@ -566,8 +595,7 @@ def check_yaml(file, suffix=(".yaml", ".yml"), hard=True):
|
|
|
566
595
|
|
|
567
596
|
|
|
568
597
|
def check_is_path_safe(basedir, path):
|
|
569
|
-
"""
|
|
570
|
-
Check if the resolved path is under the intended directory to prevent path traversal.
|
|
598
|
+
"""Check if the resolved path is under the intended directory to prevent path traversal.
|
|
571
599
|
|
|
572
600
|
Args:
|
|
573
601
|
basedir (Path | str): The intended directory.
|
|
@@ -584,8 +612,7 @@ def check_is_path_safe(basedir, path):
|
|
|
584
612
|
|
|
585
613
|
@functools.lru_cache
|
|
586
614
|
def check_imshow(warn=False):
|
|
587
|
-
"""
|
|
588
|
-
Check if environment supports image displays.
|
|
615
|
+
"""Check if environment supports image displays.
|
|
589
616
|
|
|
590
617
|
Args:
|
|
591
618
|
warn (bool): Whether to warn if environment doesn't support image displays.
|
|
@@ -609,14 +636,13 @@ def check_imshow(warn=False):
|
|
|
609
636
|
|
|
610
637
|
|
|
611
638
|
def check_yolo(verbose=True, device=""):
|
|
612
|
-
"""
|
|
613
|
-
Return a human-readable YOLO software and hardware summary.
|
|
639
|
+
"""Return a human-readable YOLO software and hardware summary.
|
|
614
640
|
|
|
615
641
|
Args:
|
|
616
642
|
verbose (bool): Whether to print verbose information.
|
|
617
643
|
device (str | torch.device): Device to use for YOLO.
|
|
618
644
|
"""
|
|
619
|
-
import psutil
|
|
645
|
+
import psutil # scoped as slow import
|
|
620
646
|
|
|
621
647
|
from ultralytics.utils.torch_utils import select_device
|
|
622
648
|
|
|
@@ -627,7 +653,7 @@ def check_yolo(verbose=True, device=""):
|
|
|
627
653
|
# System info
|
|
628
654
|
gib = 1 << 30 # bytes per GiB
|
|
629
655
|
ram = psutil.virtual_memory().total
|
|
630
|
-
total,
|
|
656
|
+
total, _used, free = shutil.disk_usage("/")
|
|
631
657
|
s = f"({os.cpu_count()} CPUs, {ram / gib:.1f} GB RAM, {(total - free) / gib:.1f}/{total / gib:.1f} GB disk)"
|
|
632
658
|
try:
|
|
633
659
|
from IPython import display
|
|
@@ -638,32 +664,34 @@ def check_yolo(verbose=True, device=""):
|
|
|
638
664
|
else:
|
|
639
665
|
s = ""
|
|
640
666
|
|
|
667
|
+
if GIT.is_repo:
|
|
668
|
+
check_multiple_install() # check conflicting installation if using local clone
|
|
669
|
+
|
|
641
670
|
select_device(device=device, newline=False)
|
|
642
671
|
LOGGER.info(f"Setup complete ✅ {s}")
|
|
643
672
|
|
|
644
673
|
|
|
645
674
|
def collect_system_info():
|
|
646
|
-
"""
|
|
647
|
-
Collect and print relevant system information including OS, Python, RAM, CPU, and CUDA.
|
|
675
|
+
"""Collect and print relevant system information including OS, Python, RAM, CPU, and CUDA.
|
|
648
676
|
|
|
649
677
|
Returns:
|
|
650
678
|
(dict): Dictionary containing system information.
|
|
651
679
|
"""
|
|
652
|
-
import psutil
|
|
680
|
+
import psutil # scoped as slow import
|
|
653
681
|
|
|
654
682
|
from ultralytics.utils import ENVIRONMENT # scope to avoid circular import
|
|
655
683
|
from ultralytics.utils.torch_utils import get_cpu_info, get_gpu_info
|
|
656
684
|
|
|
657
685
|
gib = 1 << 30 # bytes per GiB
|
|
658
|
-
cuda = torch
|
|
686
|
+
cuda = torch.cuda.is_available()
|
|
659
687
|
check_yolo()
|
|
660
|
-
total,
|
|
688
|
+
total, _used, free = shutil.disk_usage("/")
|
|
661
689
|
|
|
662
690
|
info_dict = {
|
|
663
691
|
"OS": platform.platform(),
|
|
664
692
|
"Environment": ENVIRONMENT,
|
|
665
693
|
"Python": PYTHON_VERSION,
|
|
666
|
-
"Install": "git" if
|
|
694
|
+
"Install": "git" if GIT.is_repo else "pip" if IS_PIP_PACKAGE else "other",
|
|
667
695
|
"Path": str(ROOT),
|
|
668
696
|
"RAM": f"{psutil.virtual_memory().total / gib:.2f} GB",
|
|
669
697
|
"Disk": f"{(total - free) / gib:.1f}/{total / gib:.1f} GB",
|
|
@@ -673,7 +701,7 @@ def collect_system_info():
|
|
|
673
701
|
"GPU count": torch.cuda.device_count() if cuda else None,
|
|
674
702
|
"CUDA": torch.version.cuda if cuda else None,
|
|
675
703
|
}
|
|
676
|
-
LOGGER.info("\n" + "\n".join(f"{k:<
|
|
704
|
+
LOGGER.info("\n" + "\n".join(f"{k:<23}{v}" for k, v in info_dict.items()) + "\n")
|
|
677
705
|
|
|
678
706
|
package_info = {}
|
|
679
707
|
for r in parse_requirements(package="ultralytics"):
|
|
@@ -684,7 +712,7 @@ def collect_system_info():
|
|
|
684
712
|
current = "(not installed)"
|
|
685
713
|
is_met = "❌ "
|
|
686
714
|
package_info[r.name] = f"{is_met}{current}{r.specifier}"
|
|
687
|
-
LOGGER.info(f"{r.name:<
|
|
715
|
+
LOGGER.info(f"{r.name:<23}{package_info[r.name]}")
|
|
688
716
|
|
|
689
717
|
info_dict["Package Info"] = package_info
|
|
690
718
|
|
|
@@ -704,14 +732,13 @@ def collect_system_info():
|
|
|
704
732
|
|
|
705
733
|
|
|
706
734
|
def check_amp(model):
|
|
707
|
-
"""
|
|
708
|
-
Checks the PyTorch Automatic Mixed Precision (AMP) functionality of a YOLO11 model.
|
|
735
|
+
"""Check the PyTorch Automatic Mixed Precision (AMP) functionality of a YOLO model.
|
|
709
736
|
|
|
710
737
|
If the checks fail, it means there are anomalies with AMP on the system that may cause NaN losses or zero-mAP
|
|
711
738
|
results, so AMP will be disabled during training.
|
|
712
739
|
|
|
713
740
|
Args:
|
|
714
|
-
model (nn.Module): A
|
|
741
|
+
model (torch.nn.Module): A YOLO model instance.
|
|
715
742
|
|
|
716
743
|
Returns:
|
|
717
744
|
(bool): Returns True if the AMP functionality works correctly with YOLO11 model, else False.
|
|
@@ -776,25 +803,32 @@ def check_amp(model):
|
|
|
776
803
|
return True
|
|
777
804
|
|
|
778
805
|
|
|
779
|
-
def
|
|
780
|
-
"""
|
|
781
|
-
|
|
806
|
+
def check_multiple_install():
|
|
807
|
+
"""Check if there are multiple Ultralytics installations."""
|
|
808
|
+
import sys
|
|
782
809
|
|
|
783
|
-
Args:
|
|
784
|
-
path (Path): Path to git repository.
|
|
785
|
-
|
|
786
|
-
Returns:
|
|
787
|
-
(str): Human-readable git description.
|
|
788
|
-
"""
|
|
789
810
|
try:
|
|
790
|
-
|
|
811
|
+
result = subprocess.run([sys.executable, "-m", "pip", "show", "ultralytics"], capture_output=True, text=True)
|
|
812
|
+
install_msg = (
|
|
813
|
+
f"Install your local copy in editable mode with 'pip install -e {ROOT.parent}' to avoid "
|
|
814
|
+
"issues. See https://docs.ultralytics.com/quickstart/"
|
|
815
|
+
)
|
|
816
|
+
if result.returncode != 0:
|
|
817
|
+
if "not found" in result.stderr.lower(): # Package not pip-installed but locally imported
|
|
818
|
+
LOGGER.warning(f"Ultralytics not found via pip but importing from: {ROOT}. {install_msg}")
|
|
819
|
+
return
|
|
820
|
+
yolo_path = (Path(re.findall(r"location:\s+(.+)", result.stdout, flags=re.I)[-1]) / "ultralytics").resolve()
|
|
821
|
+
if not yolo_path.samefile(ROOT.resolve()):
|
|
822
|
+
LOGGER.warning(
|
|
823
|
+
f"Multiple Ultralytics installations detected. The `yolo` command uses: {yolo_path}, "
|
|
824
|
+
f"but current session imports from: {ROOT}. This may cause version conflicts. {install_msg}"
|
|
825
|
+
)
|
|
791
826
|
except Exception:
|
|
792
|
-
return
|
|
827
|
+
return
|
|
793
828
|
|
|
794
829
|
|
|
795
|
-
def print_args(args:
|
|
796
|
-
"""
|
|
797
|
-
Print function arguments (optional args dict).
|
|
830
|
+
def print_args(args: dict | None = None, show_file=True, show_func=False):
|
|
831
|
+
"""Print function arguments (optional args dict).
|
|
798
832
|
|
|
799
833
|
Args:
|
|
800
834
|
args (dict, optional): Arguments to print.
|
|
@@ -820,8 +854,7 @@ def print_args(args: Optional[dict] = None, show_file=True, show_func=False):
|
|
|
820
854
|
|
|
821
855
|
|
|
822
856
|
def cuda_device_count() -> int:
|
|
823
|
-
"""
|
|
824
|
-
Get the number of NVIDIA GPUs available in the environment.
|
|
857
|
+
"""Get the number of NVIDIA GPUs available in the environment.
|
|
825
858
|
|
|
826
859
|
Returns:
|
|
827
860
|
(int): The number of NVIDIA GPUs available.
|
|
@@ -837,7 +870,7 @@ def cuda_device_count() -> int:
|
|
|
837
870
|
)
|
|
838
871
|
|
|
839
872
|
# Take the first line and strip any leading/trailing white space
|
|
840
|
-
first_line = output.strip().split("\n")[0]
|
|
873
|
+
first_line = output.strip().split("\n", 1)[0]
|
|
841
874
|
|
|
842
875
|
return int(first_line)
|
|
843
876
|
except (subprocess.CalledProcessError, FileNotFoundError, ValueError):
|
|
@@ -846,8 +879,7 @@ def cuda_device_count() -> int:
|
|
|
846
879
|
|
|
847
880
|
|
|
848
881
|
def cuda_is_available() -> bool:
|
|
849
|
-
"""
|
|
850
|
-
Check if CUDA is available in the environment.
|
|
882
|
+
"""Check if CUDA is available in the environment.
|
|
851
883
|
|
|
852
884
|
Returns:
|
|
853
885
|
(bool): True if one or more NVIDIA GPUs are available, False otherwise.
|
|
@@ -856,8 +888,7 @@ def cuda_is_available() -> bool:
|
|
|
856
888
|
|
|
857
889
|
|
|
858
890
|
def is_rockchip():
|
|
859
|
-
"""
|
|
860
|
-
Check if the current environment is running on a Rockchip SoC.
|
|
891
|
+
"""Check if the current environment is running on a Rockchip SoC.
|
|
861
892
|
|
|
862
893
|
Returns:
|
|
863
894
|
(bool): True if running on a Rockchip SoC, False otherwise.
|
|
@@ -875,9 +906,28 @@ def is_rockchip():
|
|
|
875
906
|
return False
|
|
876
907
|
|
|
877
908
|
|
|
878
|
-
def
|
|
909
|
+
def is_intel():
|
|
910
|
+
"""Check if the system has Intel hardware (CPU or GPU).
|
|
911
|
+
|
|
912
|
+
Returns:
|
|
913
|
+
(bool): True if Intel hardware is detected, False otherwise.
|
|
879
914
|
"""
|
|
880
|
-
|
|
915
|
+
from ultralytics.utils.torch_utils import get_cpu_info
|
|
916
|
+
|
|
917
|
+
# Check CPU
|
|
918
|
+
if "intel" in get_cpu_info().lower():
|
|
919
|
+
return True
|
|
920
|
+
|
|
921
|
+
# Check GPU via xpu-smi
|
|
922
|
+
try:
|
|
923
|
+
result = subprocess.run(["xpu-smi", "discovery"], capture_output=True, text=True, timeout=5)
|
|
924
|
+
return "intel" in result.stdout.lower()
|
|
925
|
+
except Exception: # broad clause to capture all Intel GPU exception types
|
|
926
|
+
return False
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
def is_sudo_available() -> bool:
|
|
930
|
+
"""Check if the sudo command is available in the environment.
|
|
881
931
|
|
|
882
932
|
Returns:
|
|
883
933
|
(bool): True if the sudo command is available, False otherwise.
|
|
@@ -894,7 +944,6 @@ check_torchvision() # check torch-torchvision compatibility
|
|
|
894
944
|
|
|
895
945
|
# Define constants
|
|
896
946
|
IS_PYTHON_3_8 = PYTHON_VERSION.startswith("3.8")
|
|
897
|
-
IS_PYTHON_3_11 = PYTHON_VERSION.startswith("3.11")
|
|
898
947
|
IS_PYTHON_3_12 = PYTHON_VERSION.startswith("3.12")
|
|
899
948
|
IS_PYTHON_3_13 = PYTHON_VERSION.startswith("3.13")
|
|
900
949
|
|