ultralytics 8.3.119__py3-none-any.whl → 8.3.120__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.
- ultralytics/__init__.py +1 -1
- ultralytics/data/augment.py +31 -50
- ultralytics/data/dataset.py +1 -1
- ultralytics/models/yolo/world/train_world.py +17 -5
- ultralytics/models/yolo/yoloe/__init__.py +2 -1
- ultralytics/models/yolo/yoloe/train.py +12 -113
- ultralytics/models/yolo/yoloe/train_seg.py +1 -17
- ultralytics/trackers/bot_sort.py +5 -5
- ultralytics/utils/loss.py +4 -3
- {ultralytics-8.3.119.dist-info → ultralytics-8.3.120.dist-info}/METADATA +1 -1
- {ultralytics-8.3.119.dist-info → ultralytics-8.3.120.dist-info}/RECORD +15 -15
- {ultralytics-8.3.119.dist-info → ultralytics-8.3.120.dist-info}/WHEEL +0 -0
- {ultralytics-8.3.119.dist-info → ultralytics-8.3.120.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.3.119.dist-info → ultralytics-8.3.120.dist-info}/licenses/LICENSE +0 -0
- {ultralytics-8.3.119.dist-info → ultralytics-8.3.120.dist-info}/top_level.txt +0 -0
ultralytics/__init__.py
CHANGED
ultralytics/data/augment.py
CHANGED
@@ -439,7 +439,7 @@ class BaseMixTransform:
|
|
439
439
|
>>> indexes = transform.get_indexes()
|
440
440
|
>>> print(indexes) # [3, 18, 7, 2]
|
441
441
|
"""
|
442
|
-
|
442
|
+
return random.randint(0, len(self.dataset) - 1)
|
443
443
|
|
444
444
|
@staticmethod
|
445
445
|
def _update_label_text(labels):
|
@@ -877,7 +877,6 @@ class MixUp(BaseMixTransform):
|
|
877
877
|
p (float): Probability of applying MixUp augmentation.
|
878
878
|
|
879
879
|
Methods:
|
880
|
-
get_indexes: Returns a random index from the dataset.
|
881
880
|
_mix_transform: Applies MixUp augmentation to the input labels.
|
882
881
|
|
883
882
|
Examples:
|
@@ -906,24 +905,6 @@ class MixUp(BaseMixTransform):
|
|
906
905
|
"""
|
907
906
|
super().__init__(dataset=dataset, pre_transform=pre_transform, p=p)
|
908
907
|
|
909
|
-
def get_indexes(self):
|
910
|
-
"""
|
911
|
-
Get a random index from the dataset.
|
912
|
-
|
913
|
-
This method returns a single random index from the dataset, which is used to select an image for MixUp
|
914
|
-
augmentation.
|
915
|
-
|
916
|
-
Returns:
|
917
|
-
(int): A random integer index within the range of the dataset length.
|
918
|
-
|
919
|
-
Examples:
|
920
|
-
>>> mixup = MixUp(dataset)
|
921
|
-
>>> index = mixup.get_indexes()
|
922
|
-
>>> print(index)
|
923
|
-
42
|
924
|
-
"""
|
925
|
-
return random.randint(0, len(self.dataset) - 1)
|
926
|
-
|
927
908
|
def _mix_transform(self, labels):
|
928
909
|
"""
|
929
910
|
Applies MixUp augmentation to the input labels.
|
@@ -961,9 +942,9 @@ class CutMix(BaseMixTransform):
|
|
961
942
|
pre_transform (Callable | None): Optional transform to apply before CutMix.
|
962
943
|
p (float): Probability of applying CutMix augmentation.
|
963
944
|
beta (float): Beta distribution parameter for sampling the mixing ratio (default=1.0).
|
945
|
+
num_areas (int): Number of areas to try to cut and mix (default=3).
|
964
946
|
|
965
947
|
Methods:
|
966
|
-
get_indexes: Returns a random index from the dataset.
|
967
948
|
_mix_transform: Applies CutMix augmentation to the input labels.
|
968
949
|
_rand_bbox: Generates random bounding box coordinates for the cut region.
|
969
950
|
|
@@ -974,7 +955,7 @@ class CutMix(BaseMixTransform):
|
|
974
955
|
>>> augmented_labels = cutmix(original_labels)
|
975
956
|
"""
|
976
957
|
|
977
|
-
def __init__(self, dataset, pre_transform=None, p=0.0, beta=1.0) -> None:
|
958
|
+
def __init__(self, dataset, pre_transform=None, p=0.0, beta=1.0, num_areas=3) -> None:
|
978
959
|
"""
|
979
960
|
Initializes the CutMix augmentation object.
|
980
961
|
|
@@ -983,31 +964,26 @@ class CutMix(BaseMixTransform):
|
|
983
964
|
pre_transform (Callable | None): Optional transform to apply before CutMix.
|
984
965
|
p (float): Probability of applying CutMix augmentation.
|
985
966
|
beta (float): Beta distribution parameter for sampling the mixing ratio (default=1.0).
|
967
|
+
num_areas (int): Number of areas to try to cut and mix (default=3).
|
986
968
|
"""
|
987
969
|
super().__init__(dataset=dataset, pre_transform=pre_transform, p=p)
|
988
970
|
self.beta = beta
|
971
|
+
self.num_areas = num_areas
|
989
972
|
|
990
|
-
def
|
991
|
-
"""
|
992
|
-
Get a random index from the dataset.
|
993
|
-
|
994
|
-
Returns:
|
995
|
-
(int): A random integer index within the range of the dataset length.
|
996
|
-
"""
|
997
|
-
return random.randint(0, len(self.dataset) - 1)
|
998
|
-
|
999
|
-
def _rand_bbox(self, width, height, lam):
|
973
|
+
def _rand_bbox(self, width, height):
|
1000
974
|
"""
|
1001
975
|
Generates random bounding box coordinates for the cut region.
|
1002
976
|
|
1003
977
|
Args:
|
1004
978
|
width (int): Width of the image.
|
1005
979
|
height (int): Height of the image.
|
1006
|
-
lam (float): Mixing ratio from the Beta distribution.
|
1007
980
|
|
1008
981
|
Returns:
|
1009
982
|
(tuple): (x1, y1, x2, y2) coordinates of the bounding box.
|
1010
983
|
"""
|
984
|
+
# Sample mixing ratio from Beta distribution
|
985
|
+
lam = np.random.beta(self.beta, self.beta)
|
986
|
+
|
1011
987
|
cut_ratio = np.sqrt(1.0 - lam)
|
1012
988
|
cut_w = int(width * cut_ratio)
|
1013
989
|
cut_h = int(height * cut_ratio)
|
@@ -1038,25 +1014,35 @@ class CutMix(BaseMixTransform):
|
|
1038
1014
|
>>> cutter = CutMix(dataset)
|
1039
1015
|
>>> mixed_labels = cutter._mix_transform(labels)
|
1040
1016
|
"""
|
1041
|
-
# Sample mixing ratio from Beta distribution
|
1042
|
-
lam = np.random.beta(self.beta, self.beta)
|
1043
|
-
|
1044
1017
|
# Get a random second image
|
1045
|
-
labels2 = labels["mix_labels"][0]
|
1046
|
-
img2 = labels2["img"]
|
1047
1018
|
h, w = labels["img"].shape[:2]
|
1048
1019
|
|
1049
|
-
|
1050
|
-
|
1020
|
+
cut_areas = np.asarray([self._rand_bbox(w, h) for _ in range(self.num_areas)], dtype=np.float32)
|
1021
|
+
ioa1 = bbox_ioa(cut_areas, labels["instances"].bboxes) # (self.num_areas, num_boxes)
|
1022
|
+
idx = np.nonzero(ioa1.sum(axis=1) <= 0)[0]
|
1023
|
+
if len(idx) == 0:
|
1024
|
+
return labels
|
1025
|
+
|
1026
|
+
labels2 = labels.pop("mix_labels")[0]
|
1027
|
+
area = cut_areas[np.random.choice(idx)] # randomle select one
|
1028
|
+
ioa2 = bbox_ioa(area[None], labels2["instances"].bboxes).squeeze(0)
|
1029
|
+
indexes2 = np.nonzero(ioa2 >= 0.01 if len(labels["instances"].segments) else 0.1)[0]
|
1030
|
+
|
1031
|
+
instances2 = labels2["instances"][indexes2]
|
1032
|
+
instances2.convert_bbox("xyxy")
|
1033
|
+
instances2.denormalize(w, h)
|
1051
1034
|
|
1052
1035
|
# Apply CutMix
|
1053
|
-
|
1036
|
+
x1, y1, x2, y2 = area.astype(np.int32)
|
1037
|
+
labels["img"][y1:y2, x1:x2] = labels2["img"][y1:y2, x1:x2]
|
1054
1038
|
|
1055
|
-
#
|
1056
|
-
|
1039
|
+
# Restrain instances2 to the random bounding border
|
1040
|
+
instances2.add_padding(-x1, -y1)
|
1041
|
+
instances2.clip(x2 - x1, y2 - y1)
|
1042
|
+
instances2.add_padding(x1, y1)
|
1057
1043
|
|
1058
|
-
labels["cls"] = np.concatenate([labels["cls"], labels2["cls"]], axis=0)
|
1059
|
-
labels["instances"] = Instances.concatenate([labels["instances"],
|
1044
|
+
labels["cls"] = np.concatenate([labels["cls"], labels2["cls"][indexes2]], axis=0)
|
1045
|
+
labels["instances"] = Instances.concatenate([labels["instances"], instances2], axis=0)
|
1060
1046
|
return labels
|
1061
1047
|
|
1062
1048
|
|
@@ -1766,7 +1752,6 @@ class CopyPaste(BaseMixTransform):
|
|
1766
1752
|
p (float): Probability of applying Copy-Paste augmentation.
|
1767
1753
|
|
1768
1754
|
Methods:
|
1769
|
-
get_indexes: Returns a random index from the dataset.
|
1770
1755
|
_mix_transform: Applies Copy-Paste augmentation to the input labels.
|
1771
1756
|
__call__: Applies the Copy-Paste transformation to images and annotations.
|
1772
1757
|
|
@@ -1783,10 +1768,6 @@ class CopyPaste(BaseMixTransform):
|
|
1783
1768
|
assert mode in {"flip", "mixup"}, f"Expected `mode` to be `flip` or `mixup`, but got {mode}."
|
1784
1769
|
self.mode = mode
|
1785
1770
|
|
1786
|
-
def get_indexes(self):
|
1787
|
-
"""Returns a list of random indexes from the dataset for CopyPaste augmentation."""
|
1788
|
-
return random.randint(0, len(self.dataset) - 1)
|
1789
|
-
|
1790
1771
|
def _mix_transform(self, labels):
|
1791
1772
|
"""Applies Copy-Paste augmentation to combine objects from another image into the current image."""
|
1792
1773
|
labels2 = labels["mix_labels"][0]
|
ultralytics/data/dataset.py
CHANGED
@@ -443,7 +443,7 @@ class GroundingDataset(YOLODataset):
|
|
443
443
|
"""
|
444
444
|
assert task in {"detect", "segment"}, "GroundingDataset currently only supports `detect` and `segment` tasks"
|
445
445
|
self.json_file = json_file
|
446
|
-
super().__init__(*args, task=task, data={}, **kwargs)
|
446
|
+
super().__init__(*args, task=task, data={"channels": 3}, **kwargs)
|
447
447
|
|
448
448
|
def get_img_files(self, img_path):
|
449
449
|
"""
|
@@ -3,7 +3,7 @@
|
|
3
3
|
from ultralytics.data import YOLOConcatDataset, build_grounding, build_yolo_dataset
|
4
4
|
from ultralytics.data.utils import check_det_dataset
|
5
5
|
from ultralytics.models.yolo.world import WorldTrainer
|
6
|
-
from ultralytics.utils import DEFAULT_CFG
|
6
|
+
from ultralytics.utils import DEFAULT_CFG, LOGGER
|
7
7
|
from ultralytics.utils.torch_utils import de_parallel
|
8
8
|
|
9
9
|
|
@@ -93,14 +93,14 @@ class WorldTrainerFromScratch(WorldTrainer):
|
|
93
93
|
"""
|
94
94
|
gs = max(int(de_parallel(self.model).stride.max() if self.model else 0), 32)
|
95
95
|
if mode != "train":
|
96
|
-
return build_yolo_dataset(self.args, img_path, batch, self.data, mode=mode, rect=
|
97
|
-
|
98
|
-
build_yolo_dataset(self.args, im_path, batch, self.
|
96
|
+
return build_yolo_dataset(self.args, img_path, batch, self.data, mode=mode, rect=False, stride=gs)
|
97
|
+
datasets = [
|
98
|
+
build_yolo_dataset(self.args, im_path, batch, self.training_data[im_path], stride=gs, multi_modal=True)
|
99
99
|
if isinstance(im_path, str)
|
100
100
|
else build_grounding(self.args, im_path["img_path"], im_path["json_file"], batch, stride=gs)
|
101
101
|
for im_path in img_path
|
102
102
|
]
|
103
|
-
return YOLOConcatDataset(
|
103
|
+
return YOLOConcatDataset(datasets) if len(datasets) > 1 else datasets[0]
|
104
104
|
|
105
105
|
def get_dataset(self):
|
106
106
|
"""
|
@@ -140,8 +140,20 @@ class WorldTrainerFromScratch(WorldTrainer):
|
|
140
140
|
# NOTE: to make training work properly, set `nc` and `names`
|
141
141
|
final_data["nc"] = data["val"][0]["nc"]
|
142
142
|
final_data["names"] = data["val"][0]["names"]
|
143
|
+
# NOTE: add path with lvis path
|
144
|
+
final_data["path"] = data["val"][0]["path"]
|
143
145
|
final_data["channels"] = data["val"][0]["channels"]
|
144
146
|
self.data = final_data
|
147
|
+
if self.args.single_cls: # consistent with base trainer
|
148
|
+
LOGGER.info("Overriding class names with single class.")
|
149
|
+
self.data["names"] = {0: "object"}
|
150
|
+
self.data["nc"] = 1
|
151
|
+
self.training_data = {}
|
152
|
+
for d in data["train"]:
|
153
|
+
if self.args.single_cls:
|
154
|
+
d["names"] = {0: "object"}
|
155
|
+
d["nc"] = 1
|
156
|
+
self.training_data[d["train"]] = d
|
145
157
|
return final_data["train"], final_data["val"][0]
|
146
158
|
|
147
159
|
def plot_training_labels(self):
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
3
|
from .predict import YOLOEVPDetectPredictor, YOLOEVPSegPredictor
|
4
|
-
from .train import YOLOEPEFreeTrainer, YOLOEPETrainer, YOLOETrainer, YOLOEVPTrainer
|
4
|
+
from .train import YOLOEPEFreeTrainer, YOLOEPETrainer, YOLOETrainer, YOLOETrainerFromScratch, YOLOEVPTrainer
|
5
5
|
from .train_seg import YOLOEPESegTrainer, YOLOESegTrainer, YOLOESegTrainerFromScratch, YOLOESegVPTrainer
|
6
6
|
from .val import YOLOEDetectValidator, YOLOESegValidator
|
7
7
|
|
@@ -18,4 +18,5 @@ __all__ = [
|
|
18
18
|
"YOLOEPEFreeTrainer",
|
19
19
|
"YOLOEVPDetectPredictor",
|
20
20
|
"YOLOEVPSegPredictor",
|
21
|
+
"YOLOETrainerFromScratch",
|
21
22
|
]
|
@@ -6,14 +6,14 @@ from pathlib import Path
|
|
6
6
|
|
7
7
|
import torch
|
8
8
|
|
9
|
-
from ultralytics.data import YOLOConcatDataset,
|
9
|
+
from ultralytics.data import YOLOConcatDataset, build_yolo_dataset
|
10
10
|
from ultralytics.data.augment import LoadVisualPrompt
|
11
|
-
from ultralytics.data.utils import check_det_dataset
|
12
11
|
from ultralytics.models.yolo.detect import DetectionTrainer, DetectionValidator
|
13
12
|
from ultralytics.nn.tasks import YOLOEModel
|
14
13
|
from ultralytics.utils import DEFAULT_CFG, LOGGER, RANK
|
15
14
|
from ultralytics.utils.torch_utils import de_parallel
|
16
15
|
|
16
|
+
from ..world.train_world import WorldTrainerFromScratch
|
17
17
|
from .val import YOLOEDetectValidator
|
18
18
|
|
19
19
|
|
@@ -92,11 +92,6 @@ class YOLOETrainer(DetectionTrainer):
|
|
92
92
|
self.args, img_path, batch, self.data, mode=mode, rect=mode == "val", stride=gs, multi_modal=mode == "train"
|
93
93
|
)
|
94
94
|
|
95
|
-
def preprocess_batch(self, batch):
|
96
|
-
"""Process batch for training, moving text features to the appropriate device."""
|
97
|
-
batch = super().preprocess_batch(batch)
|
98
|
-
return batch
|
99
|
-
|
100
95
|
|
101
96
|
class YOLOEPETrainer(DetectionTrainer):
|
102
97
|
"""Fine-tune YOLOE model in linear probing way."""
|
@@ -144,30 +139,9 @@ class YOLOEPETrainer(DetectionTrainer):
|
|
144
139
|
return model
|
145
140
|
|
146
141
|
|
147
|
-
class YOLOETrainerFromScratch(YOLOETrainer):
|
142
|
+
class YOLOETrainerFromScratch(YOLOETrainer, WorldTrainerFromScratch):
|
148
143
|
"""Train YOLOE models from scratch."""
|
149
144
|
|
150
|
-
def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
|
151
|
-
"""
|
152
|
-
Initialize the YOLOETrainerFromScratch class.
|
153
|
-
|
154
|
-
This class extends YOLOETrainer to train YOLOE models from scratch. It inherits all functionality from
|
155
|
-
the parent class while providing specialized initialization for training without pre-trained weights.
|
156
|
-
|
157
|
-
Args:
|
158
|
-
cfg (dict, optional): Configuration dictionary with training parameters. Defaults to DEFAULT_CFG.
|
159
|
-
overrides (dict, optional): Dictionary of parameter overrides for configuration.
|
160
|
-
_callbacks (list, optional): List of callback functions to be executed during training.
|
161
|
-
|
162
|
-
Examples:
|
163
|
-
>>> from ultralytics.models.yoloe.train import YOLOETrainerFromScratch
|
164
|
-
>>> trainer = YOLOETrainerFromScratch()
|
165
|
-
>>> trainer.train()
|
166
|
-
"""
|
167
|
-
if overrides is None:
|
168
|
-
overrides = {}
|
169
|
-
super().__init__(cfg, overrides, _callbacks)
|
170
|
-
|
171
145
|
def build_dataset(self, img_path, mode="train", batch=None):
|
172
146
|
"""
|
173
147
|
Build YOLO Dataset for training or validation.
|
@@ -183,17 +157,12 @@ class YOLOETrainerFromScratch(YOLOETrainer):
|
|
183
157
|
Returns:
|
184
158
|
(YOLOConcatDataset | Dataset): The constructed dataset for training or validation.
|
185
159
|
"""
|
186
|
-
|
187
|
-
if mode
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
else build_grounding(self.args, im_path["img_path"], im_path["json_file"], batch, stride=gs)
|
193
|
-
for im_path in img_path
|
194
|
-
]
|
195
|
-
self.set_text_embeddings(datasets, batch) # cache text embeddings to accelerate training
|
196
|
-
return YOLOConcatDataset(datasets) if len(datasets) > 1 else datasets[0]
|
160
|
+
datasets = WorldTrainerFromScratch.build_dataset(self, img_path, mode, batch)
|
161
|
+
if mode == "train":
|
162
|
+
self.set_text_embeddings(
|
163
|
+
datasets.datasets if hasattr(datasets, "datasets") else [datasets], batch
|
164
|
+
) # cache text embeddings to accelerate training
|
165
|
+
return datasets
|
197
166
|
|
198
167
|
def set_text_embeddings(self, datasets, batch):
|
199
168
|
"""
|
@@ -225,7 +194,7 @@ class YOLOETrainerFromScratch(YOLOETrainer):
|
|
225
194
|
|
226
195
|
def preprocess_batch(self, batch):
|
227
196
|
"""Process batch for training, moving text features to the appropriate device."""
|
228
|
-
batch =
|
197
|
+
batch = DetectionTrainer.preprocess_batch(self, batch)
|
229
198
|
|
230
199
|
texts = list(itertools.chain(*batch["texts"]))
|
231
200
|
txt_feats = torch.stack([self.text_embeddings[text] for text in texts]).to(self.device)
|
@@ -246,6 +215,7 @@ class YOLOETrainerFromScratch(YOLOETrainer):
|
|
246
215
|
(dict): Dictionary mapping text samples to their embeddings.
|
247
216
|
"""
|
248
217
|
if cache_path.exists():
|
218
|
+
LOGGER.info(f"Reading existed cache from '{cache_path}'")
|
249
219
|
return torch.load(cache_path)
|
250
220
|
assert self.model is not None
|
251
221
|
txt_feats = self.model.get_text_pe(texts, batch, without_reprta=True)
|
@@ -253,77 +223,6 @@ class YOLOETrainerFromScratch(YOLOETrainer):
|
|
253
223
|
torch.save(txt_map, cache_path)
|
254
224
|
return txt_map
|
255
225
|
|
256
|
-
def get_dataset(self):
|
257
|
-
"""
|
258
|
-
Get train and validation paths from data dictionary.
|
259
|
-
|
260
|
-
Processes the data configuration to extract paths for training and validation datasets,
|
261
|
-
handling both YOLO detection datasets and grounding datasets.
|
262
|
-
|
263
|
-
Returns:
|
264
|
-
(str): Train dataset path.
|
265
|
-
(str): Validation dataset path.
|
266
|
-
|
267
|
-
Raises:
|
268
|
-
AssertionError: If train or validation datasets are not found, or if validation has multiple datasets.
|
269
|
-
"""
|
270
|
-
final_data = {}
|
271
|
-
data_yaml = self.args.data
|
272
|
-
assert data_yaml.get("train", False), "train dataset not found" # object365.yaml
|
273
|
-
assert data_yaml.get("val", False), "validation dataset not found" # lvis.yaml
|
274
|
-
data = {k: [check_det_dataset(d) for d in v.get("yolo_data", [])] for k, v in data_yaml.items()}
|
275
|
-
assert len(data["val"]) == 1, f"Only support validating on 1 dataset for now, but got {len(data['val'])}."
|
276
|
-
val_split = "minival" if "lvis" in data["val"][0]["val"] else "val"
|
277
|
-
for d in data["val"]:
|
278
|
-
if d.get("minival") is None: # for lvis dataset
|
279
|
-
continue
|
280
|
-
d["minival"] = str(d["path"] / d["minival"])
|
281
|
-
for s in ["train", "val"]:
|
282
|
-
final_data[s] = [d["train" if s == "train" else val_split] for d in data[s]]
|
283
|
-
# save grounding data if there's one
|
284
|
-
grounding_data = data_yaml[s].get("grounding_data")
|
285
|
-
if grounding_data is None:
|
286
|
-
continue
|
287
|
-
grounding_data = grounding_data if isinstance(grounding_data, list) else [grounding_data]
|
288
|
-
for g in grounding_data:
|
289
|
-
assert isinstance(g, dict), f"Grounding data should be provided in dict format, but got {type(g)}"
|
290
|
-
final_data[s] += grounding_data
|
291
|
-
# NOTE: to make training work properly, set `nc` and `names`
|
292
|
-
final_data["nc"] = data["val"][0]["nc"]
|
293
|
-
final_data["names"] = data["val"][0]["names"]
|
294
|
-
# NOTE: add path with lvis path
|
295
|
-
final_data["path"] = data["val"][0]["path"]
|
296
|
-
self.data = final_data
|
297
|
-
if self.args.single_cls: # consistent with base trainer
|
298
|
-
LOGGER.info("Overriding class names with single class.")
|
299
|
-
self.data["names"] = {0: "object"}
|
300
|
-
self.data["nc"] = 1
|
301
|
-
self.training_data = {}
|
302
|
-
for d in data["train"]:
|
303
|
-
if self.args.single_cls:
|
304
|
-
d["names"] = {0: "object"}
|
305
|
-
d["nc"] = 1
|
306
|
-
self.training_data[d["train"]] = d
|
307
|
-
return final_data["train"], final_data["val"][0]
|
308
|
-
|
309
|
-
def plot_training_labels(self):
|
310
|
-
"""Do not plot labels for YOLO-World training."""
|
311
|
-
pass
|
312
|
-
|
313
|
-
def final_eval(self):
|
314
|
-
"""
|
315
|
-
Perform final evaluation on the validation dataset.
|
316
|
-
|
317
|
-
Configures the validator with the appropriate dataset and split before running evaluation.
|
318
|
-
|
319
|
-
Returns:
|
320
|
-
(dict): Evaluation metrics.
|
321
|
-
"""
|
322
|
-
val = self.args.data["val"]["yolo_data"][0]
|
323
|
-
self.validator.args.data = val
|
324
|
-
self.validator.args.split = "minival" if isinstance(val, str) and "lvis" in val else "val"
|
325
|
-
return super().final_eval()
|
326
|
-
|
327
226
|
|
328
227
|
class YOLOEPEFreeTrainer(YOLOEPETrainer, YOLOETrainerFromScratch):
|
329
228
|
"""Train prompt-free YOLOE model."""
|
@@ -337,7 +236,7 @@ class YOLOEPEFreeTrainer(YOLOEPETrainer, YOLOETrainerFromScratch):
|
|
337
236
|
|
338
237
|
def preprocess_batch(self, batch):
|
339
238
|
"""Preprocesses a batch of images for YOLOE training, adjusting formatting and dimensions as needed."""
|
340
|
-
batch =
|
239
|
+
batch = DetectionTrainer.preprocess_batch(self, batch)
|
341
240
|
return batch
|
342
241
|
|
343
242
|
def set_text_embeddings(self, datasets, batch):
|
@@ -5,7 +5,7 @@ from copy import copy, deepcopy
|
|
5
5
|
|
6
6
|
from ultralytics.models.yolo.segment import SegmentationTrainer
|
7
7
|
from ultralytics.nn.tasks import YOLOESegModel
|
8
|
-
from ultralytics.utils import
|
8
|
+
from ultralytics.utils import RANK
|
9
9
|
|
10
10
|
from .train import YOLOETrainer, YOLOETrainerFromScratch, YOLOEVPTrainer
|
11
11
|
from .val import YOLOESegValidator
|
@@ -24,22 +24,6 @@ class YOLOESegTrainer(YOLOETrainer, SegmentationTrainer):
|
|
24
24
|
_callbacks (list): List of callback functions for training events.
|
25
25
|
"""
|
26
26
|
|
27
|
-
def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):
|
28
|
-
"""
|
29
|
-
Initialize the YOLOESegTrainer class.
|
30
|
-
|
31
|
-
This class combines YOLOETrainer and SegmentationTrainer to provide training functionality
|
32
|
-
specifically for YOLOE segmentation models.
|
33
|
-
|
34
|
-
Args:
|
35
|
-
cfg (Dict): Configuration dictionary with training parameters.
|
36
|
-
overrides (Dict, optional): Dictionary with parameter overrides.
|
37
|
-
_callbacks (List, optional): List of callback functions for training events.
|
38
|
-
"""
|
39
|
-
if overrides is None:
|
40
|
-
overrides = {}
|
41
|
-
super().__init__(cfg, overrides, _callbacks)
|
42
|
-
|
43
27
|
def get_model(self, cfg=None, weights=None, verbose=True):
|
44
28
|
"""
|
45
29
|
Return YOLOESegModel initialized with specified config and weights.
|
ultralytics/trackers/bot_sort.py
CHANGED
@@ -17,7 +17,7 @@ from .utils.kalman_filter import KalmanFilterXYWH
|
|
17
17
|
|
18
18
|
class BOTrack(STrack):
|
19
19
|
"""
|
20
|
-
An extended version of the STrack class for
|
20
|
+
An extended version of the STrack class for YOLO, adding object tracking features.
|
21
21
|
|
22
22
|
This class extends the STrack class to include additional functionalities for object tracking, such as feature
|
23
23
|
smoothing, Kalman filter prediction, and reactivation of tracks.
|
@@ -150,7 +150,7 @@ class BOTrack(STrack):
|
|
150
150
|
|
151
151
|
class BOTSORT(BYTETracker):
|
152
152
|
"""
|
153
|
-
An extended version of the BYTETracker class for
|
153
|
+
An extended version of the BYTETracker class for YOLO, designed for object tracking with ReID and GMC algorithm.
|
154
154
|
|
155
155
|
Attributes:
|
156
156
|
proximity_thresh (float): Threshold for spatial proximity (IoU) between tracks and detections.
|
@@ -163,7 +163,7 @@ class BOTSORT(BYTETracker):
|
|
163
163
|
get_kalmanfilter: Return an instance of KalmanFilterXYWH for object tracking.
|
164
164
|
init_track: Initialize track with detections, scores, and classes.
|
165
165
|
get_dists: Get distances between tracks and detections using IoU and (optionally) ReID.
|
166
|
-
multi_predict: Predict and track multiple objects with
|
166
|
+
multi_predict: Predict and track multiple objects with a YOLO model.
|
167
167
|
reset: Reset the BOTSORT tracker to its initial state.
|
168
168
|
|
169
169
|
Examples:
|
@@ -173,7 +173,7 @@ class BOTSORT(BYTETracker):
|
|
173
173
|
>>> bot_sort.multi_predict(tracks)
|
174
174
|
|
175
175
|
Note:
|
176
|
-
The class is designed to work with
|
176
|
+
The class is designed to work with a YOLO object detection model and supports ReID only if enabled via args.
|
177
177
|
"""
|
178
178
|
|
179
179
|
def __init__(self, args, frame_rate=30):
|
@@ -197,7 +197,7 @@ class BOTSORT(BYTETracker):
|
|
197
197
|
self.appearance_thresh = args.appearance_thresh
|
198
198
|
self.encoder = (
|
199
199
|
(lambda feats, s: [f.cpu().numpy() for f in feats]) # native features do not require any model
|
200
|
-
if self.args.model == "auto"
|
200
|
+
if args.with_reid and self.args.model == "auto"
|
201
201
|
else ReID(args.model)
|
202
202
|
if args.with_reid
|
203
203
|
else None
|
ultralytics/utils/loss.py
CHANGED
@@ -794,15 +794,16 @@ class TVPSegmentLoss(TVPDetectLoss):
|
|
794
794
|
|
795
795
|
def __init__(self, model):
|
796
796
|
"""Initialize TVPSegmentLoss with task-prompt and visual-prompt criteria using the provided model."""
|
797
|
+
super().__init__(model)
|
797
798
|
self.vp_criterion = v8SegmentationLoss(model)
|
798
799
|
|
799
800
|
def __call__(self, preds, batch):
|
800
801
|
"""Calculate the loss for text-visual prompt segmentation."""
|
801
802
|
feats, pred_masks, proto = preds if len(preds) == 3 else preds[1]
|
802
|
-
assert self.
|
803
|
+
assert self.ori_reg_max == self.vp_criterion.reg_max # TODO: remove it
|
803
804
|
|
804
|
-
if self.
|
805
|
-
loss = torch.zeros(4, device=self.
|
805
|
+
if self.ori_reg_max * 4 + self.ori_nc == feats[0].shape[1]:
|
806
|
+
loss = torch.zeros(4, device=self.vp_criterion.device, requires_grad=True)
|
806
807
|
return loss, loss.detach()
|
807
808
|
|
808
809
|
vp_feats = self._get_vp_features(feats)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ultralytics
|
3
|
-
Version: 8.3.
|
3
|
+
Version: 8.3.120
|
4
4
|
Summary: Ultralytics YOLO 🚀 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
|
5
5
|
Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>, Jing Qiu <jing.qiu@ultralytics.com>
|
6
6
|
Maintainer-email: Ultralytics <hello@ultralytics.com>
|
@@ -7,7 +7,7 @@ tests/test_exports.py,sha256=dhZn86LdbapW15RthQF870LGxDjC1MUZhlGdBgPmgIQ,9716
|
|
7
7
|
tests/test_integrations.py,sha256=dQteeRsRVuT_p5-T88-7jqT65Zm9iAXkyKg-KQ1_TQ8,6341
|
8
8
|
tests/test_python.py,sha256=ok2xp7zwPOwcyl4yNawlx1uJ5HETn9eU-jyTPYzA0fI,25491
|
9
9
|
tests/test_solutions.py,sha256=BIvg9zW0a_ggEmrPKgB_Y0MncveH-eYuN5KlqdJ6nHs,5726
|
10
|
-
ultralytics/__init__.py,sha256=
|
10
|
+
ultralytics/__init__.py,sha256=s0vdAaSAbSlu_5DON0IAjl8rb6whRMR18hW9WkNVsfw,730
|
11
11
|
ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
|
12
12
|
ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
|
13
13
|
ultralytics/cfg/__init__.py,sha256=eZ7exHSsrTLY72atmmHKatJgJYLjfZDPXMWVmpZF9Qw,39683
|
@@ -104,11 +104,11 @@ ultralytics/cfg/trackers/botsort.yaml,sha256=8fM3y4TXKKT_5aWsqmQw5JEgwNlBGlRaf8L
|
|
104
104
|
ultralytics/cfg/trackers/bytetrack.yaml,sha256=6u-tiZlk16EqEwkNXaMrza6PAQmWj_ypgv26LGCtPDg,886
|
105
105
|
ultralytics/data/__init__.py,sha256=nAXaL1puCc7z_NjzQNlJnhbVhT9Fla2u7Dsqo7q1dAc,644
|
106
106
|
ultralytics/data/annotator.py,sha256=VEwb11FsEZm75qlEp8XDHFGKW0_rGsEaFDaBVd771Kw,2902
|
107
|
-
ultralytics/data/augment.py,sha256=
|
107
|
+
ultralytics/data/augment.py,sha256=m0haieHkMrpe-nEApapfR4mEuOnCw8I4k-tvTVJpOnU,129172
|
108
108
|
ultralytics/data/base.py,sha256=uMh_xzs6ci1hciDLpbVW2ZQr7js0o8jctE8KhL2T7Z4,19015
|
109
109
|
ultralytics/data/build.py,sha256=FVIkgLGv5n1C7SRDrQiKOMDcI7V59WmEihKslzvEISg,9651
|
110
110
|
ultralytics/data/converter.py,sha256=znXH2XTdo0Q4NDHMny1ydVBvrxKn2kbbwI-X5bn1MlQ,26890
|
111
|
-
ultralytics/data/dataset.py,sha256=
|
111
|
+
ultralytics/data/dataset.py,sha256=hbsjhmZBO-T1_gkUAm128kKowdwsLNwnK2lhnzmxJB8,34826
|
112
112
|
ultralytics/data/loaders.py,sha256=o844tZlfZEhXop16t-hwaEQHhbfP3_bQMS0whF_NSos,28531
|
113
113
|
ultralytics/data/split.py,sha256=6LHB1z8woXurWjXfM-Zm2thRr1KXvzR18CFJA-SDUvE,4677
|
114
114
|
ultralytics/data/split_dota.py,sha256=p8eVGht9tABSVbf9vwvxA_AQYEva3IGHePKlMeNrn64,11872
|
@@ -186,11 +186,11 @@ ultralytics/models/yolo/segment/train.py,sha256=EIyIAjYp127Mb-DomyjPORaONu57OY_g
|
|
186
186
|
ultralytics/models/yolo/segment/val.py,sha256=cXJM1JNuzDraU0SJQRIdzNxabd0bfcxiRE8wozHZChY,18415
|
187
187
|
ultralytics/models/yolo/world/__init__.py,sha256=nlh8I6t8hMGz_vZg8QSlsUW1R-2eKvn9CGUoPPQEGhA,131
|
188
188
|
ultralytics/models/yolo/world/train.py,sha256=HUJ0XiJIGx_FA9kqNYnSFsaKWMiZUDxgkpfGoBH6UNc,4896
|
189
|
-
ultralytics/models/yolo/world/train_world.py,sha256
|
190
|
-
ultralytics/models/yolo/yoloe/__init__.py,sha256=
|
189
|
+
ultralytics/models/yolo/world/train_world.py,sha256=-o_-85zoczEvXZHWHJaVhXQ_hAIGTFtPlgSWJmUf5AU,8287
|
190
|
+
ultralytics/models/yolo/yoloe/__init__.py,sha256=6SLytdJtwu37qewf7CobG7C7Wl1m-xtNdvCXEasfPDE,760
|
191
191
|
ultralytics/models/yolo/yoloe/predict.py,sha256=pjvQ8TKlAe_KIFo70qiNdOrSTITU3pcJ4VE_k7uJjDk,6994
|
192
|
-
ultralytics/models/yolo/yoloe/train.py,sha256=
|
193
|
-
ultralytics/models/yolo/yoloe/train_seg.py,sha256=
|
192
|
+
ultralytics/models/yolo/yoloe/train.py,sha256=St3zw_XWRol9pODWU4lvKlJnWYr1lmWQNuhLFwWMge4,12989
|
193
|
+
ultralytics/models/yolo/yoloe/train_seg.py,sha256=l0SOMQQd0Y_EBBHhTNekgrQsftqhYyK4oWTdCg1dLrE,4633
|
194
194
|
ultralytics/models/yolo/yoloe/val.py,sha256=oA8cVT3pBXF6aPZy7ITq0mDcktRuIgks8tTtqMRISyY,8431
|
195
195
|
ultralytics/nn/__init__.py,sha256=rjociYD9lo_K-d-1s6TbdWklPLjTcEHk7OIlRDJstIE,615
|
196
196
|
ultralytics/nn/autobackend.py,sha256=tnYxzboWGBgNvUYrz2zokPH1Bw__GD2ZQro1gO-ZIF8,39298
|
@@ -223,7 +223,7 @@ ultralytics/solutions/trackzone.py,sha256=efko4U8zT8lyNLLo9zF543rTXHefeYthxf9GV3
|
|
223
223
|
ultralytics/solutions/vision_eye.py,sha256=DHf3pQzNqP71oYx3QXflvcGsg4nEYJCD1SOdSOxiWBk,2965
|
224
224
|
ultralytics/trackers/__init__.py,sha256=Zlu_Ig5osn7hqch_g5Be_e4pwZUkeeTQiesJCi0pFGI,255
|
225
225
|
ultralytics/trackers/basetrack.py,sha256=LYvWB5d7Woyrz_RlxaopjV07RQKH3sff_lZJfMcMxcA,4450
|
226
|
-
ultralytics/trackers/bot_sort.py,sha256=
|
226
|
+
ultralytics/trackers/bot_sort.py,sha256=iDYLk3VAfsdCHisy4l9_JKxJw3YEBMgGdK0E6HthoXo,11307
|
227
227
|
ultralytics/trackers/byte_tracker.py,sha256=D7JQ_6V8OUMQryxTrAr010UXMSaboQnI7T1xppzHXYg,20921
|
228
228
|
ultralytics/trackers/track.py,sha256=mu6L9RWAW8Nq0vJanX-hTTUST-OmLq49d8VV96-J9u8,4817
|
229
229
|
ultralytics/trackers/utils/__init__.py,sha256=lm6MckFYCPTbqIoX7w0s_daxdjNeBeKW6DXppv1-QUM,70
|
@@ -240,7 +240,7 @@ ultralytics/utils/errors.py,sha256=vY9h2evFSrHnZdHJVVrmm8Zzw4qVDLyo9DeYW5g0dFk,1
|
|
240
240
|
ultralytics/utils/export.py,sha256=mTkebwilsT1jwIfTLgAQdkbrnZr9Sm96W-Vi7B1j5wQ,8817
|
241
241
|
ultralytics/utils/files.py,sha256=0K4O1cgqRiXaDw7EQK13TqA5SME_RrvfDVQSPetNr5w,8042
|
242
242
|
ultralytics/utils/instance.py,sha256=UOEsXR9V-bXNRk6BTonASBEgeMqvzzAk4S7VdXZJUAM,18090
|
243
|
-
ultralytics/utils/loss.py,sha256=
|
243
|
+
ultralytics/utils/loss.py,sha256=s9LT-zz1zc81Kak0xt1O5HQlv8z0Br-EvudklYs6A6E,37501
|
244
244
|
ultralytics/utils/metrics.py,sha256=uv5O-2Ft8wYfTvDedFxiUqMZ6Nr2CL6I9ybGZiK3e2s,53773
|
245
245
|
ultralytics/utils/ops.py,sha256=YFwPrKlPcgEmgAWqnJVR0Ccx5NQgp5e3P-YYHwVSP0k,34779
|
246
246
|
ultralytics/utils/patches.py,sha256=6rVT-l8WDp_Py3O-gZdv9t3PnrYRRkrX_lF3mZ1XS8c,4928
|
@@ -260,9 +260,9 @@ ultralytics/utils/callbacks/neptune.py,sha256=JaI95Cj2kIjUhlEEOiDN0-Drc-fDelLhNI
|
|
260
260
|
ultralytics/utils/callbacks/raytune.py,sha256=A8amUGpux7dYES-L1iSeMoMXBySGWCD1aUqT7vcG-pU,1284
|
261
261
|
ultralytics/utils/callbacks/tensorboard.py,sha256=jgYnym3cUQFAgN1GzTyO7l3jINtfAh8zhrllDvnLuVQ,5339
|
262
262
|
ultralytics/utils/callbacks/wb.py,sha256=iDRFXI4IIDm8R5OI89DMTmjs8aHLo1HRCLkOFKdaMG4,7507
|
263
|
-
ultralytics-8.3.
|
264
|
-
ultralytics-8.3.
|
265
|
-
ultralytics-8.3.
|
266
|
-
ultralytics-8.3.
|
267
|
-
ultralytics-8.3.
|
268
|
-
ultralytics-8.3.
|
263
|
+
ultralytics-8.3.120.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
264
|
+
ultralytics-8.3.120.dist-info/METADATA,sha256=mP-Pkx1G9KDrCfpRBMWAJ9MlL1o-sF7NQHVUdXH-xas,37195
|
265
|
+
ultralytics-8.3.120.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
|
266
|
+
ultralytics-8.3.120.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
|
267
|
+
ultralytics-8.3.120.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
|
268
|
+
ultralytics-8.3.120.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|