ultralytics 8.3.190__py3-none-any.whl → 8.3.191__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_cuda.py +6 -5
- tests/test_exports.py +1 -6
- tests/test_python.py +1 -4
- tests/test_solutions.py +1 -1
- ultralytics/__init__.py +1 -1
- ultralytics/cfg/__init__.py +16 -14
- ultralytics/cfg/datasets/VisDrone.yaml +4 -4
- ultralytics/data/annotator.py +6 -6
- ultralytics/data/augment.py +53 -51
- ultralytics/data/base.py +15 -13
- ultralytics/data/build.py +7 -4
- ultralytics/data/converter.py +9 -10
- ultralytics/data/dataset.py +24 -22
- ultralytics/data/loaders.py +13 -11
- ultralytics/data/split.py +4 -3
- ultralytics/data/split_dota.py +14 -12
- ultralytics/data/utils.py +29 -23
- ultralytics/engine/exporter.py +2 -2
- ultralytics/engine/model.py +16 -14
- ultralytics/engine/predictor.py +8 -6
- ultralytics/engine/results.py +54 -52
- ultralytics/engine/trainer.py +7 -2
- ultralytics/engine/tuner.py +4 -3
- ultralytics/hub/google/__init__.py +7 -6
- ultralytics/hub/session.py +8 -6
- ultralytics/hub/utils.py +3 -4
- ultralytics/models/fastsam/model.py +8 -6
- ultralytics/models/nas/model.py +5 -3
- ultralytics/models/rtdetr/train.py +4 -3
- ultralytics/models/rtdetr/val.py +6 -4
- ultralytics/models/sam/amg.py +13 -10
- ultralytics/models/sam/model.py +3 -2
- ultralytics/models/sam/modules/blocks.py +21 -21
- ultralytics/models/sam/modules/decoders.py +11 -11
- ultralytics/models/sam/modules/encoders.py +25 -25
- ultralytics/models/sam/modules/memory_attention.py +9 -8
- ultralytics/models/sam/modules/sam.py +8 -10
- ultralytics/models/sam/modules/tiny_encoder.py +21 -20
- ultralytics/models/sam/modules/transformer.py +6 -5
- ultralytics/models/sam/modules/utils.py +7 -5
- ultralytics/models/sam/predict.py +32 -31
- ultralytics/models/utils/loss.py +29 -27
- ultralytics/models/utils/ops.py +10 -8
- ultralytics/models/yolo/classify/train.py +7 -5
- ultralytics/models/yolo/classify/val.py +10 -8
- ultralytics/models/yolo/detect/predict.py +1 -1
- ultralytics/models/yolo/detect/train.py +8 -6
- ultralytics/models/yolo/detect/val.py +21 -19
- ultralytics/models/yolo/model.py +14 -14
- ultralytics/models/yolo/obb/train.py +5 -3
- ultralytics/models/yolo/obb/val.py +11 -9
- ultralytics/models/yolo/pose/train.py +7 -5
- ultralytics/models/yolo/pose/val.py +11 -9
- ultralytics/models/yolo/segment/train.py +4 -5
- ultralytics/models/yolo/segment/val.py +12 -10
- ultralytics/models/yolo/world/train.py +9 -7
- ultralytics/models/yolo/yoloe/train.py +7 -6
- ultralytics/models/yolo/yoloe/val.py +10 -8
- ultralytics/nn/autobackend.py +17 -19
- ultralytics/nn/modules/block.py +12 -12
- ultralytics/nn/modules/conv.py +4 -3
- ultralytics/nn/modules/head.py +41 -37
- ultralytics/nn/modules/transformer.py +22 -21
- ultralytics/nn/tasks.py +2 -2
- ultralytics/nn/text_model.py +6 -5
- ultralytics/solutions/analytics.py +7 -5
- ultralytics/solutions/config.py +12 -10
- ultralytics/solutions/distance_calculation.py +3 -3
- ultralytics/solutions/heatmap.py +4 -2
- ultralytics/solutions/object_counter.py +5 -3
- ultralytics/solutions/parking_management.py +4 -2
- ultralytics/solutions/region_counter.py +7 -5
- ultralytics/solutions/similarity_search.py +5 -3
- ultralytics/solutions/solutions.py +38 -36
- ultralytics/solutions/streamlit_inference.py +8 -7
- ultralytics/trackers/bot_sort.py +11 -9
- ultralytics/trackers/byte_tracker.py +17 -15
- ultralytics/trackers/utils/gmc.py +4 -3
- ultralytics/utils/__init__.py +16 -88
- ultralytics/utils/autobatch.py +3 -2
- ultralytics/utils/autodevice.py +10 -10
- ultralytics/utils/benchmarks.py +11 -10
- ultralytics/utils/callbacks/comet.py +9 -9
- ultralytics/utils/checks.py +17 -26
- ultralytics/utils/export.py +12 -11
- ultralytics/utils/files.py +8 -7
- ultralytics/utils/git.py +139 -0
- ultralytics/utils/instance.py +8 -7
- ultralytics/utils/loss.py +15 -13
- ultralytics/utils/metrics.py +62 -62
- ultralytics/utils/ops.py +3 -2
- ultralytics/utils/patches.py +6 -4
- ultralytics/utils/plotting.py +18 -16
- ultralytics/utils/torch_utils.py +4 -2
- ultralytics/utils/tqdm.py +15 -12
- ultralytics/utils/triton.py +3 -2
- {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/METADATA +1 -1
- {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/RECORD +102 -101
- {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/WHEEL +0 -0
- {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/licenses/LICENSE +0 -0
- {ultralytics-8.3.190.dist-info → ultralytics-8.3.191.dist-info}/top_level.txt +0 -0
ultralytics/engine/results.py
CHANGED
@@ -5,10 +5,12 @@ Ultralytics Results, Boxes and Masks classes for handling inference results.
|
|
5
5
|
Usage: See https://docs.ultralytics.com/modes/predict/
|
6
6
|
"""
|
7
7
|
|
8
|
+
from __future__ import annotations
|
9
|
+
|
8
10
|
from copy import deepcopy
|
9
11
|
from functools import lru_cache
|
10
12
|
from pathlib import Path
|
11
|
-
from typing import Any
|
13
|
+
from typing import Any
|
12
14
|
|
13
15
|
import numpy as np
|
14
16
|
import torch
|
@@ -46,7 +48,7 @@ class BaseTensor(SimpleClass):
|
|
46
48
|
>>> gpu_tensor = base_tensor.cuda()
|
47
49
|
"""
|
48
50
|
|
49
|
-
def __init__(self, data:
|
51
|
+
def __init__(self, data: torch.Tensor | np.ndarray, orig_shape: tuple[int, int]) -> None:
|
50
52
|
"""
|
51
53
|
Initialize BaseTensor with prediction data and the original shape of the image.
|
52
54
|
|
@@ -65,7 +67,7 @@ class BaseTensor(SimpleClass):
|
|
65
67
|
self.orig_shape = orig_shape
|
66
68
|
|
67
69
|
@property
|
68
|
-
def shape(self) ->
|
70
|
+
def shape(self) -> tuple[int, ...]:
|
69
71
|
"""
|
70
72
|
Return the shape of the underlying data tensor.
|
71
73
|
|
@@ -239,13 +241,13 @@ class Results(SimpleClass, DataExportMixin):
|
|
239
241
|
self,
|
240
242
|
orig_img: np.ndarray,
|
241
243
|
path: str,
|
242
|
-
names:
|
243
|
-
boxes:
|
244
|
-
masks:
|
245
|
-
probs:
|
246
|
-
keypoints:
|
247
|
-
obb:
|
248
|
-
speed:
|
244
|
+
names: dict[int, str],
|
245
|
+
boxes: torch.Tensor | None = None,
|
246
|
+
masks: torch.Tensor | None = None,
|
247
|
+
probs: torch.Tensor | None = None,
|
248
|
+
keypoints: torch.Tensor | None = None,
|
249
|
+
obb: torch.Tensor | None = None,
|
250
|
+
speed: dict[str, float] | None = None,
|
249
251
|
) -> None:
|
250
252
|
"""
|
251
253
|
Initialize the Results class for storing and manipulating inference results.
|
@@ -324,11 +326,11 @@ class Results(SimpleClass, DataExportMixin):
|
|
324
326
|
|
325
327
|
def update(
|
326
328
|
self,
|
327
|
-
boxes:
|
328
|
-
masks:
|
329
|
-
probs:
|
330
|
-
obb:
|
331
|
-
keypoints:
|
329
|
+
boxes: torch.Tensor | None = None,
|
330
|
+
masks: torch.Tensor | None = None,
|
331
|
+
probs: torch.Tensor | None = None,
|
332
|
+
obb: torch.Tensor | None = None,
|
333
|
+
keypoints: torch.Tensor | None = None,
|
332
334
|
):
|
333
335
|
"""
|
334
336
|
Update the Results object with new detection data.
|
@@ -473,12 +475,12 @@ class Results(SimpleClass, DataExportMixin):
|
|
473
475
|
def plot(
|
474
476
|
self,
|
475
477
|
conf: bool = True,
|
476
|
-
line_width:
|
477
|
-
font_size:
|
478
|
+
line_width: float | None = None,
|
479
|
+
font_size: float | None = None,
|
478
480
|
font: str = "Arial.ttf",
|
479
481
|
pil: bool = False,
|
480
|
-
img:
|
481
|
-
im_gpu:
|
482
|
+
img: np.ndarray | None = None,
|
483
|
+
im_gpu: torch.Tensor | None = None,
|
482
484
|
kpt_radius: int = 5,
|
483
485
|
kpt_line: bool = True,
|
484
486
|
labels: bool = True,
|
@@ -487,9 +489,9 @@ class Results(SimpleClass, DataExportMixin):
|
|
487
489
|
probs: bool = True,
|
488
490
|
show: bool = False,
|
489
491
|
save: bool = False,
|
490
|
-
filename:
|
492
|
+
filename: str | None = None,
|
491
493
|
color_mode: str = "class",
|
492
|
-
txt_color:
|
494
|
+
txt_color: tuple[int, int, int] = (255, 255, 255),
|
493
495
|
) -> np.ndarray:
|
494
496
|
"""
|
495
497
|
Plot detection results on an input RGB image.
|
@@ -629,7 +631,7 @@ class Results(SimpleClass, DataExportMixin):
|
|
629
631
|
"""
|
630
632
|
self.plot(show=True, *args, **kwargs)
|
631
633
|
|
632
|
-
def save(self, filename:
|
634
|
+
def save(self, filename: str | None = None, *args, **kwargs) -> str:
|
633
635
|
"""
|
634
636
|
Save annotated inference results image to file.
|
635
637
|
|
@@ -690,7 +692,7 @@ class Results(SimpleClass, DataExportMixin):
|
|
690
692
|
counts = boxes.cls.int().bincount()
|
691
693
|
return "".join(f"{n} {self.names[i]}{'s' * (n > 1)}, " for i, n in enumerate(counts) if n > 0)
|
692
694
|
|
693
|
-
def save_txt(self, txt_file:
|
695
|
+
def save_txt(self, txt_file: str | Path, save_conf: bool = False) -> str:
|
694
696
|
"""
|
695
697
|
Save detection results to a text file.
|
696
698
|
|
@@ -747,7 +749,7 @@ class Results(SimpleClass, DataExportMixin):
|
|
747
749
|
|
748
750
|
return str(txt_file)
|
749
751
|
|
750
|
-
def save_crop(self, save_dir:
|
752
|
+
def save_crop(self, save_dir: str | Path, file_name: str | Path = Path("im.jpg")):
|
751
753
|
"""
|
752
754
|
Save cropped detection images to specified directory.
|
753
755
|
|
@@ -783,7 +785,7 @@ class Results(SimpleClass, DataExportMixin):
|
|
783
785
|
BGR=True,
|
784
786
|
)
|
785
787
|
|
786
|
-
def summary(self, normalize: bool = False, decimals: int = 5) ->
|
788
|
+
def summary(self, normalize: bool = False, decimals: int = 5) -> list[dict[str, Any]]:
|
787
789
|
"""
|
788
790
|
Convert inference results to a summarized dictionary with optional normalization for box coordinates.
|
789
791
|
|
@@ -887,7 +889,7 @@ class Boxes(BaseTensor):
|
|
887
889
|
>>> print(boxes.xywhn)
|
888
890
|
"""
|
889
891
|
|
890
|
-
def __init__(self, boxes:
|
892
|
+
def __init__(self, boxes: torch.Tensor | np.ndarray, orig_shape: tuple[int, int]) -> None:
|
891
893
|
"""
|
892
894
|
Initialize the Boxes class with detection box data and the original image shape.
|
893
895
|
|
@@ -923,7 +925,7 @@ class Boxes(BaseTensor):
|
|
923
925
|
self.orig_shape = orig_shape
|
924
926
|
|
925
927
|
@property
|
926
|
-
def xyxy(self) ->
|
928
|
+
def xyxy(self) -> torch.Tensor | np.ndarray:
|
927
929
|
"""
|
928
930
|
Return bounding boxes in [x1, y1, x2, y2] format.
|
929
931
|
|
@@ -940,7 +942,7 @@ class Boxes(BaseTensor):
|
|
940
942
|
return self.data[:, :4]
|
941
943
|
|
942
944
|
@property
|
943
|
-
def conf(self) ->
|
945
|
+
def conf(self) -> torch.Tensor | np.ndarray:
|
944
946
|
"""
|
945
947
|
Return the confidence scores for each detection box.
|
946
948
|
|
@@ -957,7 +959,7 @@ class Boxes(BaseTensor):
|
|
957
959
|
return self.data[:, -2]
|
958
960
|
|
959
961
|
@property
|
960
|
-
def cls(self) ->
|
962
|
+
def cls(self) -> torch.Tensor | np.ndarray:
|
961
963
|
"""
|
962
964
|
Return the class ID tensor representing category predictions for each bounding box.
|
963
965
|
|
@@ -974,7 +976,7 @@ class Boxes(BaseTensor):
|
|
974
976
|
return self.data[:, -1]
|
975
977
|
|
976
978
|
@property
|
977
|
-
def id(self) ->
|
979
|
+
def id(self) -> torch.Tensor | np.ndarray | None:
|
978
980
|
"""
|
979
981
|
Return the tracking IDs for each detection box if available.
|
980
982
|
|
@@ -1000,7 +1002,7 @@ class Boxes(BaseTensor):
|
|
1000
1002
|
|
1001
1003
|
@property
|
1002
1004
|
@lru_cache(maxsize=2)
|
1003
|
-
def xywh(self) ->
|
1005
|
+
def xywh(self) -> torch.Tensor | np.ndarray:
|
1004
1006
|
"""
|
1005
1007
|
Convert bounding boxes from [x1, y1, x2, y2] format to [x, y, width, height] format.
|
1006
1008
|
|
@@ -1021,7 +1023,7 @@ class Boxes(BaseTensor):
|
|
1021
1023
|
|
1022
1024
|
@property
|
1023
1025
|
@lru_cache(maxsize=2)
|
1024
|
-
def xyxyn(self) ->
|
1026
|
+
def xyxyn(self) -> torch.Tensor | np.ndarray:
|
1025
1027
|
"""
|
1026
1028
|
Return normalized bounding box coordinates relative to the original image size.
|
1027
1029
|
|
@@ -1045,7 +1047,7 @@ class Boxes(BaseTensor):
|
|
1045
1047
|
|
1046
1048
|
@property
|
1047
1049
|
@lru_cache(maxsize=2)
|
1048
|
-
def xywhn(self) ->
|
1050
|
+
def xywhn(self) -> torch.Tensor | np.ndarray:
|
1049
1051
|
"""
|
1050
1052
|
Return normalized bounding boxes in [x, y, width, height] format.
|
1051
1053
|
|
@@ -1096,7 +1098,7 @@ class Masks(BaseTensor):
|
|
1096
1098
|
>>> normalized_coords = masks.xyn
|
1097
1099
|
"""
|
1098
1100
|
|
1099
|
-
def __init__(self, masks:
|
1101
|
+
def __init__(self, masks: torch.Tensor | np.ndarray, orig_shape: tuple[int, int]) -> None:
|
1100
1102
|
"""
|
1101
1103
|
Initialize the Masks class with detection mask data and the original image shape.
|
1102
1104
|
|
@@ -1117,7 +1119,7 @@ class Masks(BaseTensor):
|
|
1117
1119
|
|
1118
1120
|
@property
|
1119
1121
|
@lru_cache(maxsize=1)
|
1120
|
-
def xyn(self) ->
|
1122
|
+
def xyn(self) -> list[np.ndarray]:
|
1121
1123
|
"""
|
1122
1124
|
Return normalized xy-coordinates of the segmentation masks.
|
1123
1125
|
|
@@ -1142,7 +1144,7 @@ class Masks(BaseTensor):
|
|
1142
1144
|
|
1143
1145
|
@property
|
1144
1146
|
@lru_cache(maxsize=1)
|
1145
|
-
def xy(self) ->
|
1147
|
+
def xy(self) -> list[np.ndarray]:
|
1146
1148
|
"""
|
1147
1149
|
Return the [x, y] pixel coordinates for each segment in the mask tensor.
|
1148
1150
|
|
@@ -1200,7 +1202,7 @@ class Keypoints(BaseTensor):
|
|
1200
1202
|
>>> keypoints_cpu = keypoints.cpu() # Move keypoints to CPU
|
1201
1203
|
"""
|
1202
1204
|
|
1203
|
-
def __init__(self, keypoints:
|
1205
|
+
def __init__(self, keypoints: torch.Tensor | np.ndarray, orig_shape: tuple[int, int]) -> None:
|
1204
1206
|
"""
|
1205
1207
|
Initialize the Keypoints object with detection keypoints and original image dimensions.
|
1206
1208
|
|
@@ -1225,7 +1227,7 @@ class Keypoints(BaseTensor):
|
|
1225
1227
|
|
1226
1228
|
@property
|
1227
1229
|
@lru_cache(maxsize=1)
|
1228
|
-
def xy(self) ->
|
1230
|
+
def xy(self) -> torch.Tensor | np.ndarray:
|
1229
1231
|
"""
|
1230
1232
|
Return x, y coordinates of keypoints.
|
1231
1233
|
|
@@ -1249,7 +1251,7 @@ class Keypoints(BaseTensor):
|
|
1249
1251
|
|
1250
1252
|
@property
|
1251
1253
|
@lru_cache(maxsize=1)
|
1252
|
-
def xyn(self) ->
|
1254
|
+
def xyn(self) -> torch.Tensor | np.ndarray:
|
1253
1255
|
"""
|
1254
1256
|
Return normalized coordinates (x, y) of keypoints relative to the original image size.
|
1255
1257
|
|
@@ -1271,7 +1273,7 @@ class Keypoints(BaseTensor):
|
|
1271
1273
|
|
1272
1274
|
@property
|
1273
1275
|
@lru_cache(maxsize=1)
|
1274
|
-
def conf(self) ->
|
1276
|
+
def conf(self) -> torch.Tensor | np.ndarray | None:
|
1275
1277
|
"""
|
1276
1278
|
Return confidence values for each keypoint.
|
1277
1279
|
|
@@ -1322,7 +1324,7 @@ class Probs(BaseTensor):
|
|
1322
1324
|
tensor([0.6000, 0.3000, 0.1000])
|
1323
1325
|
"""
|
1324
1326
|
|
1325
|
-
def __init__(self, probs:
|
1327
|
+
def __init__(self, probs: torch.Tensor | np.ndarray, orig_shape: tuple[int, int] | None = None) -> None:
|
1326
1328
|
"""
|
1327
1329
|
Initialize the Probs class with classification probabilities.
|
1328
1330
|
|
@@ -1372,7 +1374,7 @@ class Probs(BaseTensor):
|
|
1372
1374
|
|
1373
1375
|
@property
|
1374
1376
|
@lru_cache(maxsize=1)
|
1375
|
-
def top5(self) ->
|
1377
|
+
def top5(self) -> list[int]:
|
1376
1378
|
"""
|
1377
1379
|
Return the indices of the top 5 class probabilities.
|
1378
1380
|
|
@@ -1388,7 +1390,7 @@ class Probs(BaseTensor):
|
|
1388
1390
|
|
1389
1391
|
@property
|
1390
1392
|
@lru_cache(maxsize=1)
|
1391
|
-
def top1conf(self) ->
|
1393
|
+
def top1conf(self) -> torch.Tensor | np.ndarray:
|
1392
1394
|
"""
|
1393
1395
|
Return the confidence score of the highest probability class.
|
1394
1396
|
|
@@ -1408,7 +1410,7 @@ class Probs(BaseTensor):
|
|
1408
1410
|
|
1409
1411
|
@property
|
1410
1412
|
@lru_cache(maxsize=1)
|
1411
|
-
def top5conf(self) ->
|
1413
|
+
def top5conf(self) -> torch.Tensor | np.ndarray:
|
1412
1414
|
"""
|
1413
1415
|
Return confidence scores for the top 5 classification predictions.
|
1414
1416
|
|
@@ -1463,7 +1465,7 @@ class OBB(BaseTensor):
|
|
1463
1465
|
>>> print(obb.cls)
|
1464
1466
|
"""
|
1465
1467
|
|
1466
|
-
def __init__(self, boxes:
|
1468
|
+
def __init__(self, boxes: torch.Tensor | np.ndarray, orig_shape: tuple[int, int]) -> None:
|
1467
1469
|
"""
|
1468
1470
|
Initialize an OBB (Oriented Bounding Box) instance with oriented bounding box data and original image shape.
|
1469
1471
|
|
@@ -1500,7 +1502,7 @@ class OBB(BaseTensor):
|
|
1500
1502
|
self.orig_shape = orig_shape
|
1501
1503
|
|
1502
1504
|
@property
|
1503
|
-
def xywhr(self) ->
|
1505
|
+
def xywhr(self) -> torch.Tensor | np.ndarray:
|
1504
1506
|
"""
|
1505
1507
|
Return boxes in [x_center, y_center, width, height, rotation] format.
|
1506
1508
|
|
@@ -1518,7 +1520,7 @@ class OBB(BaseTensor):
|
|
1518
1520
|
return self.data[:, :5]
|
1519
1521
|
|
1520
1522
|
@property
|
1521
|
-
def conf(self) ->
|
1523
|
+
def conf(self) -> torch.Tensor | np.ndarray:
|
1522
1524
|
"""
|
1523
1525
|
Return the confidence scores for Oriented Bounding Boxes (OBBs).
|
1524
1526
|
|
@@ -1538,7 +1540,7 @@ class OBB(BaseTensor):
|
|
1538
1540
|
return self.data[:, -2]
|
1539
1541
|
|
1540
1542
|
@property
|
1541
|
-
def cls(self) ->
|
1543
|
+
def cls(self) -> torch.Tensor | np.ndarray:
|
1542
1544
|
"""
|
1543
1545
|
Return the class values of the oriented bounding boxes.
|
1544
1546
|
|
@@ -1556,7 +1558,7 @@ class OBB(BaseTensor):
|
|
1556
1558
|
return self.data[:, -1]
|
1557
1559
|
|
1558
1560
|
@property
|
1559
|
-
def id(self) ->
|
1561
|
+
def id(self) -> torch.Tensor | np.ndarray | None:
|
1560
1562
|
"""
|
1561
1563
|
Return the tracking IDs of the oriented bounding boxes (if available).
|
1562
1564
|
|
@@ -1576,7 +1578,7 @@ class OBB(BaseTensor):
|
|
1576
1578
|
|
1577
1579
|
@property
|
1578
1580
|
@lru_cache(maxsize=2)
|
1579
|
-
def xyxyxyxy(self) ->
|
1581
|
+
def xyxyxyxy(self) -> torch.Tensor | np.ndarray:
|
1580
1582
|
"""
|
1581
1583
|
Convert OBB format to 8-point (xyxyxyxy) coordinate format for rotated bounding boxes.
|
1582
1584
|
|
@@ -1595,7 +1597,7 @@ class OBB(BaseTensor):
|
|
1595
1597
|
|
1596
1598
|
@property
|
1597
1599
|
@lru_cache(maxsize=2)
|
1598
|
-
def xyxyxyxyn(self) ->
|
1600
|
+
def xyxyxyxyn(self) -> torch.Tensor | np.ndarray:
|
1599
1601
|
"""
|
1600
1602
|
Convert rotated bounding boxes to normalized xyxyxyxy format.
|
1601
1603
|
|
@@ -1617,7 +1619,7 @@ class OBB(BaseTensor):
|
|
1617
1619
|
|
1618
1620
|
@property
|
1619
1621
|
@lru_cache(maxsize=2)
|
1620
|
-
def xyxy(self) ->
|
1622
|
+
def xyxy(self) -> torch.Tensor | np.ndarray:
|
1621
1623
|
"""
|
1622
1624
|
Convert oriented bounding boxes (OBB) to axis-aligned bounding boxes in xyxy format.
|
1623
1625
|
|
ultralytics/engine/trainer.py
CHANGED
@@ -27,6 +27,7 @@ from ultralytics.data.utils import check_cls_dataset, check_det_dataset
|
|
27
27
|
from ultralytics.nn.tasks import attempt_load_one_weight, attempt_load_weights
|
28
28
|
from ultralytics.utils import (
|
29
29
|
DEFAULT_CFG,
|
30
|
+
GIT,
|
30
31
|
LOCAL_RANK,
|
31
32
|
LOGGER,
|
32
33
|
RANK,
|
@@ -36,7 +37,6 @@ from ultralytics.utils import (
|
|
36
37
|
clean_url,
|
37
38
|
colorstr,
|
38
39
|
emojis,
|
39
|
-
get_git_commit,
|
40
40
|
)
|
41
41
|
from ultralytics.utils.autobatch import check_train_batch_size
|
42
42
|
from ultralytics.utils.checks import check_amp, check_file, check_imgsz, check_model_file_from_stem, print_args
|
@@ -573,7 +573,12 @@ class BaseTrainer:
|
|
573
573
|
"train_results": self.read_results_csv(),
|
574
574
|
"date": datetime.now().isoformat(),
|
575
575
|
"version": __version__,
|
576
|
-
"
|
576
|
+
"git": {
|
577
|
+
"root": str(GIT.root),
|
578
|
+
"branch": GIT.branch,
|
579
|
+
"commit": GIT.commit,
|
580
|
+
"origin": GIT.origin,
|
581
|
+
},
|
577
582
|
"license": "AGPL-3.0 (https://ultralytics.com/license)",
|
578
583
|
"docs": "https://docs.ultralytics.com",
|
579
584
|
},
|
ultralytics/engine/tuner.py
CHANGED
@@ -14,11 +14,12 @@ Examples:
|
|
14
14
|
>>> model.tune(data="coco8.yaml", epochs=10, iterations=300, optimizer="AdamW", plots=False, save=False, val=False)
|
15
15
|
"""
|
16
16
|
|
17
|
+
from __future__ import annotations
|
18
|
+
|
17
19
|
import random
|
18
20
|
import shutil
|
19
21
|
import subprocess
|
20
22
|
import time
|
21
|
-
from typing import Dict, List, Optional
|
22
23
|
|
23
24
|
import numpy as np
|
24
25
|
|
@@ -59,7 +60,7 @@ class Tuner:
|
|
59
60
|
>>> model.tune(space={key1: val1, key2: val2}) # custom search space dictionary
|
60
61
|
"""
|
61
62
|
|
62
|
-
def __init__(self, args=DEFAULT_CFG, _callbacks:
|
63
|
+
def __init__(self, args=DEFAULT_CFG, _callbacks: list | None = None):
|
63
64
|
"""
|
64
65
|
Initialize the Tuner with configurations.
|
65
66
|
|
@@ -109,7 +110,7 @@ class Tuner:
|
|
109
110
|
|
110
111
|
def _mutate(
|
111
112
|
self, parent: str = "single", n: int = 5, mutation: float = 0.8, sigma: float = 0.2
|
112
|
-
) ->
|
113
|
+
) -> dict[str, float]:
|
113
114
|
"""
|
114
115
|
Mutate hyperparameters based on bounds and scaling factors specified in `self.space`.
|
115
116
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import concurrent.futures
|
4
6
|
import statistics
|
5
7
|
import time
|
6
|
-
from typing import List, Optional, Tuple
|
7
8
|
|
8
9
|
|
9
10
|
class GCPRegions:
|
@@ -71,16 +72,16 @@ class GCPRegions:
|
|
71
72
|
"us-west4": (2, "Las Vegas", "United States"),
|
72
73
|
}
|
73
74
|
|
74
|
-
def tier1(self) ->
|
75
|
+
def tier1(self) -> list[str]:
|
75
76
|
"""Return a list of GCP regions classified as tier 1 based on predefined criteria."""
|
76
77
|
return [region for region, info in self.regions.items() if info[0] == 1]
|
77
78
|
|
78
|
-
def tier2(self) ->
|
79
|
+
def tier2(self) -> list[str]:
|
79
80
|
"""Return a list of GCP regions classified as tier 2 based on predefined criteria."""
|
80
81
|
return [region for region, info in self.regions.items() if info[0] == 2]
|
81
82
|
|
82
83
|
@staticmethod
|
83
|
-
def _ping_region(region: str, attempts: int = 1) ->
|
84
|
+
def _ping_region(region: str, attempts: int = 1) -> tuple[str, float, float, float, float]:
|
84
85
|
"""
|
85
86
|
Ping a specified GCP region and measure network latency statistics.
|
86
87
|
|
@@ -122,9 +123,9 @@ class GCPRegions:
|
|
122
123
|
self,
|
123
124
|
top: int = 1,
|
124
125
|
verbose: bool = False,
|
125
|
-
tier:
|
126
|
+
tier: int | None = None,
|
126
127
|
attempts: int = 1,
|
127
|
-
) ->
|
128
|
+
) -> list[tuple[str, float, float, float, float]]:
|
128
129
|
"""
|
129
130
|
Determine the GCP regions with the lowest latency based on ping tests.
|
130
131
|
|
ultralytics/hub/session.py
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import shutil
|
4
6
|
import threading
|
5
7
|
import time
|
6
8
|
from http import HTTPStatus
|
7
9
|
from pathlib import Path
|
8
|
-
from typing import Any
|
10
|
+
from typing import Any
|
9
11
|
from urllib.parse import parse_qs, urlparse
|
10
12
|
|
11
13
|
from ultralytics import __version__
|
@@ -90,7 +92,7 @@ class HUBTrainingSession:
|
|
90
92
|
)
|
91
93
|
|
92
94
|
@classmethod
|
93
|
-
def create_session(cls, identifier: str, args:
|
95
|
+
def create_session(cls, identifier: str, args: dict[str, Any] | None = None):
|
94
96
|
"""
|
95
97
|
Create an authenticated HUBTrainingSession or return None.
|
96
98
|
|
@@ -137,7 +139,7 @@ class HUBTrainingSession:
|
|
137
139
|
self.model.start_heartbeat(self.rate_limits["heartbeat"])
|
138
140
|
LOGGER.info(f"{PREFIX}View model at {self.model_url} 🚀")
|
139
141
|
|
140
|
-
def create_model(self, model_args:
|
142
|
+
def create_model(self, model_args: dict[str, Any]):
|
141
143
|
"""
|
142
144
|
Initialize a HUB training session with the specified model arguments.
|
143
145
|
|
@@ -204,7 +206,7 @@ class HUBTrainingSession:
|
|
204
206
|
HUBModelError: If the identifier format is not recognized.
|
205
207
|
"""
|
206
208
|
api_key, model_id, filename = None, None, None
|
207
|
-
if
|
209
|
+
if identifier.endswith((".pt", ".yaml")):
|
208
210
|
filename = identifier
|
209
211
|
elif identifier.startswith(f"{HUB_WEB_ROOT}/models/"):
|
210
212
|
parsed_url = urlparse(identifier)
|
@@ -254,8 +256,8 @@ class HUBTrainingSession:
|
|
254
256
|
timeout: int = 30,
|
255
257
|
thread: bool = True,
|
256
258
|
verbose: bool = True,
|
257
|
-
progress_total:
|
258
|
-
stream_response:
|
259
|
+
progress_total: int | None = None,
|
260
|
+
stream_response: bool | None = None,
|
259
261
|
*args,
|
260
262
|
**kwargs,
|
261
263
|
):
|
ultralytics/hub/utils.py
CHANGED
@@ -11,8 +11,8 @@ from ultralytics import __version__
|
|
11
11
|
from ultralytics.utils import (
|
12
12
|
ARGV,
|
13
13
|
ENVIRONMENT,
|
14
|
+
GIT,
|
14
15
|
IS_COLAB,
|
15
|
-
IS_GIT_DIR,
|
16
16
|
IS_PIP_PACKAGE,
|
17
17
|
LOGGER,
|
18
18
|
ONLINE,
|
@@ -23,7 +23,6 @@ from ultralytics.utils import (
|
|
23
23
|
TQDM,
|
24
24
|
TryExcept,
|
25
25
|
colorstr,
|
26
|
-
get_git_origin_url,
|
27
26
|
)
|
28
27
|
from ultralytics.utils.downloads import GITHUB_ASSETS_NAMES
|
29
28
|
from ultralytics.utils.torch_utils import get_cpu_info
|
@@ -205,7 +204,7 @@ class Events:
|
|
205
204
|
self.t = 0.0 # rate limit timer (seconds)
|
206
205
|
self.metadata = {
|
207
206
|
"cli": Path(ARGV[0]).name == "yolo",
|
208
|
-
"install": "git" if
|
207
|
+
"install": "git" if GIT.is_repo else "pip" if IS_PIP_PACKAGE else "other",
|
209
208
|
"python": PYTHON_VERSION.rsplit(".", 1)[0], # i.e. 3.13
|
210
209
|
"CPU": get_cpu_info(),
|
211
210
|
# "GPU": get_gpu_info(index=0) if cuda else None,
|
@@ -219,7 +218,7 @@ class Events:
|
|
219
218
|
and RANK in {-1, 0}
|
220
219
|
and not TESTS_RUNNING
|
221
220
|
and ONLINE
|
222
|
-
and (IS_PIP_PACKAGE or
|
221
|
+
and (IS_PIP_PACKAGE or GIT.origin == "https://github.com/ultralytics/ultralytics.git")
|
223
222
|
)
|
224
223
|
|
225
224
|
def __call__(self, cfg, device=None):
|
@@ -1,7 +1,9 @@
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
from pathlib import Path
|
4
|
-
from typing import Any
|
6
|
+
from typing import Any
|
5
7
|
|
6
8
|
from ultralytics.engine.model import Model
|
7
9
|
|
@@ -45,10 +47,10 @@ class FastSAM(Model):
|
|
45
47
|
self,
|
46
48
|
source,
|
47
49
|
stream: bool = False,
|
48
|
-
bboxes:
|
49
|
-
points:
|
50
|
-
labels:
|
51
|
-
texts:
|
50
|
+
bboxes: list | None = None,
|
51
|
+
points: list | None = None,
|
52
|
+
labels: list | None = None,
|
53
|
+
texts: list | None = None,
|
52
54
|
**kwargs: Any,
|
53
55
|
):
|
54
56
|
"""
|
@@ -74,6 +76,6 @@ class FastSAM(Model):
|
|
74
76
|
return super().predict(source, stream, prompts=prompts, **kwargs)
|
75
77
|
|
76
78
|
@property
|
77
|
-
def task_map(self) ->
|
79
|
+
def task_map(self) -> dict[str, dict[str, Any]]:
|
78
80
|
"""Returns a dictionary mapping segment task to corresponding predictor and validator classes."""
|
79
81
|
return {"segment": {"predictor": FastSAMPredictor, "validator": FastSAMValidator}}
|
ultralytics/models/nas/model.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
from pathlib import Path
|
4
|
-
from typing import Any
|
6
|
+
from typing import Any
|
5
7
|
|
6
8
|
import torch
|
7
9
|
|
@@ -80,7 +82,7 @@ class NAS(Model):
|
|
80
82
|
self.model.args = {**DEFAULT_CFG_DICT, **self.overrides} # for export()
|
81
83
|
self.model.eval()
|
82
84
|
|
83
|
-
def info(self, detailed: bool = False, verbose: bool = True) ->
|
85
|
+
def info(self, detailed: bool = False, verbose: bool = True) -> dict[str, Any]:
|
84
86
|
"""
|
85
87
|
Log model information.
|
86
88
|
|
@@ -94,6 +96,6 @@ class NAS(Model):
|
|
94
96
|
return model_info(self.model, detailed=detailed, verbose=verbose, imgsz=640)
|
95
97
|
|
96
98
|
@property
|
97
|
-
def task_map(self) ->
|
99
|
+
def task_map(self) -> dict[str, dict[str, Any]]:
|
98
100
|
"""Return a dictionary mapping tasks to respective predictor and validator classes."""
|
99
101
|
return {"detect": {"predictor": NASPredictor, "validator": NASValidator}}
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
2
2
|
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
from copy import copy
|
4
|
-
from typing import Optional
|
5
6
|
|
6
7
|
from ultralytics.models.yolo.detect import DetectionTrainer
|
7
8
|
from ultralytics.nn.tasks import RTDETRDetectionModel
|
@@ -41,7 +42,7 @@ class RTDETRTrainer(DetectionTrainer):
|
|
41
42
|
>>> trainer.train()
|
42
43
|
"""
|
43
44
|
|
44
|
-
def get_model(self, cfg:
|
45
|
+
def get_model(self, cfg: dict | None = None, weights: str | None = None, verbose: bool = True):
|
45
46
|
"""
|
46
47
|
Initialize and return an RT-DETR model for object detection tasks.
|
47
48
|
|
@@ -58,7 +59,7 @@ class RTDETRTrainer(DetectionTrainer):
|
|
58
59
|
model.load(weights)
|
59
60
|
return model
|
60
61
|
|
61
|
-
def build_dataset(self, img_path: str, mode: str = "val", batch:
|
62
|
+
def build_dataset(self, img_path: str, mode: str = "val", batch: int | None = None):
|
62
63
|
"""
|
63
64
|
Build and return an RT-DETR dataset for training or validation.
|
64
65
|
|