dgenerate-ultralytics-headless 8.3.220__py3-none-any.whl → 8.3.221__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.220.dist-info → dgenerate_ultralytics_headless-8.3.221.dist-info}/METADATA +1 -1
- {dgenerate_ultralytics_headless-8.3.220.dist-info → dgenerate_ultralytics_headless-8.3.221.dist-info}/RECORD +73 -73
- tests/__init__.py +5 -7
- tests/conftest.py +3 -7
- tests/test_cli.py +1 -1
- tests/test_engine.py +1 -1
- tests/test_integrations.py +4 -4
- tests/test_python.py +37 -44
- tests/test_solutions.py +154 -145
- ultralytics/__init__.py +1 -1
- ultralytics/cfg/__init__.py +7 -5
- ultralytics/data/__init__.py +4 -4
- ultralytics/data/augment.py +10 -10
- ultralytics/data/base.py +1 -1
- ultralytics/data/build.py +1 -1
- ultralytics/data/converter.py +3 -3
- ultralytics/data/dataset.py +3 -3
- ultralytics/data/loaders.py +2 -2
- ultralytics/data/utils.py +2 -2
- ultralytics/engine/exporter.py +16 -16
- ultralytics/engine/model.py +1 -1
- ultralytics/engine/trainer.py +5 -3
- ultralytics/engine/tuner.py +4 -4
- ultralytics/hub/__init__.py +9 -7
- ultralytics/hub/utils.py +2 -2
- ultralytics/models/__init__.py +1 -1
- ultralytics/models/fastsam/__init__.py +1 -1
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/sam/__init__.py +1 -1
- ultralytics/models/sam/amg.py +2 -2
- ultralytics/models/sam/modules/blocks.py +1 -1
- ultralytics/models/sam/modules/transformer.py +1 -1
- ultralytics/models/sam/predict.py +1 -1
- ultralytics/models/yolo/__init__.py +1 -1
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/segment/val.py +1 -1
- ultralytics/models/yolo/yoloe/__init__.py +7 -7
- ultralytics/nn/__init__.py +7 -7
- ultralytics/nn/autobackend.py +5 -5
- ultralytics/nn/modules/__init__.py +60 -60
- ultralytics/nn/modules/block.py +26 -26
- ultralytics/nn/modules/conv.py +7 -7
- ultralytics/nn/modules/head.py +1 -1
- ultralytics/nn/modules/transformer.py +7 -7
- ultralytics/nn/modules/utils.py +1 -1
- ultralytics/nn/tasks.py +3 -3
- ultralytics/solutions/__init__.py +12 -12
- ultralytics/solutions/object_counter.py +3 -6
- ultralytics/solutions/queue_management.py +1 -1
- ultralytics/solutions/similarity_search.py +1 -1
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/byte_tracker.py +2 -2
- ultralytics/trackers/utils/matching.py +1 -1
- ultralytics/utils/__init__.py +2 -2
- ultralytics/utils/benchmarks.py +4 -4
- ultralytics/utils/callbacks/comet.py +2 -2
- ultralytics/utils/checks.py +2 -2
- ultralytics/utils/downloads.py +2 -2
- ultralytics/utils/export/__init__.py +1 -1
- ultralytics/utils/files.py +1 -1
- ultralytics/utils/git.py +1 -1
- ultralytics/utils/logger.py +1 -1
- ultralytics/utils/metrics.py +13 -9
- ultralytics/utils/ops.py +8 -8
- ultralytics/utils/plotting.py +2 -1
- ultralytics/utils/torch_utils.py +4 -4
- ultralytics/utils/triton.py +2 -2
- ultralytics/utils/tuner.py +4 -2
- {dgenerate_ultralytics_headless-8.3.220.dist-info → dgenerate_ultralytics_headless-8.3.221.dist-info}/WHEEL +0 -0
- {dgenerate_ultralytics_headless-8.3.220.dist-info → dgenerate_ultralytics_headless-8.3.221.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.220.dist-info → dgenerate_ultralytics_headless-8.3.221.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.220.dist-info → dgenerate_ultralytics_headless-8.3.221.dist-info}/top_level.txt +0 -0
ultralytics/data/augment.py
CHANGED
|
@@ -477,7 +477,7 @@ class BaseMixTransform:
|
|
|
477
477
|
if "texts" not in labels:
|
|
478
478
|
return labels
|
|
479
479
|
|
|
480
|
-
mix_texts =
|
|
480
|
+
mix_texts = [*labels["texts"], *(item for x in labels["mix_labels"] for item in x["texts"])]
|
|
481
481
|
mix_texts = list({tuple(x) for x in mix_texts})
|
|
482
482
|
text2id = {text: i for i, text in enumerate(mix_texts)}
|
|
483
483
|
|
|
@@ -1517,7 +1517,7 @@ class RandomFlip:
|
|
|
1517
1517
|
>>> flipped_instances = result["instances"]
|
|
1518
1518
|
"""
|
|
1519
1519
|
|
|
1520
|
-
def __init__(self, p: float = 0.5, direction: str = "horizontal", flip_idx: list[int] = None) -> None:
|
|
1520
|
+
def __init__(self, p: float = 0.5, direction: str = "horizontal", flip_idx: list[int] | None = None) -> None:
|
|
1521
1521
|
"""
|
|
1522
1522
|
Initialize the RandomFlip class with probability and direction.
|
|
1523
1523
|
|
|
@@ -1664,7 +1664,7 @@ class LetterBox:
|
|
|
1664
1664
|
self.padding_value = padding_value
|
|
1665
1665
|
self.interpolation = interpolation
|
|
1666
1666
|
|
|
1667
|
-
def __call__(self, labels: dict[str, Any] = None, image: np.ndarray = None) -> dict[str, Any] | np.ndarray:
|
|
1667
|
+
def __call__(self, labels: dict[str, Any] | None = None, image: np.ndarray = None) -> dict[str, Any] | np.ndarray:
|
|
1668
1668
|
"""
|
|
1669
1669
|
Resize and pad an image for object detection, instance segmentation, or pose estimation tasks.
|
|
1670
1670
|
|
|
@@ -1701,7 +1701,7 @@ class LetterBox:
|
|
|
1701
1701
|
|
|
1702
1702
|
# Compute padding
|
|
1703
1703
|
ratio = r, r # width, height ratios
|
|
1704
|
-
new_unpad =
|
|
1704
|
+
new_unpad = round(shape[1] * r), round(shape[0] * r)
|
|
1705
1705
|
dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
|
|
1706
1706
|
if self.auto: # minimum rectangle
|
|
1707
1707
|
dw, dh = np.mod(dw, self.stride), np.mod(dh, self.stride) # wh padding
|
|
@@ -1719,8 +1719,8 @@ class LetterBox:
|
|
|
1719
1719
|
if img.ndim == 2:
|
|
1720
1720
|
img = img[..., None]
|
|
1721
1721
|
|
|
1722
|
-
top, bottom =
|
|
1723
|
-
left, right =
|
|
1722
|
+
top, bottom = round(dh - 0.1) if self.center else 0, round(dh + 0.1)
|
|
1723
|
+
left, right = round(dw - 0.1) if self.center else 0, round(dw + 0.1)
|
|
1724
1724
|
h, w, c = img.shape
|
|
1725
1725
|
if c == 3:
|
|
1726
1726
|
img = cv2.copyMakeBorder(
|
|
@@ -2601,7 +2601,7 @@ def classify_transforms(
|
|
|
2601
2601
|
mean: tuple[float, float, float] = DEFAULT_MEAN,
|
|
2602
2602
|
std: tuple[float, float, float] = DEFAULT_STD,
|
|
2603
2603
|
interpolation: str = "BILINEAR",
|
|
2604
|
-
crop_fraction: float = None,
|
|
2604
|
+
crop_fraction: float | None = None,
|
|
2605
2605
|
):
|
|
2606
2606
|
"""
|
|
2607
2607
|
Create a composition of image transforms for classification tasks.
|
|
@@ -2651,11 +2651,11 @@ def classify_augmentations(
|
|
|
2651
2651
|
size: int = 224,
|
|
2652
2652
|
mean: tuple[float, float, float] = DEFAULT_MEAN,
|
|
2653
2653
|
std: tuple[float, float, float] = DEFAULT_STD,
|
|
2654
|
-
scale: tuple[float, float] = None,
|
|
2655
|
-
ratio: tuple[float, float] = None,
|
|
2654
|
+
scale: tuple[float, float] | None = None,
|
|
2655
|
+
ratio: tuple[float, float] | None = None,
|
|
2656
2656
|
hflip: float = 0.5,
|
|
2657
2657
|
vflip: float = 0.0,
|
|
2658
|
-
auto_augment: str = None,
|
|
2658
|
+
auto_augment: str | None = None,
|
|
2659
2659
|
hsv_h: float = 0.015, # image HSV-Hue augmentation (fraction)
|
|
2660
2660
|
hsv_s: float = 0.4, # image HSV-Saturation augmentation (fraction)
|
|
2661
2661
|
hsv_v: float = 0.4, # image HSV-Value augmentation (fraction)
|
ultralytics/data/base.py
CHANGED
|
@@ -310,7 +310,7 @@ class BaseDataset(Dataset):
|
|
|
310
310
|
LOGGER.warning(f"{self.prefix}Skipping caching images to disk, directory not writeable")
|
|
311
311
|
return False
|
|
312
312
|
disk_required = b * self.ni / n * (1 + safety_margin) # bytes required to cache dataset to disk
|
|
313
|
-
total,
|
|
313
|
+
total, _used, free = shutil.disk_usage(Path(self.im_files[0]).parent)
|
|
314
314
|
if disk_required > free:
|
|
315
315
|
self.cache = None
|
|
316
316
|
LOGGER.warning(
|
ultralytics/data/build.py
CHANGED
|
@@ -211,7 +211,7 @@ class ContiguousDistributedSampler(torch.utils.data.Sampler):
|
|
|
211
211
|
self.epoch = epoch
|
|
212
212
|
|
|
213
213
|
|
|
214
|
-
def seed_worker(worker_id: int):
|
|
214
|
+
def seed_worker(worker_id: int):
|
|
215
215
|
"""Set dataloader worker seed for reproducibility across worker processes."""
|
|
216
216
|
worker_seed = torch.initial_seed() % 2**32
|
|
217
217
|
np.random.seed(worker_seed)
|
ultralytics/data/converter.py
CHANGED
|
@@ -308,7 +308,7 @@ def convert_coco(
|
|
|
308
308
|
continue
|
|
309
309
|
|
|
310
310
|
cls = coco80[ann["category_id"] - 1] if cls91to80 else ann["category_id"] - 1 # class
|
|
311
|
-
box = [cls
|
|
311
|
+
box = [cls, *box.tolist()]
|
|
312
312
|
if box not in bboxes:
|
|
313
313
|
bboxes.append(box)
|
|
314
314
|
if use_segments and ann.get("segmentation") is not None:
|
|
@@ -321,7 +321,7 @@ def convert_coco(
|
|
|
321
321
|
else:
|
|
322
322
|
s = [j for i in ann["segmentation"] for j in i] # all segments concatenated
|
|
323
323
|
s = (np.array(s).reshape(-1, 2) / np.array([w, h])).reshape(-1).tolist()
|
|
324
|
-
s = [cls
|
|
324
|
+
s = [cls, *s]
|
|
325
325
|
segments.append(s)
|
|
326
326
|
if use_keypoints and ann.get("keypoints") is not None:
|
|
327
327
|
keypoints.append(
|
|
@@ -730,7 +730,7 @@ def convert_to_multispectral(path: str | Path, n_channels: int = 10, replace: bo
|
|
|
730
730
|
path = Path(path)
|
|
731
731
|
if path.is_dir():
|
|
732
732
|
# Process directory
|
|
733
|
-
im_files =
|
|
733
|
+
im_files = [f for ext in (IMG_FORMATS - {"tif", "tiff"}) for f in path.rglob(f"*.{ext}")]
|
|
734
734
|
for im_path in im_files:
|
|
735
735
|
try:
|
|
736
736
|
convert_to_multispectral(im_path, n_channels)
|
ultralytics/data/dataset.py
CHANGED
|
@@ -548,7 +548,7 @@ class GroundingDataset(YOLODataset):
|
|
|
548
548
|
cat2id[cat_name] = len(cat2id)
|
|
549
549
|
texts.append([cat_name])
|
|
550
550
|
cls = cat2id[cat_name] # class
|
|
551
|
-
box = [cls
|
|
551
|
+
box = [cls, *box.tolist()]
|
|
552
552
|
if box not in bboxes:
|
|
553
553
|
bboxes.append(box)
|
|
554
554
|
if ann.get("segmentation") is not None:
|
|
@@ -565,7 +565,7 @@ class GroundingDataset(YOLODataset):
|
|
|
565
565
|
.reshape(-1)
|
|
566
566
|
.tolist()
|
|
567
567
|
)
|
|
568
|
-
s = [cls
|
|
568
|
+
s = [cls, *s]
|
|
569
569
|
segments.append(s)
|
|
570
570
|
lb = np.array(bboxes, dtype=np.float32) if len(bboxes) else np.zeros((0, 5), dtype=np.float32)
|
|
571
571
|
|
|
@@ -768,7 +768,7 @@ class ClassificationDataset:
|
|
|
768
768
|
self.cache_ram = False
|
|
769
769
|
self.cache_disk = str(args.cache).lower() == "disk" # cache images on hard drive as uncompressed *.npy files
|
|
770
770
|
self.samples = self.verify_images() # filter out bad images
|
|
771
|
-
self.samples = [list(x)
|
|
771
|
+
self.samples = [[*list(x), Path(x[0]).with_suffix(".npy"), None] for x in self.samples] # file, index, npy, im
|
|
772
772
|
scale = (1.0 - args.scale, 1.0) # (0.08, 1.0)
|
|
773
773
|
self.torch_transforms = (
|
|
774
774
|
classify_augmentations(
|
ultralytics/data/loaders.py
CHANGED
|
@@ -267,7 +267,7 @@ class LoadScreenshots:
|
|
|
267
267
|
channels (int): Number of image channels (1 for grayscale, 3 for RGB).
|
|
268
268
|
"""
|
|
269
269
|
check_requirements("mss")
|
|
270
|
-
import mss
|
|
270
|
+
import mss
|
|
271
271
|
|
|
272
272
|
source, *params = source.split()
|
|
273
273
|
self.screen, left, top, width, height = 0, None, None, None, None # default to full screen 0
|
|
@@ -690,7 +690,7 @@ def get_best_youtube_url(url: str, method: str = "pytube") -> str | None:
|
|
|
690
690
|
|
|
691
691
|
elif method == "pafy":
|
|
692
692
|
check_requirements(("pafy", "youtube_dl==2020.12.2"))
|
|
693
|
-
import pafy
|
|
693
|
+
import pafy
|
|
694
694
|
|
|
695
695
|
return pafy.new(url).getbestvideo(preftype="mp4").url
|
|
696
696
|
|
ultralytics/data/utils.py
CHANGED
|
@@ -460,7 +460,7 @@ def check_det_dataset(dataset: str, autodownload: bool = True) -> dict[str, Any]
|
|
|
460
460
|
if not all(x.exists() for x in val):
|
|
461
461
|
name = clean_url(dataset) # dataset name with URL auth stripped
|
|
462
462
|
LOGGER.info("")
|
|
463
|
-
m = f"Dataset '{name}' images not found, missing path '{
|
|
463
|
+
m = f"Dataset '{name}' images not found, missing path '{next(x for x in val if not x.exists())}'"
|
|
464
464
|
if s and autodownload:
|
|
465
465
|
LOGGER.warning(m)
|
|
466
466
|
else:
|
|
@@ -747,7 +747,7 @@ class HUBDatasetStats:
|
|
|
747
747
|
return self.im_dir
|
|
748
748
|
|
|
749
749
|
|
|
750
|
-
def compress_one_image(f: str, f_new: str = None, max_dim: int = 1920, quality: int = 50):
|
|
750
|
+
def compress_one_image(f: str, f_new: str | None = None, max_dim: int = 1920, quality: int = 50):
|
|
751
751
|
"""
|
|
752
752
|
Compress a single image file to reduced size while preserving its aspect ratio and quality using either the Python
|
|
753
753
|
Imaging Library (PIL) or OpenCV library. If the input image is smaller than the maximum dimension, it will not be
|
ultralytics/engine/exporter.py
CHANGED
|
@@ -636,7 +636,7 @@ class Exporter:
|
|
|
636
636
|
if self.args.simplify:
|
|
637
637
|
requirements += ["onnxslim>=0.1.71", "onnxruntime" + ("-gpu" if torch.cuda.is_available() else "")]
|
|
638
638
|
check_requirements(requirements)
|
|
639
|
-
import onnx
|
|
639
|
+
import onnx
|
|
640
640
|
|
|
641
641
|
opset = self.args.opset or best_onnx_opset(onnx, cuda="cuda" in self.device.type)
|
|
642
642
|
LOGGER.info(f"\n{prefix} starting export with onnx {onnx.__version__} opset {opset}...")
|
|
@@ -785,8 +785,8 @@ class Exporter:
|
|
|
785
785
|
"x2paddle",
|
|
786
786
|
)
|
|
787
787
|
)
|
|
788
|
-
import x2paddle
|
|
789
|
-
from x2paddle.convert import pytorch2paddle
|
|
788
|
+
import x2paddle
|
|
789
|
+
from x2paddle.convert import pytorch2paddle
|
|
790
790
|
|
|
791
791
|
LOGGER.info(f"\n{prefix} starting export with X2Paddle {x2paddle.__version__}...")
|
|
792
792
|
f = str(self.file).replace(self.file.suffix, f"_paddle_model{os.sep}")
|
|
@@ -801,7 +801,7 @@ class Exporter:
|
|
|
801
801
|
f_onnx = self.export_onnx() # get onnx model first
|
|
802
802
|
|
|
803
803
|
check_requirements("MNN>=2.9.6")
|
|
804
|
-
import MNN
|
|
804
|
+
import MNN
|
|
805
805
|
from MNN.tools import mnnconvert
|
|
806
806
|
|
|
807
807
|
# Setup and checks
|
|
@@ -824,7 +824,7 @@ class Exporter:
|
|
|
824
824
|
def export_ncnn(self, prefix=colorstr("NCNN:")):
|
|
825
825
|
"""Export YOLO model to NCNN format using PNNX https://github.com/pnnx/pnnx."""
|
|
826
826
|
check_requirements("ncnn", cmds="--no-deps") # no deps to avoid installing opencv-python
|
|
827
|
-
import ncnn
|
|
827
|
+
import ncnn
|
|
828
828
|
|
|
829
829
|
LOGGER.info(f"\n{prefix} starting export with NCNN {ncnn.__version__}...")
|
|
830
830
|
f = Path(str(self.file).replace(self.file.suffix, f"_ncnn_model{os.sep}"))
|
|
@@ -841,7 +841,7 @@ class Exporter:
|
|
|
841
841
|
system = "macos" if MACOS else "windows" if WINDOWS else "linux-aarch64" if ARM64 else "linux"
|
|
842
842
|
try:
|
|
843
843
|
release, assets = get_github_assets(repo="pnnx/pnnx")
|
|
844
|
-
asset =
|
|
844
|
+
asset = next(x for x in assets if f"{system}.zip" in x)
|
|
845
845
|
assert isinstance(asset, str), "Unable to retrieve PNNX repo assets" # i.e. pnnx-20250930-macos.zip
|
|
846
846
|
LOGGER.info(f"{prefix} successfully found latest PNNX asset file {asset}")
|
|
847
847
|
except Exception as e:
|
|
@@ -893,7 +893,7 @@ class Exporter:
|
|
|
893
893
|
"""Export YOLO model to CoreML format."""
|
|
894
894
|
mlmodel = self.args.format.lower() == "mlmodel" # legacy *.mlmodel export format requested
|
|
895
895
|
check_requirements("coremltools>=8.0")
|
|
896
|
-
import coremltools as ct
|
|
896
|
+
import coremltools as ct
|
|
897
897
|
|
|
898
898
|
LOGGER.info(f"\n{prefix} starting export with coremltools {ct.__version__}...")
|
|
899
899
|
assert not WINDOWS, "CoreML export is not supported on Windows, please run on macOS or Linux."
|
|
@@ -989,12 +989,12 @@ class Exporter:
|
|
|
989
989
|
f_onnx = self.export_onnx() # run before TRT import https://github.com/ultralytics/ultralytics/issues/7016
|
|
990
990
|
|
|
991
991
|
try:
|
|
992
|
-
import tensorrt as trt
|
|
992
|
+
import tensorrt as trt
|
|
993
993
|
except ImportError:
|
|
994
994
|
if LINUX:
|
|
995
995
|
cuda_version = torch.version.cuda.split(".")[0]
|
|
996
996
|
check_requirements(f"tensorrt-cu{cuda_version}>7.0.0,!=10.1.0")
|
|
997
|
-
import tensorrt as trt
|
|
997
|
+
import tensorrt as trt
|
|
998
998
|
check_version(trt.__version__, ">=7.0.0", hard=True)
|
|
999
999
|
check_version(trt.__version__, "!=10.1.0", msg="https://github.com/ultralytics/ultralytics/pull/14239")
|
|
1000
1000
|
|
|
@@ -1024,10 +1024,10 @@ class Exporter:
|
|
|
1024
1024
|
"""Export YOLO model to TensorFlow SavedModel format."""
|
|
1025
1025
|
cuda = torch.cuda.is_available()
|
|
1026
1026
|
try:
|
|
1027
|
-
import tensorflow as tf
|
|
1027
|
+
import tensorflow as tf
|
|
1028
1028
|
except ImportError:
|
|
1029
1029
|
check_requirements("tensorflow>=2.0.0,<=2.19.0")
|
|
1030
|
-
import tensorflow as tf
|
|
1030
|
+
import tensorflow as tf
|
|
1031
1031
|
check_requirements(
|
|
1032
1032
|
(
|
|
1033
1033
|
"tf_keras<=2.19.0", # required by 'onnx2tf' package
|
|
@@ -1113,8 +1113,8 @@ class Exporter:
|
|
|
1113
1113
|
@try_export
|
|
1114
1114
|
def export_pb(self, keras_model, prefix=colorstr("TensorFlow GraphDef:")):
|
|
1115
1115
|
"""Export YOLO model to TensorFlow GraphDef *.pb format https://github.com/leimao/Frozen-Graph-TensorFlow."""
|
|
1116
|
-
import tensorflow as tf
|
|
1117
|
-
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
|
|
1116
|
+
import tensorflow as tf
|
|
1117
|
+
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
|
|
1118
1118
|
|
|
1119
1119
|
LOGGER.info(f"\n{prefix} starting export with tensorflow {tf.__version__}...")
|
|
1120
1120
|
f = self.file.with_suffix(".pb")
|
|
@@ -1130,7 +1130,7 @@ class Exporter:
|
|
|
1130
1130
|
def export_tflite(self, prefix=colorstr("TensorFlow Lite:")):
|
|
1131
1131
|
"""Export YOLO model to TensorFlow Lite format."""
|
|
1132
1132
|
# BUG https://github.com/ultralytics/ultralytics/issues/13436
|
|
1133
|
-
import tensorflow as tf
|
|
1133
|
+
import tensorflow as tf
|
|
1134
1134
|
|
|
1135
1135
|
LOGGER.info(f"\n{prefix} starting export with tensorflow {tf.__version__}...")
|
|
1136
1136
|
saved_model = Path(str(self.file).replace(self.file.suffix, "_saved_model"))
|
|
@@ -1215,7 +1215,7 @@ class Exporter:
|
|
|
1215
1215
|
"""Export YOLO model to TensorFlow.js format."""
|
|
1216
1216
|
check_requirements("tensorflowjs")
|
|
1217
1217
|
import tensorflow as tf
|
|
1218
|
-
import tensorflowjs as tfjs
|
|
1218
|
+
import tensorflowjs as tfjs
|
|
1219
1219
|
|
|
1220
1220
|
LOGGER.info(f"\n{prefix} starting export with tensorflowjs {tfjs.__version__}...")
|
|
1221
1221
|
f = str(self.file).replace(self.file.suffix, "_web_model") # js dir
|
|
@@ -1315,7 +1315,7 @@ class Exporter:
|
|
|
1315
1315
|
|
|
1316
1316
|
def _pipeline_coreml(self, model, weights_dir=None, prefix=colorstr("CoreML Pipeline:")):
|
|
1317
1317
|
"""Create CoreML pipeline with NMS for YOLO detection models."""
|
|
1318
|
-
import coremltools as ct
|
|
1318
|
+
import coremltools as ct
|
|
1319
1319
|
|
|
1320
1320
|
LOGGER.info(f"{prefix} starting pipeline with coremltools {ct.__version__}...")
|
|
1321
1321
|
|
ultralytics/engine/model.py
CHANGED
ultralytics/engine/trainer.py
CHANGED
|
@@ -6,6 +6,8 @@ Usage:
|
|
|
6
6
|
$ yolo mode=train model=yolo11n.pt data=coco8.yaml imgsz=640 epochs=100 batch=16
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
9
11
|
import gc
|
|
10
12
|
import math
|
|
11
13
|
import os
|
|
@@ -545,7 +547,7 @@ class BaseTrainer:
|
|
|
545
547
|
total = torch.cuda.get_device_properties(self.device).total_memory
|
|
546
548
|
return ((memory / total) if total > 0 else 0) if fraction else (memory / 2**30)
|
|
547
549
|
|
|
548
|
-
def _clear_memory(self, threshold: float = None):
|
|
550
|
+
def _clear_memory(self, threshold: float | None = None):
|
|
549
551
|
"""Clear accelerator memory by calling garbage collector and emptying cache."""
|
|
550
552
|
if threshold:
|
|
551
553
|
assert 0 <= threshold <= 1, "Threshold must be between 0 and 1."
|
|
@@ -759,9 +761,9 @@ class BaseTrainer:
|
|
|
759
761
|
n = len(metrics) + 2 # number of cols
|
|
760
762
|
t = time.time() - self.train_time_start
|
|
761
763
|
self.csv.parent.mkdir(parents=True, exist_ok=True) # ensure parent directory exists
|
|
762
|
-
s = "" if self.csv.exists() else (("%s," * n % tuple(["epoch", "time"
|
|
764
|
+
s = "" if self.csv.exists() else (("%s," * n % tuple(["epoch", "time", *keys])).rstrip(",") + "\n") # header
|
|
763
765
|
with open(self.csv, "a", encoding="utf-8") as f:
|
|
764
|
-
f.write(s + ("%.6g," * n % tuple([self.epoch + 1, t
|
|
766
|
+
f.write(s + ("%.6g," * n % tuple([self.epoch + 1, t, *vals])).rstrip(",") + "\n")
|
|
765
767
|
|
|
766
768
|
def plot_metrics(self):
|
|
767
769
|
"""Plot metrics from a CSV file."""
|
ultralytics/engine/tuner.py
CHANGED
|
@@ -257,13 +257,13 @@ class Tuner:
|
|
|
257
257
|
return
|
|
258
258
|
|
|
259
259
|
# Write to CSV
|
|
260
|
-
headers = ",".join(["fitness"
|
|
260
|
+
headers = ",".join(["fitness", *list(self.space.keys())]) + "\n"
|
|
261
261
|
with open(self.tune_csv, "w", encoding="utf-8") as f:
|
|
262
262
|
f.write(headers)
|
|
263
263
|
for result in all_results:
|
|
264
264
|
fitness = result["fitness"]
|
|
265
265
|
hyp_values = [result["hyperparameters"][k] for k in self.space.keys()]
|
|
266
|
-
log_row = [round(fitness, 5)
|
|
266
|
+
log_row = [round(fitness, 5), *hyp_values]
|
|
267
267
|
f.write(",".join(map(str, log_row)) + "\n")
|
|
268
268
|
|
|
269
269
|
except Exception as e:
|
|
@@ -344,7 +344,7 @@ class Tuner:
|
|
|
344
344
|
|
|
345
345
|
# Update types
|
|
346
346
|
if "close_mosaic" in hyp:
|
|
347
|
-
hyp["close_mosaic"] =
|
|
347
|
+
hyp["close_mosaic"] = round(hyp["close_mosaic"])
|
|
348
348
|
|
|
349
349
|
return hyp
|
|
350
350
|
|
|
@@ -421,7 +421,7 @@ class Tuner:
|
|
|
421
421
|
else:
|
|
422
422
|
# Save to CSV only if no MongoDB
|
|
423
423
|
log_row = [round(fitness, 5)] + [mutated_hyp[k] for k in self.space.keys()]
|
|
424
|
-
headers = "" if self.tune_csv.exists() else (",".join(["fitness"
|
|
424
|
+
headers = "" if self.tune_csv.exists() else (",".join(["fitness", *list(self.space.keys())]) + "\n")
|
|
425
425
|
with open(self.tune_csv, "a", encoding="utf-8") as f:
|
|
426
426
|
f.write(headers + ",".join(map(str, log_row)) + "\n")
|
|
427
427
|
|
ultralytics/hub/__init__.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
|
from ultralytics.data.utils import HUBDatasetStats
|
|
4
6
|
from ultralytics.hub.auth import Auth
|
|
5
7
|
from ultralytics.hub.session import HUBTrainingSession
|
|
@@ -7,20 +9,20 @@ from ultralytics.hub.utils import HUB_API_ROOT, HUB_WEB_ROOT, PREFIX
|
|
|
7
9
|
from ultralytics.utils import LOGGER, SETTINGS, checks
|
|
8
10
|
|
|
9
11
|
__all__ = (
|
|
10
|
-
"PREFIX",
|
|
11
12
|
"HUB_WEB_ROOT",
|
|
13
|
+
"PREFIX",
|
|
12
14
|
"HUBTrainingSession",
|
|
13
|
-
"
|
|
14
|
-
"logout",
|
|
15
|
-
"reset_model",
|
|
15
|
+
"check_dataset",
|
|
16
16
|
"export_fmts_hub",
|
|
17
17
|
"export_model",
|
|
18
18
|
"get_export",
|
|
19
|
-
"
|
|
19
|
+
"login",
|
|
20
|
+
"logout",
|
|
21
|
+
"reset_model",
|
|
20
22
|
)
|
|
21
23
|
|
|
22
24
|
|
|
23
|
-
def login(api_key: str = None, save: bool = True) -> bool:
|
|
25
|
+
def login(api_key: str | None = None, save: bool = True) -> bool:
|
|
24
26
|
"""
|
|
25
27
|
Log in to the Ultralytics HUB API using the provided API key.
|
|
26
28
|
|
|
@@ -85,7 +87,7 @@ def export_fmts_hub():
|
|
|
85
87
|
"""Return a list of HUB-supported export formats."""
|
|
86
88
|
from ultralytics.engine.exporter import export_formats
|
|
87
89
|
|
|
88
|
-
return list(export_formats()["Argument"][1:])
|
|
90
|
+
return [*list(export_formats()["Argument"][1:]), "ultralytics_tflite", "ultralytics_coreml"]
|
|
89
91
|
|
|
90
92
|
|
|
91
93
|
def export_model(model_id: str = "", format: str = "torchscript"):
|
ultralytics/hub/utils.py
CHANGED
|
@@ -35,8 +35,8 @@ def request_with_credentials(url: str) -> Any:
|
|
|
35
35
|
"""
|
|
36
36
|
if not IS_COLAB:
|
|
37
37
|
raise OSError("request_with_credentials() must run in a Colab environment")
|
|
38
|
-
from google.colab import output
|
|
39
|
-
from IPython import display
|
|
38
|
+
from google.colab import output
|
|
39
|
+
from IPython import display
|
|
40
40
|
|
|
41
41
|
display.display(
|
|
42
42
|
display.Javascript(
|
ultralytics/models/__init__.py
CHANGED
|
@@ -6,4 +6,4 @@ from .rtdetr import RTDETR
|
|
|
6
6
|
from .sam import SAM
|
|
7
7
|
from .yolo import YOLO, YOLOE, YOLOWorld
|
|
8
8
|
|
|
9
|
-
__all__ = "
|
|
9
|
+
__all__ = "NAS", "RTDETR", "SAM", "YOLO", "YOLOE", "FastSAM", "YOLOWorld" # allow simpler import
|
|
@@ -6,7 +6,7 @@ from .predict import Predictor, SAM2DynamicInteractivePredictor, SAM2Predictor,
|
|
|
6
6
|
__all__ = (
|
|
7
7
|
"SAM",
|
|
8
8
|
"Predictor",
|
|
9
|
+
"SAM2DynamicInteractivePredictor",
|
|
9
10
|
"SAM2Predictor",
|
|
10
11
|
"SAM2VideoPredictor",
|
|
11
|
-
"SAM2DynamicInteractivePredictor",
|
|
12
12
|
) # tuple or list of exportable items
|
ultralytics/models/sam/amg.py
CHANGED
|
@@ -145,7 +145,7 @@ def generate_crop_boxes(
|
|
|
145
145
|
|
|
146
146
|
def crop_len(orig_len, n_crops, overlap):
|
|
147
147
|
"""Calculate the length of each crop given the original length, number of crops, and overlap."""
|
|
148
|
-
return
|
|
148
|
+
return math.ceil((overlap * (n_crops - 1) + orig_len) / n_crops)
|
|
149
149
|
|
|
150
150
|
for i_layer in range(n_layers):
|
|
151
151
|
n_crops_per_side = 2 ** (i_layer + 1)
|
|
@@ -227,7 +227,7 @@ def remove_small_regions(mask: np.ndarray, area_thresh: float, mode: str) -> tup
|
|
|
227
227
|
small_regions = [i + 1 for i, s in enumerate(sizes) if s < area_thresh]
|
|
228
228
|
if not small_regions:
|
|
229
229
|
return mask, False
|
|
230
|
-
fill_labels = [0
|
|
230
|
+
fill_labels = [0, *small_regions]
|
|
231
231
|
if not correct_holes:
|
|
232
232
|
# If every region is below threshold, keep largest
|
|
233
233
|
fill_labels = [i for i in range(n_labels) if i not in fill_labels] or [int(np.argmax(sizes)) + 1]
|
|
@@ -619,7 +619,7 @@ class MultiScaleBlock(nn.Module):
|
|
|
619
619
|
mlp_ratio: float = 4.0,
|
|
620
620
|
drop_path: float = 0.0,
|
|
621
621
|
norm_layer: nn.Module | str = "LayerNorm",
|
|
622
|
-
q_stride: tuple[int, int] = None,
|
|
622
|
+
q_stride: tuple[int, int] | None = None,
|
|
623
623
|
act_layer: type[nn.Module] = nn.GELU,
|
|
624
624
|
window_size: int = 0,
|
|
625
625
|
):
|
|
@@ -280,7 +280,7 @@ class Attention(nn.Module):
|
|
|
280
280
|
embedding_dim: int,
|
|
281
281
|
num_heads: int,
|
|
282
282
|
downsample_rate: int = 1,
|
|
283
|
-
kv_in_dim: int = None,
|
|
283
|
+
kv_in_dim: int | None = None,
|
|
284
284
|
) -> None:
|
|
285
285
|
"""
|
|
286
286
|
Initialize the Attention module with specified dimensions and settings.
|
|
@@ -1850,7 +1850,7 @@ class SAM2DynamicInteractivePredictor(SAM2Predictor):
|
|
|
1850
1850
|
@smart_inference_mode()
|
|
1851
1851
|
def update_memory(
|
|
1852
1852
|
self,
|
|
1853
|
-
obj_ids: list[int] = None,
|
|
1853
|
+
obj_ids: list[int] | None = None,
|
|
1854
1854
|
points: torch.Tensor | None = None,
|
|
1855
1855
|
labels: torch.Tensor | None = None,
|
|
1856
1856
|
masks: torch.Tensor | None = None,
|
|
@@ -4,4 +4,4 @@ from ultralytics.models.yolo import classify, detect, obb, pose, segment, world,
|
|
|
4
4
|
|
|
5
5
|
from .model import YOLO, YOLOE, YOLOWorld
|
|
6
6
|
|
|
7
|
-
__all__ = "
|
|
7
|
+
__all__ = "YOLO", "YOLOE", "YOLOWorld", "classify", "detect", "obb", "pose", "segment", "world", "yoloe"
|
|
@@ -222,7 +222,7 @@ class SegmentationValidator(DetectionValidator):
|
|
|
222
222
|
predn (dict[str, torch.Tensor]): Predictions containing bboxes, masks, confidence scores, and classes.
|
|
223
223
|
pbatch (dict[str, Any]): Batch dictionary containing 'imgsz', 'ori_shape', 'ratio_pad', and 'im_file'.
|
|
224
224
|
"""
|
|
225
|
-
from faster_coco_eval.core.mask import encode
|
|
225
|
+
from faster_coco_eval.core.mask import encode
|
|
226
226
|
|
|
227
227
|
def single_encode(x):
|
|
228
228
|
"""Encode predicted masks as RLE and append results to jdict."""
|
|
@@ -6,17 +6,17 @@ from .train_seg import YOLOEPESegTrainer, YOLOESegTrainer, YOLOESegTrainerFromSc
|
|
|
6
6
|
from .val import YOLOEDetectValidator, YOLOESegValidator
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
|
-
"YOLOETrainer",
|
|
10
|
-
"YOLOEPETrainer",
|
|
11
|
-
"YOLOESegTrainer",
|
|
12
9
|
"YOLOEDetectValidator",
|
|
13
|
-
"
|
|
10
|
+
"YOLOEPEFreeTrainer",
|
|
14
11
|
"YOLOEPESegTrainer",
|
|
12
|
+
"YOLOEPETrainer",
|
|
13
|
+
"YOLOESegTrainer",
|
|
15
14
|
"YOLOESegTrainerFromScratch",
|
|
16
15
|
"YOLOESegVPTrainer",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
16
|
+
"YOLOESegValidator",
|
|
17
|
+
"YOLOETrainer",
|
|
18
|
+
"YOLOETrainerFromScratch",
|
|
19
19
|
"YOLOEVPDetectPredictor",
|
|
20
20
|
"YOLOEVPSegPredictor",
|
|
21
|
-
"
|
|
21
|
+
"YOLOEVPTrainer",
|
|
22
22
|
]
|
ultralytics/nn/__init__.py
CHANGED
|
@@ -14,14 +14,14 @@ from .tasks import (
|
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
__all__ = (
|
|
17
|
+
"BaseModel",
|
|
18
|
+
"ClassificationModel",
|
|
19
|
+
"DetectionModel",
|
|
20
|
+
"SegmentationModel",
|
|
21
|
+
"guess_model_scale",
|
|
22
|
+
"guess_model_task",
|
|
17
23
|
"load_checkpoint",
|
|
18
24
|
"parse_model",
|
|
19
|
-
"yaml_model_load",
|
|
20
|
-
"guess_model_task",
|
|
21
|
-
"guess_model_scale",
|
|
22
25
|
"torch_safe_load",
|
|
23
|
-
"
|
|
24
|
-
"SegmentationModel",
|
|
25
|
-
"ClassificationModel",
|
|
26
|
-
"BaseModel",
|
|
26
|
+
"yaml_model_load",
|
|
27
27
|
)
|
ultralytics/nn/autobackend.py
CHANGED
|
@@ -337,11 +337,11 @@ class AutoBackend(nn.Module):
|
|
|
337
337
|
check_requirements("numpy==1.23.5")
|
|
338
338
|
|
|
339
339
|
try: # https://developer.nvidia.com/nvidia-tensorrt-download
|
|
340
|
-
import tensorrt as trt
|
|
340
|
+
import tensorrt as trt
|
|
341
341
|
except ImportError:
|
|
342
342
|
if LINUX:
|
|
343
343
|
check_requirements("tensorrt>7.0.0,!=10.1.0")
|
|
344
|
-
import tensorrt as trt
|
|
344
|
+
import tensorrt as trt
|
|
345
345
|
check_version(trt.__version__, ">=7.0.0", hard=True)
|
|
346
346
|
check_version(trt.__version__, "!=10.1.0", msg="https://github.com/ultralytics/ultralytics/pull/14239")
|
|
347
347
|
if device.type == "cpu":
|
|
@@ -496,7 +496,7 @@ class AutoBackend(nn.Module):
|
|
|
496
496
|
if ARM64
|
|
497
497
|
else "paddlepaddle>=3.0.0"
|
|
498
498
|
)
|
|
499
|
-
import paddle.inference as pdi
|
|
499
|
+
import paddle.inference as pdi
|
|
500
500
|
|
|
501
501
|
w = Path(w)
|
|
502
502
|
model_file, params_file = None, None
|
|
@@ -652,7 +652,7 @@ class AutoBackend(nn.Module):
|
|
|
652
652
|
Returns:
|
|
653
653
|
(torch.Tensor | list[torch.Tensor]): The raw output tensor(s) from the model.
|
|
654
654
|
"""
|
|
655
|
-
|
|
655
|
+
_b, _ch, h, w = im.shape # batch, channel, height, width
|
|
656
656
|
if self.fp16 and im.dtype != torch.float16:
|
|
657
657
|
im = im.half() # to FP16
|
|
658
658
|
if self.nhwc:
|
|
@@ -919,4 +919,4 @@ class AutoBackend(nn.Module):
|
|
|
919
919
|
url = urlsplit(p)
|
|
920
920
|
triton = bool(url.netloc) and bool(url.path) and url.scheme in {"http", "grpc"}
|
|
921
921
|
|
|
922
|
-
return types
|
|
922
|
+
return [*types, triton]
|