ultralytics 8.3.123__py3-none-any.whl → 8.3.125__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tests/test_python.py +5 -8
- ultralytics/__init__.py +1 -1
- ultralytics/cfg/__init__.py +7 -14
- ultralytics/cfg/default.yaml +2 -2
- ultralytics/data/base.py +1 -2
- ultralytics/data/loaders.py +3 -4
- ultralytics/data/utils.py +8 -9
- ultralytics/engine/exporter.py +7 -7
- ultralytics/engine/model.py +7 -4
- ultralytics/engine/trainer.py +2 -2
- ultralytics/engine/tuner.py +3 -3
- ultralytics/hub/session.py +1 -1
- ultralytics/models/sam/model.py +2 -1
- ultralytics/models/sam/modules/tiny_encoder.py +2 -3
- ultralytics/models/sam/predict.py +4 -1
- ultralytics/models/yolo/model.py +3 -3
- ultralytics/nn/autobackend.py +4 -4
- ultralytics/nn/tasks.py +7 -7
- ultralytics/solutions/analytics.py +9 -8
- ultralytics/solutions/config.py +104 -0
- ultralytics/solutions/heatmap.py +1 -1
- ultralytics/solutions/object_blurrer.py +1 -1
- ultralytics/solutions/object_cropper.py +2 -2
- ultralytics/solutions/parking_management.py +2 -2
- ultralytics/solutions/security_alarm.py +1 -1
- ultralytics/solutions/solutions.py +6 -9
- ultralytics/solutions/speed_estimation.py +4 -4
- ultralytics/solutions/trackzone.py +1 -1
- ultralytics/solutions/vision_eye.py +1 -1
- ultralytics/trackers/track.py +2 -2
- ultralytics/utils/__init__.py +115 -59
- ultralytics/utils/benchmarks.py +4 -8
- ultralytics/utils/checks.py +4 -3
- ultralytics/utils/dist.py +2 -1
- ultralytics/utils/downloads.py +6 -1
- ultralytics/utils/metrics.py +6 -2
- ultralytics/utils/plotting.py +11 -5
- ultralytics/utils/torch_utils.py +10 -5
- {ultralytics-8.3.123.dist-info → ultralytics-8.3.125.dist-info}/METADATA +1 -1
- {ultralytics-8.3.123.dist-info → ultralytics-8.3.125.dist-info}/RECORD +44 -44
- {ultralytics-8.3.123.dist-info → ultralytics-8.3.125.dist-info}/WHEEL +1 -1
- ultralytics/cfg/solutions/default.yaml +0 -24
- {ultralytics-8.3.123.dist-info → ultralytics-8.3.125.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.3.123.dist-info → ultralytics-8.3.125.dist-info}/licenses/LICENSE +0 -0
- {ultralytics-8.3.123.dist-info → ultralytics-8.3.125.dist-info}/top_level.txt +0 -0
tests/test_python.py
CHANGED
@@ -10,7 +10,6 @@ import cv2
|
|
10
10
|
import numpy as np
|
11
11
|
import pytest
|
12
12
|
import torch
|
13
|
-
import yaml
|
14
13
|
from PIL import Image
|
15
14
|
|
16
15
|
from tests import CFG, MODEL, SOURCE, SOURCES_LIST, TMP
|
@@ -28,6 +27,7 @@ from ultralytics.utils import (
|
|
28
27
|
ROOT,
|
29
28
|
WEIGHTS_DIR,
|
30
29
|
WINDOWS,
|
30
|
+
YAML,
|
31
31
|
checks,
|
32
32
|
is_dir_writeable,
|
33
33
|
is_github_action_running,
|
@@ -190,13 +190,10 @@ def test_track_stream():
|
|
190
190
|
|
191
191
|
# Test Global Motion Compensation (GMC) methods
|
192
192
|
for gmc in "orb", "sift", "ecc":
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
with open(tracker, "w", encoding="utf-8") as f:
|
198
|
-
yaml.safe_dump(data, f)
|
199
|
-
model.track(video_url, imgsz=160, tracker=tracker)
|
193
|
+
default_args = YAML.load(ROOT / "cfg/trackers/botsort.yaml")
|
194
|
+
custom_yaml = TMP / f"botsort-{gmc}.yaml"
|
195
|
+
YAML.save(custom_yaml, {**default_args, "gmc_method": gmc})
|
196
|
+
model.track(video_url, imgsz=160, tracker=custom_yaml)
|
200
197
|
|
201
198
|
|
202
199
|
def test_val():
|
ultralytics/__init__.py
CHANGED
ultralytics/cfg/__init__.py
CHANGED
@@ -15,7 +15,6 @@ from ultralytics.utils import (
|
|
15
15
|
DEFAULT_CFG,
|
16
16
|
DEFAULT_CFG_DICT,
|
17
17
|
DEFAULT_CFG_PATH,
|
18
|
-
DEFAULT_SOL_DICT,
|
19
18
|
IS_VSCODE,
|
20
19
|
LOGGER,
|
21
20
|
RANK,
|
@@ -24,13 +23,12 @@ from ultralytics.utils import (
|
|
24
23
|
SETTINGS,
|
25
24
|
SETTINGS_FILE,
|
26
25
|
TESTS_RUNNING,
|
26
|
+
YAML,
|
27
27
|
IterableSimpleNamespace,
|
28
28
|
checks,
|
29
29
|
colorstr,
|
30
30
|
deprecation_warn,
|
31
31
|
vscode_msg,
|
32
|
-
yaml_load,
|
33
|
-
yaml_print,
|
34
32
|
)
|
35
33
|
|
36
34
|
# Define valid solutions
|
@@ -271,7 +269,7 @@ def cfg2dict(cfg: Union[str, Path, Dict, SimpleNamespace]) -> Dict:
|
|
271
269
|
- If cfg is already a dictionary, it's returned unchanged.
|
272
270
|
"""
|
273
271
|
if isinstance(cfg, (str, Path)):
|
274
|
-
cfg =
|
272
|
+
cfg = YAML.load(cfg) # load dict
|
275
273
|
elif isinstance(cfg, SimpleNamespace):
|
276
274
|
cfg = vars(cfg) # convert to dict
|
277
275
|
return cfg
|
@@ -650,7 +648,6 @@ def handle_yolo_solutions(args: List[str]) -> None:
|
|
650
648
|
>>> handle_yolo_solutions(["inference", "model=yolo11n.pt"])
|
651
649
|
|
652
650
|
Notes:
|
653
|
-
- Default configurations are merged from DEFAULT_SOL_DICT and DEFAULT_CFG_DICT
|
654
651
|
- Arguments can be provided in the format 'key=value' or as boolean flags
|
655
652
|
- Available solutions are defined in SOLUTION_MAP with their respective classes and methods
|
656
653
|
- If an invalid solution is provided, defaults to 'count' solution
|
@@ -662,13 +659,9 @@ def handle_yolo_solutions(args: List[str]) -> None:
|
|
662
659
|
- The inference solution will be launched using the 'streamlit run' command.
|
663
660
|
- The Streamlit app file is located in the Ultralytics package directory.
|
664
661
|
"""
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
"blur_ratio": 0.5,
|
669
|
-
"vision_point": (20, 20),
|
670
|
-
"crop_dir": "cropped-detections",
|
671
|
-
} # arguments dictionary
|
662
|
+
from ultralytics.solutions.config import SolutionConfig
|
663
|
+
|
664
|
+
full_args_dict = vars(SolutionConfig()) # arguments dictionary
|
672
665
|
overrides = {}
|
673
666
|
|
674
667
|
# check dictionary alignment
|
@@ -859,7 +852,7 @@ def entrypoint(debug: str = "") -> None:
|
|
859
852
|
"checks": checks.collect_system_info,
|
860
853
|
"version": lambda: LOGGER.info(__version__),
|
861
854
|
"settings": lambda: handle_yolo_settings(args[1:]),
|
862
|
-
"cfg": lambda:
|
855
|
+
"cfg": lambda: YAML.print(DEFAULT_CFG_PATH),
|
863
856
|
"hub": lambda: handle_yolo_hub(args[1:]),
|
864
857
|
"login": lambda: handle_yolo_hub(args),
|
865
858
|
"logout": lambda: handle_yolo_hub(args),
|
@@ -886,7 +879,7 @@ def entrypoint(debug: str = "") -> None:
|
|
886
879
|
k, v = parse_key_value_pair(a)
|
887
880
|
if k == "cfg" and v is not None: # custom.yaml passed
|
888
881
|
LOGGER.info(f"Overriding {DEFAULT_CFG_PATH} with {v}")
|
889
|
-
overrides = {k: val for k, val in
|
882
|
+
overrides = {k: val for k, val in YAML.load(checks.check_yaml(v)).items() if k != "cfg"}
|
890
883
|
else:
|
891
884
|
overrides[k] = v
|
892
885
|
except (NameError, SyntaxError, ValueError, AssertionError) as e:
|
ultralytics/cfg/default.yaml
CHANGED
@@ -35,7 +35,7 @@ resume: False # (bool) resume training from last checkpoint
|
|
35
35
|
amp: True # (bool) Automatic Mixed Precision (AMP) training, choices=[True, False], True runs AMP check
|
36
36
|
fraction: 1.0 # (float) dataset fraction to train on (default is 1.0, all images in train set)
|
37
37
|
profile: False # (bool) profile ONNX and TensorRT speeds during training for loggers
|
38
|
-
freeze:
|
38
|
+
freeze: # (int | list, optional) freeze first n layers, or freeze list of layer indices during training
|
39
39
|
multi_scale: False # (bool) Whether to use multiscale during training
|
40
40
|
# Segmentation
|
41
41
|
overlap_mask: True # (bool) merge object masks into a single image mask during training (segment train only)
|
@@ -84,7 +84,7 @@ int8: False # (bool) CoreML/TF INT8 quantization
|
|
84
84
|
dynamic: False # (bool) ONNX/TF/TensorRT: dynamic axes
|
85
85
|
simplify: True # (bool) ONNX: simplify model using `onnxslim`
|
86
86
|
opset: # (int, optional) ONNX: opset version
|
87
|
-
workspace:
|
87
|
+
workspace: # (float, optional) TensorRT: workspace size (GiB), `None` will let TensorRT auto-allocate memory
|
88
88
|
nms: False # (bool) CoreML: add NMS
|
89
89
|
|
90
90
|
# Hyperparameters ------------------------------------------------------------------------------------------------------
|
ultralytics/data/base.py
CHANGED
@@ -11,7 +11,6 @@ from typing import Optional
|
|
11
11
|
|
12
12
|
import cv2
|
13
13
|
import numpy as np
|
14
|
-
import psutil
|
15
14
|
from torch.utils.data import Dataset
|
16
15
|
|
17
16
|
from ultralytics.data.utils import FORMATS_HELP_MSG, HELP_URL, IMG_FORMATS, check_file_speeds
|
@@ -336,7 +335,7 @@ class BaseDataset(Dataset):
|
|
336
335
|
ratio = self.imgsz / max(im.shape[0], im.shape[1]) # max(h, w) # ratio
|
337
336
|
b += im.nbytes * ratio**2
|
338
337
|
mem_required = b * self.ni / n * (1 + safety_margin) # GB required to cache dataset into RAM
|
339
|
-
mem = psutil.virtual_memory()
|
338
|
+
mem = __import__("psutil").virtual_memory()
|
340
339
|
if mem_required > mem.available:
|
341
340
|
self.cache = None
|
342
341
|
LOGGER.warning(
|
ultralytics/data/loaders.py
CHANGED
@@ -4,14 +4,13 @@ import glob
|
|
4
4
|
import math
|
5
5
|
import os
|
6
6
|
import time
|
7
|
+
import urllib
|
7
8
|
from dataclasses import dataclass
|
8
9
|
from pathlib import Path
|
9
10
|
from threading import Thread
|
10
|
-
from urllib.parse import urlparse
|
11
11
|
|
12
12
|
import cv2
|
13
13
|
import numpy as np
|
14
|
-
import requests
|
15
14
|
import torch
|
16
15
|
from PIL import Image
|
17
16
|
|
@@ -111,7 +110,7 @@ class LoadStreams:
|
|
111
110
|
for i, s in enumerate(sources): # index, source
|
112
111
|
# Start thread to read frames from video stream
|
113
112
|
st = f"{i + 1}/{n}: {s}... "
|
114
|
-
if urlparse(s).hostname in {"www.youtube.com", "youtube.com", "youtu.be"}: #
|
113
|
+
if urllib.parse.urlparse(s).hostname in {"www.youtube.com", "youtube.com", "youtu.be"}: # YouTube video
|
115
114
|
# YouTube format i.e. 'https://www.youtube.com/watch?v=Jsn8D3aC840' or 'https://youtu.be/Jsn8D3aC840'
|
116
115
|
s = get_best_youtube_url(s)
|
117
116
|
s = eval(s) if s.isnumeric() else s # i.e. s = '0' local webcam
|
@@ -589,7 +588,7 @@ def autocast_list(source):
|
|
589
588
|
files = []
|
590
589
|
for im in source:
|
591
590
|
if isinstance(im, (str, Path)): # filename or uri
|
592
|
-
files.append(Image.open(
|
591
|
+
files.append(Image.open(urllib.request.urlopen(im) if str(im).startswith("http") else im))
|
593
592
|
elif isinstance(im, (Image.Image, np.ndarray)): # PIL or np Image
|
594
593
|
files.append(im)
|
595
594
|
else:
|
ultralytics/data/utils.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
|
-
import hashlib
|
4
3
|
import json
|
5
4
|
import os
|
6
5
|
import random
|
@@ -19,16 +18,16 @@ from ultralytics.nn.autobackend import check_class_names
|
|
19
18
|
from ultralytics.utils import (
|
20
19
|
DATASETS_DIR,
|
21
20
|
LOGGER,
|
21
|
+
MACOS,
|
22
22
|
NUM_THREADS,
|
23
23
|
ROOT,
|
24
24
|
SETTINGS_FILE,
|
25
25
|
TQDM,
|
26
|
+
YAML,
|
26
27
|
clean_url,
|
27
28
|
colorstr,
|
28
29
|
emojis,
|
29
30
|
is_dir_writeable,
|
30
|
-
yaml_load,
|
31
|
-
yaml_save,
|
32
31
|
)
|
33
32
|
from ultralytics.utils.checks import check_file, check_font, is_ascii
|
34
33
|
from ultralytics.utils.downloads import download, safe_download, unzip_file
|
@@ -37,7 +36,7 @@ from ultralytics.utils.ops import segments2boxes
|
|
37
36
|
HELP_URL = "See https://docs.ultralytics.com/datasets for dataset formatting guidance."
|
38
37
|
IMG_FORMATS = {"bmp", "dng", "jpeg", "jpg", "mpo", "png", "tif", "tiff", "webp", "pfm", "heic"} # image suffixes
|
39
38
|
VID_FORMATS = {"asf", "avi", "gif", "m4v", "mkv", "mov", "mp4", "mpeg", "mpg", "ts", "wmv", "webm"} # video suffixes
|
40
|
-
PIN_MEMORY = str(os.getenv("PIN_MEMORY",
|
39
|
+
PIN_MEMORY = str(os.getenv("PIN_MEMORY", not MACOS)).lower() == "true" # global pin_memory for dataloaders
|
41
40
|
FORMATS_HELP_MSG = f"Supported formats are:\nimages: {IMG_FORMATS}\nvideos: {VID_FORMATS}"
|
42
41
|
|
43
42
|
|
@@ -131,7 +130,7 @@ def get_hash(paths):
|
|
131
130
|
size += os.stat(p).st_size
|
132
131
|
except OSError:
|
133
132
|
continue
|
134
|
-
h = hashlib.sha256(str(size).encode()) # hash sizes
|
133
|
+
h = __import__("hashlib").sha256(str(size).encode()) # hash sizes
|
135
134
|
h.update("".join(paths).encode()) # hash paths
|
136
135
|
return h.hexdigest() # return hash
|
137
136
|
|
@@ -400,7 +399,7 @@ def check_det_dataset(dataset, autodownload=True):
|
|
400
399
|
extract_dir, autodownload = file.parent, False
|
401
400
|
|
402
401
|
# Read YAML
|
403
|
-
data =
|
402
|
+
data = YAML.load(file, append_filename=True) # dictionary
|
404
403
|
|
405
404
|
# Checks
|
406
405
|
for k in "train", "val":
|
@@ -493,7 +492,7 @@ def check_cls_dataset(dataset, split=""):
|
|
493
492
|
# Download (optional if dataset=https://file.zip is passed directly)
|
494
493
|
if str(dataset).startswith(("http:/", "https:/")):
|
495
494
|
dataset = safe_download(dataset, dir=DATASETS_DIR, unzip=True, delete=False)
|
496
|
-
elif
|
495
|
+
elif str(dataset).endswith((".zip", ".tar", ".gz")):
|
497
496
|
file = check_file(dataset)
|
498
497
|
dataset = safe_download(file, dir=DATASETS_DIR, unzip=True, delete=False)
|
499
498
|
|
@@ -600,9 +599,9 @@ class HUBDatasetStats:
|
|
600
599
|
_, data_dir, yaml_path = self._unzip(Path(path))
|
601
600
|
try:
|
602
601
|
# Load YAML with checks
|
603
|
-
data =
|
602
|
+
data = YAML.load(yaml_path)
|
604
603
|
data["path"] = "" # strip path since YAML should be in dataset root for all HUB datasets
|
605
|
-
|
604
|
+
YAML.save(yaml_path, data)
|
606
605
|
data = check_det_dataset(yaml_path, autodownload) # dict
|
607
606
|
data["path"] = data_dir # YAML path should be set to '' (relative) or parent (absolute)
|
608
607
|
except Exception as e:
|
ultralytics/engine/exporter.py
CHANGED
@@ -89,10 +89,10 @@ from ultralytics.utils import (
|
|
89
89
|
RKNN_CHIPS,
|
90
90
|
ROOT,
|
91
91
|
WINDOWS,
|
92
|
+
YAML,
|
92
93
|
callbacks,
|
93
94
|
colorstr,
|
94
95
|
get_default_args,
|
95
|
-
yaml_save,
|
96
96
|
)
|
97
97
|
from ultralytics.utils.checks import (
|
98
98
|
check_imgsz,
|
@@ -631,7 +631,7 @@ class Exporter:
|
|
631
631
|
ov_model.set_rt_info("fit_to_window_letterbox", ["model_info", "resize_type"])
|
632
632
|
|
633
633
|
ov.save_model(ov_model, file, compress_to_fp16=self.args.half)
|
634
|
-
|
634
|
+
YAML.save(Path(file).parent / "metadata.yaml", self.metadata) # add metadata.yaml
|
635
635
|
|
636
636
|
if self.args.int8:
|
637
637
|
fq = str(self.file).replace(self.file.suffix, f"_int8_openvino_model{os.sep}")
|
@@ -690,7 +690,7 @@ class Exporter:
|
|
690
690
|
f = str(self.file).replace(self.file.suffix, f"_paddle_model{os.sep}")
|
691
691
|
|
692
692
|
pytorch2paddle(module=self.model, save_dir=f, jit_type="trace", input_examples=[self.im]) # export
|
693
|
-
|
693
|
+
YAML.save(Path(f) / "metadata.yaml", self.metadata) # add metadata.yaml
|
694
694
|
return f, None
|
695
695
|
|
696
696
|
@try_export
|
@@ -783,7 +783,7 @@ class Exporter:
|
|
783
783
|
for f_debug in ("debug.bin", "debug.param", "debug2.bin", "debug2.param", *pnnx_files):
|
784
784
|
Path(f_debug).unlink(missing_ok=True)
|
785
785
|
|
786
|
-
|
786
|
+
YAML.save(f / "metadata.yaml", self.metadata) # add metadata.yaml
|
787
787
|
return str(f), None
|
788
788
|
|
789
789
|
@try_export
|
@@ -974,7 +974,7 @@ class Exporter:
|
|
974
974
|
output_signaturedefs=True, # fix error with Attention block group convolution
|
975
975
|
optimization_for_gpu_delegate=True,
|
976
976
|
)
|
977
|
-
|
977
|
+
YAML.save(f / "metadata.yaml", self.metadata) # add metadata.yaml
|
978
978
|
|
979
979
|
# Remove/rename TFLite models
|
980
980
|
if self.args.int8:
|
@@ -1087,7 +1087,7 @@ class Exporter:
|
|
1087
1087
|
LOGGER.warning(f"{prefix} your model may not work correctly with spaces in path '{f}'.")
|
1088
1088
|
|
1089
1089
|
# Add metadata
|
1090
|
-
|
1090
|
+
YAML.save(Path(f) / "metadata.yaml", self.metadata) # add metadata.yaml
|
1091
1091
|
return f, None
|
1092
1092
|
|
1093
1093
|
@try_export
|
@@ -1114,7 +1114,7 @@ class Exporter:
|
|
1114
1114
|
rknn.build(do_quantization=self.args.int8)
|
1115
1115
|
f = f.replace(".onnx", f"-{self.args.name}-int8.rknn" if self.args.int8 else f"-{self.args.name}-fp16.rknn")
|
1116
1116
|
rknn.export_rknn(f"{export_path / f}")
|
1117
|
-
|
1117
|
+
YAML.save(export_path / "metadata.yaml", self.metadata)
|
1118
1118
|
return export_path, None
|
1119
1119
|
|
1120
1120
|
@try_export
|
ultralytics/engine/model.py
CHANGED
@@ -10,7 +10,6 @@ from PIL import Image
|
|
10
10
|
|
11
11
|
from ultralytics.cfg import TASK2DATA, get_cfg, get_save_dir
|
12
12
|
from ultralytics.engine.results import Results
|
13
|
-
from ultralytics.hub import HUB_WEB_ROOT, HUBTrainingSession
|
14
13
|
from ultralytics.nn.tasks import attempt_load_one_weight, guess_model_task, yaml_model_load
|
15
14
|
from ultralytics.utils import (
|
16
15
|
ARGV,
|
@@ -19,9 +18,9 @@ from ultralytics.utils import (
|
|
19
18
|
LOGGER,
|
20
19
|
RANK,
|
21
20
|
SETTINGS,
|
21
|
+
YAML,
|
22
22
|
callbacks,
|
23
23
|
checks,
|
24
|
-
yaml_load,
|
25
24
|
)
|
26
25
|
|
27
26
|
|
@@ -126,6 +125,8 @@ class Model(torch.nn.Module):
|
|
126
125
|
|
127
126
|
# Check if Ultralytics HUB model from https://hub.ultralytics.com
|
128
127
|
if self.is_hub_model(model):
|
128
|
+
from ultralytics.hub import HUBTrainingSession
|
129
|
+
|
129
130
|
# Fetch model from HUB
|
130
131
|
checks.check_requirements("hub-sdk>=0.0.12")
|
131
132
|
session = HUBTrainingSession.create_session(model)
|
@@ -141,7 +142,7 @@ class Model(torch.nn.Module):
|
|
141
142
|
|
142
143
|
# Load or create new YOLO model
|
143
144
|
__import__("os").environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" # to avoid deterministic warnings
|
144
|
-
if
|
145
|
+
if str(model).endswith((".yaml", ".yml")):
|
145
146
|
self._new(model, task=task, verbose=verbose)
|
146
147
|
else:
|
147
148
|
self._load(model, task=task)
|
@@ -225,6 +226,8 @@ class Model(torch.nn.Module):
|
|
225
226
|
>>> Model.is_hub_model("yolo11n.pt")
|
226
227
|
False
|
227
228
|
"""
|
229
|
+
from ultralytics.hub import HUB_WEB_ROOT
|
230
|
+
|
228
231
|
return model.startswith(f"{HUB_WEB_ROOT}/models/")
|
229
232
|
|
230
233
|
def _new(self, cfg: str, task=None, model=None, verbose=False) -> None:
|
@@ -770,7 +773,7 @@ class Model(torch.nn.Module):
|
|
770
773
|
|
771
774
|
checks.check_pip_update_available()
|
772
775
|
|
773
|
-
overrides =
|
776
|
+
overrides = YAML.load(checks.check_yaml(kwargs["cfg"])) if kwargs.get("cfg") else self.overrides
|
774
777
|
custom = {
|
775
778
|
# NOTE: handle the case when 'cfg' includes 'data'.
|
776
779
|
"data": overrides.get("data") or DEFAULT_CFG_DICT["data"] or TASK2DATA[self.task],
|
ultralytics/engine/trainer.py
CHANGED
@@ -31,11 +31,11 @@ from ultralytics.utils import (
|
|
31
31
|
LOGGER,
|
32
32
|
RANK,
|
33
33
|
TQDM,
|
34
|
+
YAML,
|
34
35
|
callbacks,
|
35
36
|
clean_url,
|
36
37
|
colorstr,
|
37
38
|
emojis,
|
38
|
-
yaml_save,
|
39
39
|
)
|
40
40
|
from ultralytics.utils.autobatch import check_train_batch_size
|
41
41
|
from ultralytics.utils.checks import check_amp, check_file, check_imgsz, check_model_file_from_stem, print_args
|
@@ -117,7 +117,7 @@ class BaseTrainer:
|
|
117
117
|
if RANK in {-1, 0}:
|
118
118
|
self.wdir.mkdir(parents=True, exist_ok=True) # make dir
|
119
119
|
self.args.save_dir = str(self.save_dir)
|
120
|
-
|
120
|
+
YAML.save(self.save_dir / "args.yaml", vars(self.args)) # save run args
|
121
121
|
self.last, self.best = self.wdir / "last.pt", self.wdir / "best.pt" # checkpoint paths
|
122
122
|
self.save_period = self.args.save_period
|
123
123
|
|
ultralytics/engine/tuner.py
CHANGED
@@ -23,7 +23,7 @@ import numpy as np
|
|
23
23
|
import torch
|
24
24
|
|
25
25
|
from ultralytics.cfg import get_cfg, get_save_dir
|
26
|
-
from ultralytics.utils import DEFAULT_CFG, LOGGER, callbacks, colorstr, remove_colorstr
|
26
|
+
from ultralytics.utils import DEFAULT_CFG, LOGGER, YAML, callbacks, colorstr, remove_colorstr
|
27
27
|
from ultralytics.utils.plotting import plot_tune_results
|
28
28
|
|
29
29
|
|
@@ -235,9 +235,9 @@ class Tuner:
|
|
235
235
|
)
|
236
236
|
LOGGER.info("\n" + header)
|
237
237
|
data = {k: float(x[best_idx, i + 1]) for i, k in enumerate(self.space.keys())}
|
238
|
-
|
238
|
+
YAML.save(
|
239
239
|
self.tune_dir / "best_hyperparameters.yaml",
|
240
240
|
data=data,
|
241
241
|
header=remove_colorstr(header.replace(self.prefix, "# ")) + "\n",
|
242
242
|
)
|
243
|
-
|
243
|
+
YAML.print(self.tune_dir / "best_hyperparameters.yaml")
|
ultralytics/hub/session.py
CHANGED
@@ -201,7 +201,7 @@ class HUBTrainingSession:
|
|
201
201
|
HUBModelError: If the identifier format is not recognized.
|
202
202
|
"""
|
203
203
|
api_key, model_id, filename = None, None, None
|
204
|
-
if
|
204
|
+
if str(identifier).endswith((".pt", ".yaml")):
|
205
205
|
filename = identifier
|
206
206
|
elif identifier.startswith(f"{HUB_WEB_ROOT}/models/"):
|
207
207
|
parsed_url = urlparse(identifier)
|
ultralytics/models/sam/model.py
CHANGED
@@ -19,7 +19,6 @@ from pathlib import Path
|
|
19
19
|
from ultralytics.engine.model import Model
|
20
20
|
from ultralytics.utils.torch_utils import model_info
|
21
21
|
|
22
|
-
from .build import build_sam
|
23
22
|
from .predict import Predictor, SAM2Predictor
|
24
23
|
|
25
24
|
|
@@ -78,6 +77,8 @@ class SAM(Model):
|
|
78
77
|
>>> sam = SAM("sam_b.pt")
|
79
78
|
>>> sam._load("path/to/custom_weights.pt")
|
80
79
|
"""
|
80
|
+
from .build import build_sam # slow import
|
81
|
+
|
81
82
|
self.model = build_sam(weights)
|
82
83
|
|
83
84
|
def predict(self, source, stream=False, bboxes=None, points=None, labels=None, **kwargs):
|
@@ -15,7 +15,6 @@ from typing import Tuple
|
|
15
15
|
import torch
|
16
16
|
import torch.nn as nn
|
17
17
|
import torch.nn.functional as F
|
18
|
-
import torch.utils.checkpoint as checkpoint
|
19
18
|
|
20
19
|
from ultralytics.nn.modules import LayerNorm2d
|
21
20
|
from ultralytics.utils.instance import to_2tuple
|
@@ -308,7 +307,7 @@ class ConvLayer(nn.Module):
|
|
308
307
|
def forward(self, x):
|
309
308
|
"""Processes input through convolutional layers, applying MBConv blocks and optional downsampling."""
|
310
309
|
for blk in self.blocks:
|
311
|
-
x =
|
310
|
+
x = torch.utils.checkpoint(blk, x) if self.use_checkpoint else blk(x) # warn: checkpoint is slow import
|
312
311
|
return x if self.downsample is None else self.downsample(x)
|
313
312
|
|
314
313
|
|
@@ -751,7 +750,7 @@ class BasicLayer(nn.Module):
|
|
751
750
|
def forward(self, x):
|
752
751
|
"""Processes input through TinyViT blocks and optional downsampling."""
|
753
752
|
for blk in self.blocks:
|
754
|
-
x =
|
753
|
+
x = torch.utils.checkpoint(blk, x) if self.use_checkpoint else blk(x) # warn: checkpoint is slow import
|
755
754
|
return x if self.downsample is None else self.downsample(x)
|
756
755
|
|
757
756
|
def extra_repr(self) -> str:
|
@@ -31,7 +31,6 @@ from .amg import (
|
|
31
31
|
uncrop_boxes_xyxy,
|
32
32
|
uncrop_masks,
|
33
33
|
)
|
34
|
-
from .build import build_sam
|
35
34
|
|
36
35
|
|
37
36
|
class Predictor(BasePredictor):
|
@@ -439,6 +438,8 @@ class Predictor(BasePredictor):
|
|
439
438
|
|
440
439
|
def get_model(self):
|
441
440
|
"""Retrieves or builds the Segment Anything Model (SAM) for image segmentation tasks."""
|
441
|
+
from .build import build_sam # slow import
|
442
|
+
|
442
443
|
return build_sam(self.args.model)
|
443
444
|
|
444
445
|
def postprocess(self, preds, img, orig_imgs):
|
@@ -658,6 +659,8 @@ class SAM2Predictor(Predictor):
|
|
658
659
|
|
659
660
|
def get_model(self):
|
660
661
|
"""Retrieves and initializes the Segment Anything Model 2 (SAM2) for image segmentation tasks."""
|
662
|
+
from .build import build_sam # slow import
|
663
|
+
|
661
664
|
return build_sam(self.args.model)
|
662
665
|
|
663
666
|
def prompt_inference(
|
ultralytics/models/yolo/model.py
CHANGED
@@ -15,7 +15,7 @@ from ultralytics.nn.tasks import (
|
|
15
15
|
YOLOEModel,
|
16
16
|
YOLOESegModel,
|
17
17
|
)
|
18
|
-
from ultralytics.utils import ROOT,
|
18
|
+
from ultralytics.utils import ROOT, YAML
|
19
19
|
|
20
20
|
|
21
21
|
class YOLO(Model):
|
@@ -107,7 +107,7 @@ class YOLOWorld(Model):
|
|
107
107
|
|
108
108
|
# Assign default COCO class names when there are no custom names
|
109
109
|
if not hasattr(self.model, "names"):
|
110
|
-
self.model.names =
|
110
|
+
self.model.names = YAML.load(ROOT / "cfg/datasets/coco8.yaml").get("names")
|
111
111
|
|
112
112
|
@property
|
113
113
|
def task_map(self):
|
@@ -156,7 +156,7 @@ class YOLOE(Model):
|
|
156
156
|
|
157
157
|
# Assign default COCO class names when there are no custom names
|
158
158
|
if not hasattr(self.model, "names"):
|
159
|
-
self.model.names =
|
159
|
+
self.model.names = YAML.load(ROOT / "cfg/datasets/coco8.yaml").get("names")
|
160
160
|
|
161
161
|
@property
|
162
162
|
def task_map(self):
|
ultralytics/nn/autobackend.py
CHANGED
@@ -14,7 +14,7 @@ import torch
|
|
14
14
|
import torch.nn as nn
|
15
15
|
from PIL import Image
|
16
16
|
|
17
|
-
from ultralytics.utils import ARM64, IS_JETSON, LINUX, LOGGER, PYTHON_VERSION, ROOT,
|
17
|
+
from ultralytics.utils import ARM64, IS_JETSON, LINUX, LOGGER, PYTHON_VERSION, ROOT, YAML
|
18
18
|
from ultralytics.utils.checks import check_requirements, check_suffix, check_version, check_yaml, is_rockchip
|
19
19
|
from ultralytics.utils.downloads import attempt_download_asset, is_url
|
20
20
|
|
@@ -33,7 +33,7 @@ def check_class_names(names):
|
|
33
33
|
f"{min(names.keys())}-{max(names.keys())} defined in your dataset YAML."
|
34
34
|
)
|
35
35
|
if isinstance(names[0], str) and names[0].startswith("n0"): # imagenet class codes, i.e. 'n01440764'
|
36
|
-
names_map =
|
36
|
+
names_map = YAML.load(ROOT / "cfg/datasets/ImageNet.yaml")["map"] # human-readable names
|
37
37
|
names = {k: names_map[v] for k, v in names.items()}
|
38
38
|
return names
|
39
39
|
|
@@ -42,7 +42,7 @@ def default_class_names(data=None):
|
|
42
42
|
"""Applies default class names to an input YAML file or returns numerical class names."""
|
43
43
|
if data:
|
44
44
|
try:
|
45
|
-
return
|
45
|
+
return YAML.load(check_yaml(data))["names"]
|
46
46
|
except Exception:
|
47
47
|
pass
|
48
48
|
return {i: f"class{i}" for i in range(999)} # return default if above errors
|
@@ -536,7 +536,7 @@ class AutoBackend(nn.Module):
|
|
536
536
|
|
537
537
|
# Load external metadata YAML
|
538
538
|
if isinstance(metadata, (str, Path)) and Path(metadata).exists():
|
539
|
-
metadata =
|
539
|
+
metadata = YAML.load(metadata)
|
540
540
|
if metadata and isinstance(metadata, dict):
|
541
541
|
for k, v in metadata.items():
|
542
542
|
if k in {"stride", "batch", "channels"}:
|
ultralytics/nn/tasks.py
CHANGED
@@ -69,7 +69,7 @@ from ultralytics.nn.modules import (
|
|
69
69
|
YOLOESegment,
|
70
70
|
v10Detect,
|
71
71
|
)
|
72
|
-
from ultralytics.utils import DEFAULT_CFG_DICT, DEFAULT_CFG_KEYS, LOGGER, colorstr, emojis
|
72
|
+
from ultralytics.utils import DEFAULT_CFG_DICT, DEFAULT_CFG_KEYS, LOGGER, YAML, colorstr, emojis
|
73
73
|
from ultralytics.utils.checks import check_requirements, check_suffix, check_yaml
|
74
74
|
from ultralytics.utils.loss import (
|
75
75
|
E2EDetectLoss,
|
@@ -92,11 +92,6 @@ from ultralytics.utils.torch_utils import (
|
|
92
92
|
time_sync,
|
93
93
|
)
|
94
94
|
|
95
|
-
try:
|
96
|
-
import thop
|
97
|
-
except ImportError:
|
98
|
-
thop = None # conda support without 'ultralytics-thop' installed
|
99
|
-
|
100
95
|
|
101
96
|
class BaseModel(torch.nn.Module):
|
102
97
|
"""The BaseModel class serves as a base class for all the models in the Ultralytics YOLO family."""
|
@@ -183,6 +178,11 @@ class BaseModel(torch.nn.Module):
|
|
183
178
|
x (torch.Tensor): The input data to the layer.
|
184
179
|
dt (list): A list to store the computation time of the layer.
|
185
180
|
"""
|
181
|
+
try:
|
182
|
+
import thop
|
183
|
+
except ImportError:
|
184
|
+
thop = None # conda support without 'ultralytics-thop' installed
|
185
|
+
|
186
186
|
c = m == self.model[-1] and isinstance(x, list) # is final layer list, copy input as inplace fix
|
187
187
|
flops = thop.profile(m, inputs=[x.copy() if c else x], verbose=False)[0] / 1e9 * 2 if thop else 0 # GFLOPs
|
188
188
|
t = time_sync()
|
@@ -1523,7 +1523,7 @@ def yaml_model_load(path):
|
|
1523
1523
|
|
1524
1524
|
unified_path = re.sub(r"(\d+)([nslmx])(.+)?$", r"\1\3", str(path)) # i.e. yolov8x.yaml -> yolov8.yaml
|
1525
1525
|
yaml_file = check_yaml(unified_path, hard=False) or check_yaml(path)
|
1526
|
-
d =
|
1526
|
+
d = YAML.load(yaml_file) # model dict
|
1527
1527
|
d["scale"] = guess_model_scale(path)
|
1528
1528
|
d["yaml_file"] = str(path)
|
1529
1529
|
return d
|