dgenerate-ultralytics-headless 8.3.195__py3-none-any.whl → 8.3.197__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.195.dist-info → dgenerate_ultralytics_headless-8.3.197.dist-info}/METADATA +1 -1
- {dgenerate_ultralytics_headless-8.3.195.dist-info → dgenerate_ultralytics_headless-8.3.197.dist-info}/RECORD +37 -36
- ultralytics/__init__.py +1 -1
- ultralytics/cfg/__init__.py +1 -0
- ultralytics/cfg/datasets/construction-ppe.yaml +32 -0
- ultralytics/cfg/default.yaml +1 -0
- ultralytics/data/augment.py +1 -1
- ultralytics/data/build.py +5 -1
- ultralytics/engine/exporter.py +20 -31
- ultralytics/engine/model.py +1 -2
- ultralytics/engine/predictor.py +3 -1
- ultralytics/engine/trainer.py +17 -8
- ultralytics/engine/validator.py +6 -2
- ultralytics/models/yolo/classify/train.py +1 -11
- ultralytics/models/yolo/detect/train.py +27 -6
- ultralytics/models/yolo/detect/val.py +6 -5
- ultralytics/models/yolo/obb/train.py +0 -9
- ultralytics/models/yolo/pose/train.py +0 -9
- ultralytics/models/yolo/pose/val.py +1 -1
- ultralytics/models/yolo/segment/train.py +0 -9
- ultralytics/models/yolo/segment/val.py +5 -5
- ultralytics/models/yolo/world/train.py +4 -4
- ultralytics/models/yolo/world/train_world.py +2 -2
- ultralytics/models/yolo/yoloe/train.py +3 -12
- ultralytics/models/yolo/yoloe/val.py +0 -7
- ultralytics/nn/tasks.py +4 -2
- ultralytics/utils/__init__.py +30 -19
- ultralytics/utils/callbacks/tensorboard.py +2 -2
- ultralytics/utils/checks.py +2 -0
- ultralytics/utils/loss.py +12 -7
- ultralytics/utils/nms.py +3 -1
- ultralytics/utils/plotting.py +1 -0
- ultralytics/utils/torch_utils.py +89 -9
- {dgenerate_ultralytics_headless-8.3.195.dist-info → dgenerate_ultralytics_headless-8.3.197.dist-info}/WHEEL +0 -0
- {dgenerate_ultralytics_headless-8.3.195.dist-info → dgenerate_ultralytics_headless-8.3.197.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.195.dist-info → dgenerate_ultralytics_headless-8.3.197.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.195.dist-info → dgenerate_ultralytics_headless-8.3.197.dist-info}/top_level.txt +0 -0
@@ -8,16 +8,17 @@ from copy import copy
|
|
8
8
|
from typing import Any
|
9
9
|
|
10
10
|
import numpy as np
|
11
|
+
import torch
|
11
12
|
import torch.nn as nn
|
12
13
|
|
13
14
|
from ultralytics.data import build_dataloader, build_yolo_dataset
|
14
15
|
from ultralytics.engine.trainer import BaseTrainer
|
15
16
|
from ultralytics.models import yolo
|
16
17
|
from ultralytics.nn.tasks import DetectionModel
|
17
|
-
from ultralytics.utils import LOGGER, RANK
|
18
|
+
from ultralytics.utils import DEFAULT_CFG, LOGGER, RANK
|
18
19
|
from ultralytics.utils.patches import override_configs
|
19
20
|
from ultralytics.utils.plotting import plot_images, plot_labels, plot_results
|
20
|
-
from ultralytics.utils.torch_utils import
|
21
|
+
from ultralytics.utils.torch_utils import torch_distributed_zero_first, unwrap_model
|
21
22
|
|
22
23
|
|
23
24
|
class DetectionTrainer(BaseTrainer):
|
@@ -53,6 +54,17 @@ class DetectionTrainer(BaseTrainer):
|
|
53
54
|
>>> trainer.train()
|
54
55
|
"""
|
55
56
|
|
57
|
+
def __init__(self, cfg=DEFAULT_CFG, overrides: dict[str, Any] | None = None, _callbacks=None):
|
58
|
+
"""
|
59
|
+
Initialize a DetectionTrainer object for training YOLO object detection model training.
|
60
|
+
|
61
|
+
Args:
|
62
|
+
cfg (dict, optional): Default configuration dictionary containing training parameters.
|
63
|
+
overrides (dict, optional): Dictionary of parameter overrides for the default configuration.
|
64
|
+
_callbacks (list, optional): List of callback functions to be executed during training.
|
65
|
+
"""
|
66
|
+
super().__init__(cfg, overrides, _callbacks)
|
67
|
+
|
56
68
|
def build_dataset(self, img_path: str, mode: str = "train", batch: int | None = None):
|
57
69
|
"""
|
58
70
|
Build YOLO Dataset for training or validation.
|
@@ -65,7 +77,7 @@ class DetectionTrainer(BaseTrainer):
|
|
65
77
|
Returns:
|
66
78
|
(Dataset): YOLO dataset object configured for the specified mode.
|
67
79
|
"""
|
68
|
-
gs = max(int(
|
80
|
+
gs = max(int(unwrap_model(self.model).stride.max() if self.model else 0), 32)
|
69
81
|
return build_yolo_dataset(self.args, img_path, batch, self.data, mode=mode, rect=mode == "val", stride=gs)
|
70
82
|
|
71
83
|
def get_dataloader(self, dataset_path: str, batch_size: int = 16, rank: int = 0, mode: str = "train"):
|
@@ -88,8 +100,14 @@ class DetectionTrainer(BaseTrainer):
|
|
88
100
|
if getattr(dataset, "rect", False) and shuffle:
|
89
101
|
LOGGER.warning("'rect=True' is incompatible with DataLoader shuffle, setting shuffle=False")
|
90
102
|
shuffle = False
|
91
|
-
|
92
|
-
|
103
|
+
return build_dataloader(
|
104
|
+
dataset,
|
105
|
+
batch=batch_size,
|
106
|
+
workers=self.args.workers if mode == "train" else self.args.workers * 2,
|
107
|
+
shuffle=shuffle,
|
108
|
+
rank=rank,
|
109
|
+
drop_last=self.args.compile and mode == "train",
|
110
|
+
)
|
93
111
|
|
94
112
|
def preprocess_batch(self, batch: dict) -> dict:
|
95
113
|
"""
|
@@ -101,7 +119,10 @@ class DetectionTrainer(BaseTrainer):
|
|
101
119
|
Returns:
|
102
120
|
(dict): Preprocessed batch with normalized images.
|
103
121
|
"""
|
104
|
-
|
122
|
+
for k, v in batch.items():
|
123
|
+
if isinstance(v, torch.Tensor):
|
124
|
+
batch[k] = v.to(self.device, non_blocking=True)
|
125
|
+
batch["img"] = batch["img"].float() / 255
|
105
126
|
if self.args.multi_scale:
|
106
127
|
imgs = batch["img"]
|
107
128
|
sz = (
|
@@ -71,11 +71,10 @@ class DetectionValidator(BaseValidator):
|
|
71
71
|
Returns:
|
72
72
|
(dict[str, Any]): Preprocessed batch.
|
73
73
|
"""
|
74
|
-
|
74
|
+
for k, v in batch.items():
|
75
|
+
if isinstance(v, torch.Tensor):
|
76
|
+
batch[k] = v.to(self.device, non_blocking=True)
|
75
77
|
batch["img"] = (batch["img"].half() if self.args.half else batch["img"].float()) / 255
|
76
|
-
for k in {"batch_idx", "cls", "bboxes"}:
|
77
|
-
batch[k] = batch[k].to(self.device, non_blocking=True)
|
78
|
-
|
79
78
|
return batch
|
80
79
|
|
81
80
|
def init_metrics(self, model: torch.nn.Module) -> None:
|
@@ -300,7 +299,9 @@ class DetectionValidator(BaseValidator):
|
|
300
299
|
(torch.utils.data.DataLoader): Dataloader for validation.
|
301
300
|
"""
|
302
301
|
dataset = self.build_dataset(dataset_path, batch=batch_size, mode="val")
|
303
|
-
return build_dataloader(
|
302
|
+
return build_dataloader(
|
303
|
+
dataset, batch_size, self.args.workers, shuffle=False, rank=-1, drop_last=self.args.compile
|
304
|
+
)
|
304
305
|
|
305
306
|
def plot_val_samples(self, batch: dict[str, Any], ni: int) -> None:
|
306
307
|
"""
|
@@ -37,21 +37,12 @@ class OBBTrainer(yolo.detect.DetectionTrainer):
|
|
37
37
|
"""
|
38
38
|
Initialize an OBBTrainer object for training Oriented Bounding Box (OBB) models.
|
39
39
|
|
40
|
-
This trainer extends the DetectionTrainer class to specialize in training models that detect oriented
|
41
|
-
bounding boxes. It automatically sets the task to 'obb' in the configuration.
|
42
|
-
|
43
40
|
Args:
|
44
41
|
cfg (dict, optional): Configuration dictionary for the trainer. Contains training parameters and
|
45
42
|
model configuration.
|
46
43
|
overrides (dict, optional): Dictionary of parameter overrides for the configuration. Any values here
|
47
44
|
will take precedence over those in cfg.
|
48
45
|
_callbacks (list[Any], optional): List of callback functions to be invoked during training.
|
49
|
-
|
50
|
-
Examples:
|
51
|
-
>>> from ultralytics.models.yolo.obb import OBBTrainer
|
52
|
-
>>> args = dict(model="yolo11n-obb.pt", data="dota8.yaml", epochs=3)
|
53
|
-
>>> trainer = OBBTrainer(overrides=args)
|
54
|
-
>>> trainer.train()
|
55
46
|
"""
|
56
47
|
if overrides is None:
|
57
48
|
overrides = {}
|
@@ -44,9 +44,6 @@ class PoseTrainer(yolo.detect.DetectionTrainer):
|
|
44
44
|
"""
|
45
45
|
Initialize a PoseTrainer object for training YOLO pose estimation models.
|
46
46
|
|
47
|
-
This initializes a trainer specialized for pose estimation tasks, setting the task to 'pose' and
|
48
|
-
handling specific configurations needed for keypoint detection models.
|
49
|
-
|
50
47
|
Args:
|
51
48
|
cfg (dict, optional): Default configuration dictionary containing training parameters.
|
52
49
|
overrides (dict, optional): Dictionary of parameter overrides for the default configuration.
|
@@ -55,12 +52,6 @@ class PoseTrainer(yolo.detect.DetectionTrainer):
|
|
55
52
|
Notes:
|
56
53
|
This trainer will automatically set the task to 'pose' regardless of what is provided in overrides.
|
57
54
|
A warning is issued when using Apple MPS device due to known bugs with pose models.
|
58
|
-
|
59
|
-
Examples:
|
60
|
-
>>> from ultralytics.models.yolo.pose import PoseTrainer
|
61
|
-
>>> args = dict(model="yolo11n-pose.pt", data="coco8-pose.yaml", epochs=3)
|
62
|
-
>>> trainer = PoseTrainer(overrides=args)
|
63
|
-
>>> trainer.train()
|
64
55
|
"""
|
65
56
|
if overrides is None:
|
66
57
|
overrides = {}
|
@@ -86,7 +86,7 @@ class PoseValidator(DetectionValidator):
|
|
86
86
|
def preprocess(self, batch: dict[str, Any]) -> dict[str, Any]:
|
87
87
|
"""Preprocess batch by converting keypoints data to float and moving it to the device."""
|
88
88
|
batch = super().preprocess(batch)
|
89
|
-
batch["keypoints"] = batch["keypoints"].
|
89
|
+
batch["keypoints"] = batch["keypoints"].float()
|
90
90
|
return batch
|
91
91
|
|
92
92
|
def get_desc(self) -> str:
|
@@ -32,19 +32,10 @@ class SegmentationTrainer(yolo.detect.DetectionTrainer):
|
|
32
32
|
"""
|
33
33
|
Initialize a SegmentationTrainer object.
|
34
34
|
|
35
|
-
This initializes a trainer for segmentation tasks, extending the detection trainer with segmentation-specific
|
36
|
-
functionality. It sets the task to 'segment' and prepares the trainer for training segmentation models.
|
37
|
-
|
38
35
|
Args:
|
39
36
|
cfg (dict): Configuration dictionary with default training settings.
|
40
37
|
overrides (dict, optional): Dictionary of parameter overrides for the default configuration.
|
41
38
|
_callbacks (list, optional): List of callback functions to be executed during training.
|
42
|
-
|
43
|
-
Examples:
|
44
|
-
>>> from ultralytics.models.yolo.segment import SegmentationTrainer
|
45
|
-
>>> args = dict(model="yolo11n-seg.pt", data="coco8-seg.yaml", epochs=3)
|
46
|
-
>>> trainer = SegmentationTrainer(overrides=args)
|
47
|
-
>>> trainer.train()
|
48
39
|
"""
|
49
40
|
if overrides is None:
|
50
41
|
overrides = {}
|
@@ -63,7 +63,7 @@ class SegmentationValidator(DetectionValidator):
|
|
63
63
|
(dict[str, Any]): Preprocessed batch.
|
64
64
|
"""
|
65
65
|
batch = super().preprocess(batch)
|
66
|
-
batch["masks"] = batch["masks"].
|
66
|
+
batch["masks"] = batch["masks"].float()
|
67
67
|
return batch
|
68
68
|
|
69
69
|
def init_metrics(self, model: torch.nn.Module) -> None:
|
@@ -187,10 +187,10 @@ class SegmentationValidator(DetectionValidator):
|
|
187
187
|
"""
|
188
188
|
for p in preds:
|
189
189
|
masks = p["masks"]
|
190
|
-
if masks.shape[0] >
|
191
|
-
LOGGER.warning("Limiting validation plots to
|
192
|
-
p["masks"] = torch.as_tensor(masks[:
|
193
|
-
super().plot_predictions(batch, preds, ni, max_det=
|
190
|
+
if masks.shape[0] > self.args.max_det:
|
191
|
+
LOGGER.warning(f"Limiting validation plots to 'max_det={self.args.max_det}' items.")
|
192
|
+
p["masks"] = torch.as_tensor(masks[: self.args.max_det], dtype=torch.uint8).cpu()
|
193
|
+
super().plot_predictions(batch, preds, ni, max_det=self.args.max_det) # plot bboxes
|
194
194
|
|
195
195
|
def save_one_txt(self, predn: torch.Tensor, save_conf: bool, shape: tuple[int, int], file: Path) -> None:
|
196
196
|
"""
|
@@ -12,7 +12,7 @@ from ultralytics.data import build_yolo_dataset
|
|
12
12
|
from ultralytics.models.yolo.detect import DetectionTrainer
|
13
13
|
from ultralytics.nn.tasks import WorldModel
|
14
14
|
from ultralytics.utils import DEFAULT_CFG, LOGGER, RANK
|
15
|
-
from ultralytics.utils.torch_utils import
|
15
|
+
from ultralytics.utils.torch_utils import unwrap_model
|
16
16
|
|
17
17
|
|
18
18
|
def on_pretrain_routine_end(trainer) -> None:
|
@@ -20,7 +20,7 @@ def on_pretrain_routine_end(trainer) -> None:
|
|
20
20
|
if RANK in {-1, 0}:
|
21
21
|
# Set class names for evaluation
|
22
22
|
names = [name.split("/", 1)[0] for name in list(trainer.test_loader.dataset.data["names"].values())]
|
23
|
-
|
23
|
+
unwrap_model(trainer.ema.ema).set_classes(names, cache_clip_model=False)
|
24
24
|
|
25
25
|
|
26
26
|
class WorldTrainer(DetectionTrainer):
|
@@ -105,7 +105,7 @@ class WorldTrainer(DetectionTrainer):
|
|
105
105
|
Returns:
|
106
106
|
(Any): YOLO dataset configured for training or validation.
|
107
107
|
"""
|
108
|
-
gs = max(int(
|
108
|
+
gs = max(int(unwrap_model(self.model).stride.max() if self.model else 0), 32)
|
109
109
|
dataset = build_yolo_dataset(
|
110
110
|
self.args, img_path, batch, self.data, mode=mode, rect=mode == "val", stride=gs, multi_modal=mode == "train"
|
111
111
|
)
|
@@ -160,7 +160,7 @@ class WorldTrainer(DetectionTrainer):
|
|
160
160
|
return txt_map
|
161
161
|
LOGGER.info(f"Caching text embeddings to '{cache_path}'")
|
162
162
|
assert self.model is not None
|
163
|
-
txt_feats =
|
163
|
+
txt_feats = unwrap_model(self.model).get_text_pe(texts, batch, cache_clip_model=False)
|
164
164
|
txt_map = dict(zip(texts, txt_feats.squeeze(0)))
|
165
165
|
torch.save(txt_map, cache_path)
|
166
166
|
return txt_map
|
@@ -6,7 +6,7 @@ from ultralytics.data import YOLOConcatDataset, build_grounding, build_yolo_data
|
|
6
6
|
from ultralytics.data.utils import check_det_dataset
|
7
7
|
from ultralytics.models.yolo.world import WorldTrainer
|
8
8
|
from ultralytics.utils import DATASETS_DIR, DEFAULT_CFG, LOGGER
|
9
|
-
from ultralytics.utils.torch_utils import
|
9
|
+
from ultralytics.utils.torch_utils import unwrap_model
|
10
10
|
|
11
11
|
|
12
12
|
class WorldTrainerFromScratch(WorldTrainer):
|
@@ -101,7 +101,7 @@ class WorldTrainerFromScratch(WorldTrainer):
|
|
101
101
|
Returns:
|
102
102
|
(YOLOConcatDataset | Dataset): The constructed dataset for training or validation.
|
103
103
|
"""
|
104
|
-
gs = max(int(
|
104
|
+
gs = max(int(unwrap_model(self.model).stride.max() if self.model else 0), 32)
|
105
105
|
if mode != "train":
|
106
106
|
return build_yolo_dataset(self.args, img_path, batch, self.data, mode=mode, rect=False, stride=gs)
|
107
107
|
datasets = [
|
@@ -13,7 +13,7 @@ from ultralytics.data.augment import LoadVisualPrompt
|
|
13
13
|
from ultralytics.models.yolo.detect import DetectionTrainer, DetectionValidator
|
14
14
|
from ultralytics.nn.tasks import YOLOEModel
|
15
15
|
from ultralytics.utils import DEFAULT_CFG, LOGGER, RANK
|
16
|
-
from ultralytics.utils.torch_utils import
|
16
|
+
from ultralytics.utils.torch_utils import unwrap_model
|
17
17
|
|
18
18
|
from ..world.train_world import WorldTrainerFromScratch
|
19
19
|
from .val import YOLOEDetectValidator
|
@@ -39,9 +39,6 @@ class YOLOETrainer(DetectionTrainer):
|
|
39
39
|
"""
|
40
40
|
Initialize the YOLOE Trainer with specified configurations.
|
41
41
|
|
42
|
-
This method sets up the YOLOE trainer with the provided configuration and overrides, initializing
|
43
|
-
the training environment, model, and callbacks for YOLOE object detection training.
|
44
|
-
|
45
42
|
Args:
|
46
43
|
cfg (dict): Configuration dictionary with default training settings from DEFAULT_CFG.
|
47
44
|
overrides (dict, optional): Dictionary of parameter overrides for the default configuration.
|
@@ -102,7 +99,7 @@ class YOLOETrainer(DetectionTrainer):
|
|
102
99
|
Returns:
|
103
100
|
(Dataset): YOLO dataset configured for training or validation.
|
104
101
|
"""
|
105
|
-
gs = max(int(
|
102
|
+
gs = max(int(unwrap_model(self.model).stride.max() if self.model else 0), 32)
|
106
103
|
return build_yolo_dataset(
|
107
104
|
self.args, img_path, batch, self.data, mode=mode, rect=mode == "val", stride=gs, multi_modal=mode == "train"
|
108
105
|
)
|
@@ -223,7 +220,7 @@ class YOLOETrainerFromScratch(YOLOETrainer, WorldTrainerFromScratch):
|
|
223
220
|
return txt_map
|
224
221
|
LOGGER.info(f"Caching text embeddings to '{cache_path}'")
|
225
222
|
assert self.model is not None
|
226
|
-
txt_feats =
|
223
|
+
txt_feats = unwrap_model(self.model).get_text_pe(texts, batch, without_reprta=True, cache_clip_model=False)
|
227
224
|
txt_map = dict(zip(texts, txt_feats.squeeze(0)))
|
228
225
|
torch.save(txt_map, cache_path)
|
229
226
|
return txt_map
|
@@ -313,9 +310,3 @@ class YOLOEVPTrainer(YOLOETrainerFromScratch):
|
|
313
310
|
d.transforms.append(LoadVisualPrompt())
|
314
311
|
else:
|
315
312
|
self.train_loader.dataset.transforms.append(LoadVisualPrompt())
|
316
|
-
|
317
|
-
def preprocess_batch(self, batch):
|
318
|
-
"""Preprocess a batch of images for YOLOE training, moving visual prompts to the appropriate device."""
|
319
|
-
batch = super().preprocess_batch(batch)
|
320
|
-
batch["visuals"] = batch["visuals"].to(self.device, non_blocking=True)
|
321
|
-
return batch
|
@@ -98,13 +98,6 @@ class YOLOEDetectValidator(DetectionValidator):
|
|
98
98
|
visual_pe[cls_visual_num == 0] = 0
|
99
99
|
return visual_pe.unsqueeze(0)
|
100
100
|
|
101
|
-
def preprocess(self, batch: dict[str, Any]) -> dict[str, Any]:
|
102
|
-
"""Preprocess batch data, ensuring visuals are on the same device as images."""
|
103
|
-
batch = super().preprocess(batch)
|
104
|
-
if "visuals" in batch:
|
105
|
-
batch["visuals"] = batch["visuals"].to(batch["img"].device, non_blocking=True)
|
106
|
-
return batch
|
107
|
-
|
108
101
|
def get_vpe_dataloader(self, data: dict[str, Any]) -> torch.utils.data.DataLoader:
|
109
102
|
"""
|
110
103
|
Create a dataloader for LVIS training visual prompt samples.
|
ultralytics/nn/tasks.py
CHANGED
@@ -334,7 +334,8 @@ class BaseModel(torch.nn.Module):
|
|
334
334
|
if getattr(self, "criterion", None) is None:
|
335
335
|
self.criterion = self.init_criterion()
|
336
336
|
|
337
|
-
|
337
|
+
if preds is None:
|
338
|
+
preds = self.forward(batch["img"])
|
338
339
|
return self.criterion(preds, batch)
|
339
340
|
|
340
341
|
def init_criterion(self):
|
@@ -775,7 +776,8 @@ class RTDETRDetectionModel(DetectionModel):
|
|
775
776
|
"gt_groups": gt_groups,
|
776
777
|
}
|
777
778
|
|
778
|
-
|
779
|
+
if preds is None:
|
780
|
+
preds = self.predict(img, batch=targets)
|
779
781
|
dec_bboxes, dec_scores, enc_bboxes, enc_scores, dn_meta = preds if self.training else preds[1]
|
780
782
|
if dn_meta is None:
|
781
783
|
dn_bboxes, dn_scores = None, None
|
ultralytics/utils/__init__.py
CHANGED
@@ -857,7 +857,7 @@ def get_ubuntu_version():
|
|
857
857
|
|
858
858
|
def get_user_config_dir(sub_dir="Ultralytics"):
|
859
859
|
"""
|
860
|
-
Return
|
860
|
+
Return a writable config dir, preferring YOLO_CONFIG_DIR and being OS-aware.
|
861
861
|
|
862
862
|
Args:
|
863
863
|
sub_dir (str): The name of the subdirectory to create.
|
@@ -865,27 +865,38 @@ def get_user_config_dir(sub_dir="Ultralytics"):
|
|
865
865
|
Returns:
|
866
866
|
(Path): The path to the user config directory.
|
867
867
|
"""
|
868
|
-
if
|
869
|
-
|
870
|
-
elif MACOS: # macOS
|
871
|
-
path = Path.home() / "Library" / "Application Support" / sub_dir
|
868
|
+
if env_dir := os.getenv("YOLO_CONFIG_DIR"):
|
869
|
+
p = Path(env_dir).expanduser() / sub_dir
|
872
870
|
elif LINUX:
|
873
|
-
|
871
|
+
p = Path(os.getenv("XDG_CONFIG_HOME", Path.home() / ".config")) / sub_dir
|
872
|
+
elif WINDOWS:
|
873
|
+
p = Path.home() / "AppData" / "Roaming" / sub_dir
|
874
|
+
elif MACOS:
|
875
|
+
p = Path.home() / "Library" / "Application Support" / sub_dir
|
874
876
|
else:
|
875
877
|
raise ValueError(f"Unsupported operating system: {platform.system()}")
|
876
878
|
|
877
|
-
#
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
879
|
+
if p.exists(): # already created → trust it
|
880
|
+
return p
|
881
|
+
if is_dir_writeable(p.parent): # create if possible
|
882
|
+
p.mkdir(parents=True, exist_ok=True)
|
883
|
+
return p
|
884
|
+
|
885
|
+
# Fallbacks for Docker, GCP/AWS functions where only /tmp is writeable
|
886
|
+
for alt in [Path("/tmp") / sub_dir, Path.cwd() / sub_dir]:
|
887
|
+
if alt.exists():
|
888
|
+
return alt
|
889
|
+
if is_dir_writeable(alt.parent):
|
890
|
+
alt.mkdir(parents=True, exist_ok=True)
|
891
|
+
LOGGER.warning(
|
892
|
+
f"user config directory '{p}' is not writeable, using '{alt}'. Set YOLO_CONFIG_DIR to override."
|
893
|
+
)
|
894
|
+
return alt
|
887
895
|
|
888
|
-
|
896
|
+
# Last fallback → CWD
|
897
|
+
p = Path.cwd() / sub_dir
|
898
|
+
p.mkdir(parents=True, exist_ok=True)
|
899
|
+
return p
|
889
900
|
|
890
901
|
|
891
902
|
# Define constants (required below)
|
@@ -899,7 +910,7 @@ IS_JUPYTER = is_jupyter()
|
|
899
910
|
IS_PIP_PACKAGE = is_pip_package()
|
900
911
|
IS_RASPBERRYPI = is_raspberrypi()
|
901
912
|
GIT = GitRepo()
|
902
|
-
USER_CONFIG_DIR =
|
913
|
+
USER_CONFIG_DIR = get_user_config_dir() # Ultralytics settings dir
|
903
914
|
SETTINGS_FILE = USER_CONFIG_DIR / "settings.json"
|
904
915
|
|
905
916
|
|
@@ -1383,7 +1394,7 @@ class SettingsManager(JSONDict):
|
|
1383
1394
|
|
1384
1395
|
def deprecation_warn(arg, new_arg=None):
|
1385
1396
|
"""Issue a deprecation warning when a deprecated argument is used, suggesting an updated argument."""
|
1386
|
-
msg = f"'{arg}' is deprecated and will be removed in
|
1397
|
+
msg = f"'{arg}' is deprecated and will be removed in the future."
|
1387
1398
|
if new_arg is not None:
|
1388
1399
|
msg += f" Use '{new_arg}' instead."
|
1389
1400
|
LOGGER.warning(msg)
|
@@ -70,14 +70,14 @@ def _log_tensorboard_graph(trainer) -> None:
|
|
70
70
|
# Try simple method first (YOLO)
|
71
71
|
try:
|
72
72
|
trainer.model.eval() # place in .eval() mode to avoid BatchNorm statistics changes
|
73
|
-
WRITER.add_graph(torch.jit.trace(torch_utils.
|
73
|
+
WRITER.add_graph(torch.jit.trace(torch_utils.unwrap_model(trainer.model), im, strict=False), [])
|
74
74
|
LOGGER.info(f"{PREFIX}model graph visualization added ✅")
|
75
75
|
return
|
76
76
|
|
77
77
|
except Exception:
|
78
78
|
# Fallback to TorchScript export steps (RTDETR)
|
79
79
|
try:
|
80
|
-
model = deepcopy(torch_utils.
|
80
|
+
model = deepcopy(torch_utils.unwrap_model(trainer.model))
|
81
81
|
model.eval()
|
82
82
|
model = model.fuse(verbose=False)
|
83
83
|
for m in model.modules():
|
ultralytics/utils/checks.py
CHANGED
@@ -452,6 +452,8 @@ def check_torchvision():
|
|
452
452
|
to the compatibility table based on: https://github.com/pytorch/vision#installation.
|
453
453
|
"""
|
454
454
|
compatibility_table = {
|
455
|
+
"2.9": ["0.24"],
|
456
|
+
"2.8": ["0.23"],
|
455
457
|
"2.7": ["0.22"],
|
456
458
|
"2.6": ["0.21"],
|
457
459
|
"2.5": ["0.20"],
|
ultralytics/utils/loss.py
CHANGED
@@ -260,7 +260,7 @@ class v8DetectionLoss:
|
|
260
260
|
|
261
261
|
# Targets
|
262
262
|
targets = torch.cat((batch["batch_idx"].view(-1, 1), batch["cls"].view(-1, 1), batch["bboxes"]), 1)
|
263
|
-
targets = self.preprocess(targets
|
263
|
+
targets = self.preprocess(targets, batch_size, scale_tensor=imgsz[[1, 0, 1, 0]])
|
264
264
|
gt_labels, gt_bboxes = targets.split((1, 4), 2) # cls, xyxy
|
265
265
|
mask_gt = gt_bboxes.sum(2, keepdim=True).gt_(0.0)
|
266
266
|
|
@@ -287,9 +287,14 @@ class v8DetectionLoss:
|
|
287
287
|
|
288
288
|
# Bbox loss
|
289
289
|
if fg_mask.sum():
|
290
|
-
target_bboxes /= stride_tensor
|
291
290
|
loss[0], loss[2] = self.bbox_loss(
|
292
|
-
pred_distri,
|
291
|
+
pred_distri,
|
292
|
+
pred_bboxes,
|
293
|
+
anchor_points,
|
294
|
+
target_bboxes / stride_tensor,
|
295
|
+
target_scores,
|
296
|
+
target_scores_sum,
|
297
|
+
fg_mask,
|
293
298
|
)
|
294
299
|
|
295
300
|
loss[0] *= self.hyp.box # box gain
|
@@ -329,7 +334,7 @@ class v8SegmentationLoss(v8DetectionLoss):
|
|
329
334
|
try:
|
330
335
|
batch_idx = batch["batch_idx"].view(-1, 1)
|
331
336
|
targets = torch.cat((batch_idx, batch["cls"].view(-1, 1), batch["bboxes"]), 1)
|
332
|
-
targets = self.preprocess(targets
|
337
|
+
targets = self.preprocess(targets, batch_size, scale_tensor=imgsz[[1, 0, 1, 0]])
|
333
338
|
gt_labels, gt_bboxes = targets.split((1, 4), 2) # cls, xyxy
|
334
339
|
mask_gt = gt_bboxes.sum(2, keepdim=True).gt_(0.0)
|
335
340
|
except RuntimeError as e:
|
@@ -388,7 +393,7 @@ class v8SegmentationLoss(v8DetectionLoss):
|
|
388
393
|
loss[2] *= self.hyp.cls # cls gain
|
389
394
|
loss[3] *= self.hyp.dfl # dfl gain
|
390
395
|
|
391
|
-
return loss * batch_size, loss.detach() # loss(box, cls, dfl)
|
396
|
+
return loss * batch_size, loss.detach() # loss(box, seg, cls, dfl)
|
392
397
|
|
393
398
|
@staticmethod
|
394
399
|
def single_mask_loss(
|
@@ -516,7 +521,7 @@ class v8PoseLoss(v8DetectionLoss):
|
|
516
521
|
batch_size = pred_scores.shape[0]
|
517
522
|
batch_idx = batch["batch_idx"].view(-1, 1)
|
518
523
|
targets = torch.cat((batch_idx, batch["cls"].view(-1, 1), batch["bboxes"]), 1)
|
519
|
-
targets = self.preprocess(targets
|
524
|
+
targets = self.preprocess(targets, batch_size, scale_tensor=imgsz[[1, 0, 1, 0]])
|
520
525
|
gt_labels, gt_bboxes = targets.split((1, 4), 2) # cls, xyxy
|
521
526
|
mask_gt = gt_bboxes.sum(2, keepdim=True).gt_(0.0)
|
522
527
|
|
@@ -704,7 +709,7 @@ class v8OBBLoss(v8DetectionLoss):
|
|
704
709
|
targets = torch.cat((batch_idx, batch["cls"].view(-1, 1), batch["bboxes"].view(-1, 5)), 1)
|
705
710
|
rw, rh = targets[:, 4] * imgsz[0].item(), targets[:, 5] * imgsz[1].item()
|
706
711
|
targets = targets[(rw >= 2) & (rh >= 2)] # filter rboxes of tiny size to stabilize training
|
707
|
-
targets = self.preprocess(targets
|
712
|
+
targets = self.preprocess(targets, batch_size, scale_tensor=imgsz[[1, 0, 1, 0]])
|
708
713
|
gt_labels, gt_bboxes = targets.split((1, 5), 2) # cls, xywhr
|
709
714
|
mask_gt = gt_bboxes.sum(2, keepdim=True).gt_(0.0)
|
710
715
|
except RuntimeError as e:
|
ultralytics/utils/nms.py
CHANGED
@@ -192,6 +192,7 @@ class TorchNMS:
|
|
192
192
|
iou_threshold: float,
|
193
193
|
use_triu: bool = True,
|
194
194
|
iou_func=box_iou,
|
195
|
+
exit_early: bool = True,
|
195
196
|
) -> torch.Tensor:
|
196
197
|
"""
|
197
198
|
Fast-NMS implementation from https://arxiv.org/pdf/1904.02689 using upper triangular matrix operations.
|
@@ -202,6 +203,7 @@ class TorchNMS:
|
|
202
203
|
iou_threshold (float): IoU threshold for suppression.
|
203
204
|
use_triu (bool): Whether to use torch.triu operator for upper triangular matrix operations.
|
204
205
|
iou_func (callable): Function to compute IoU between boxes.
|
206
|
+
exit_early (bool): Whether to exit early if there are no boxes.
|
205
207
|
|
206
208
|
Returns:
|
207
209
|
(torch.Tensor): Indices of boxes to keep after NMS.
|
@@ -212,7 +214,7 @@ class TorchNMS:
|
|
212
214
|
>>> scores = torch.tensor([0.9, 0.8])
|
213
215
|
>>> keep = TorchNMS.nms(boxes, scores, 0.5)
|
214
216
|
"""
|
215
|
-
if boxes.numel() == 0:
|
217
|
+
if boxes.numel() == 0 and exit_early:
|
216
218
|
return torch.empty((0,), dtype=torch.int64, device=boxes.device)
|
217
219
|
|
218
220
|
sorted_idx = torch.argsort(scores, descending=True)
|
ultralytics/utils/plotting.py
CHANGED
@@ -1004,6 +1004,7 @@ def plot_tune_results(csv_file: str = "tune_results.csv"):
|
|
1004
1004
|
_save_one_file(csv_file.with_name("tune_fitness.png"))
|
1005
1005
|
|
1006
1006
|
|
1007
|
+
@plt_settings()
|
1007
1008
|
def feature_visualization(x, module_type: str, stage: int, n: int = 32, save_dir: Path = Path("runs/detect/exp")):
|
1008
1009
|
"""
|
1009
1010
|
Visualize feature maps of a given model module during inference.
|