ultralytics 8.0.238__py3-none-any.whl → 8.0.239__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.
Potentially problematic release.
This version of ultralytics might be problematic. Click here for more details.
- ultralytics/__init__.py +2 -2
- ultralytics/cfg/__init__.py +241 -138
- ultralytics/data/__init__.py +9 -2
- ultralytics/data/annotator.py +4 -4
- ultralytics/data/augment.py +186 -169
- ultralytics/data/base.py +54 -48
- ultralytics/data/build.py +34 -23
- ultralytics/data/converter.py +242 -70
- ultralytics/data/dataset.py +117 -95
- ultralytics/data/explorer/__init__.py +3 -1
- ultralytics/data/explorer/explorer.py +120 -100
- ultralytics/data/explorer/gui/__init__.py +1 -0
- ultralytics/data/explorer/gui/dash.py +123 -89
- ultralytics/data/explorer/utils.py +37 -39
- ultralytics/data/loaders.py +75 -62
- ultralytics/data/split_dota.py +44 -36
- ultralytics/data/utils.py +160 -142
- ultralytics/engine/exporter.py +348 -292
- ultralytics/engine/model.py +102 -66
- ultralytics/engine/predictor.py +74 -55
- ultralytics/engine/results.py +61 -41
- ultralytics/engine/trainer.py +192 -144
- ultralytics/engine/tuner.py +66 -59
- ultralytics/engine/validator.py +31 -26
- ultralytics/hub/__init__.py +54 -31
- ultralytics/hub/auth.py +28 -25
- ultralytics/hub/session.py +282 -133
- ultralytics/hub/utils.py +64 -42
- ultralytics/models/__init__.py +1 -1
- ultralytics/models/fastsam/__init__.py +1 -1
- ultralytics/models/fastsam/model.py +6 -6
- ultralytics/models/fastsam/predict.py +3 -2
- ultralytics/models/fastsam/prompt.py +55 -48
- ultralytics/models/fastsam/val.py +1 -1
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/nas/model.py +9 -8
- ultralytics/models/nas/predict.py +8 -6
- ultralytics/models/nas/val.py +11 -9
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/rtdetr/model.py +11 -9
- ultralytics/models/rtdetr/train.py +18 -16
- ultralytics/models/rtdetr/val.py +25 -19
- ultralytics/models/sam/__init__.py +1 -1
- ultralytics/models/sam/amg.py +13 -14
- ultralytics/models/sam/build.py +44 -42
- ultralytics/models/sam/model.py +6 -6
- ultralytics/models/sam/modules/decoders.py +6 -4
- ultralytics/models/sam/modules/encoders.py +37 -35
- ultralytics/models/sam/modules/sam.py +5 -4
- ultralytics/models/sam/modules/tiny_encoder.py +95 -73
- ultralytics/models/sam/modules/transformer.py +3 -2
- ultralytics/models/sam/predict.py +39 -27
- ultralytics/models/utils/loss.py +99 -95
- ultralytics/models/utils/ops.py +34 -31
- ultralytics/models/yolo/__init__.py +1 -1
- ultralytics/models/yolo/classify/__init__.py +1 -1
- ultralytics/models/yolo/classify/predict.py +8 -6
- ultralytics/models/yolo/classify/train.py +37 -31
- ultralytics/models/yolo/classify/val.py +26 -24
- ultralytics/models/yolo/detect/__init__.py +1 -1
- ultralytics/models/yolo/detect/predict.py +8 -6
- ultralytics/models/yolo/detect/train.py +47 -37
- ultralytics/models/yolo/detect/val.py +100 -82
- ultralytics/models/yolo/model.py +31 -25
- ultralytics/models/yolo/obb/__init__.py +1 -1
- ultralytics/models/yolo/obb/predict.py +13 -11
- ultralytics/models/yolo/obb/train.py +3 -3
- ultralytics/models/yolo/obb/val.py +70 -59
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +17 -12
- ultralytics/models/yolo/pose/train.py +28 -25
- ultralytics/models/yolo/pose/val.py +91 -64
- ultralytics/models/yolo/segment/__init__.py +1 -1
- ultralytics/models/yolo/segment/predict.py +10 -8
- ultralytics/models/yolo/segment/train.py +16 -15
- ultralytics/models/yolo/segment/val.py +90 -68
- ultralytics/nn/__init__.py +26 -6
- ultralytics/nn/autobackend.py +144 -112
- ultralytics/nn/modules/__init__.py +96 -13
- ultralytics/nn/modules/block.py +28 -7
- ultralytics/nn/modules/conv.py +41 -23
- ultralytics/nn/modules/head.py +60 -52
- ultralytics/nn/modules/transformer.py +49 -32
- ultralytics/nn/modules/utils.py +20 -15
- ultralytics/nn/tasks.py +215 -141
- ultralytics/solutions/ai_gym.py +59 -47
- ultralytics/solutions/distance_calculation.py +17 -14
- ultralytics/solutions/heatmap.py +57 -55
- ultralytics/solutions/object_counter.py +46 -39
- ultralytics/solutions/speed_estimation.py +13 -16
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/basetrack.py +1 -0
- ultralytics/trackers/bot_sort.py +2 -1
- ultralytics/trackers/byte_tracker.py +10 -7
- ultralytics/trackers/track.py +7 -7
- ultralytics/trackers/utils/gmc.py +25 -25
- ultralytics/trackers/utils/kalman_filter.py +85 -42
- ultralytics/trackers/utils/matching.py +8 -7
- ultralytics/utils/__init__.py +173 -152
- ultralytics/utils/autobatch.py +10 -10
- ultralytics/utils/benchmarks.py +76 -86
- ultralytics/utils/callbacks/__init__.py +1 -1
- ultralytics/utils/callbacks/base.py +29 -29
- ultralytics/utils/callbacks/clearml.py +51 -43
- ultralytics/utils/callbacks/comet.py +81 -66
- ultralytics/utils/callbacks/dvc.py +33 -26
- ultralytics/utils/callbacks/hub.py +44 -26
- ultralytics/utils/callbacks/mlflow.py +31 -24
- ultralytics/utils/callbacks/neptune.py +35 -25
- ultralytics/utils/callbacks/raytune.py +9 -4
- ultralytics/utils/callbacks/tensorboard.py +16 -11
- ultralytics/utils/callbacks/wb.py +39 -33
- ultralytics/utils/checks.py +189 -141
- ultralytics/utils/dist.py +15 -12
- ultralytics/utils/downloads.py +112 -96
- ultralytics/utils/errors.py +1 -1
- ultralytics/utils/files.py +11 -11
- ultralytics/utils/instance.py +22 -22
- ultralytics/utils/loss.py +117 -67
- ultralytics/utils/metrics.py +224 -158
- ultralytics/utils/ops.py +38 -28
- ultralytics/utils/patches.py +3 -3
- ultralytics/utils/plotting.py +217 -120
- ultralytics/utils/tal.py +19 -13
- ultralytics/utils/torch_utils.py +138 -109
- ultralytics/utils/triton.py +12 -10
- ultralytics/utils/tuner.py +49 -47
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/METADATA +2 -1
- ultralytics-8.0.239.dist-info/RECORD +188 -0
- ultralytics-8.0.238.dist-info/RECORD +0 -188
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/LICENSE +0 -0
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/WHEEL +0 -0
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.0.238.dist-info → ultralytics-8.0.239.dist-info}/top_level.txt +0 -0
ultralytics/utils/ops.py
CHANGED
|
@@ -52,7 +52,7 @@ class Profile(contextlib.ContextDecorator):
|
|
|
52
52
|
|
|
53
53
|
def __str__(self):
|
|
54
54
|
"""Returns a human-readable string representing the accumulated elapsed time in the profiler."""
|
|
55
|
-
return f
|
|
55
|
+
return f"Elapsed time is {self.t} s"
|
|
56
56
|
|
|
57
57
|
def time(self):
|
|
58
58
|
"""Get current time."""
|
|
@@ -76,9 +76,13 @@ def segment2box(segment, width=640, height=640):
|
|
|
76
76
|
# Convert 1 segment label to 1 box label, applying inside-image constraint, i.e. (xy1, xy2, ...) to (xyxy)
|
|
77
77
|
x, y = segment.T # segment xy
|
|
78
78
|
inside = (x >= 0) & (y >= 0) & (x <= width) & (y <= height)
|
|
79
|
-
x
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
x = x[inside]
|
|
80
|
+
y = y[inside]
|
|
81
|
+
return (
|
|
82
|
+
np.array([x.min(), y.min(), x.max(), y.max()], dtype=segment.dtype)
|
|
83
|
+
if any(x)
|
|
84
|
+
else np.zeros(4, dtype=segment.dtype)
|
|
85
|
+
) # xyxy
|
|
82
86
|
|
|
83
87
|
|
|
84
88
|
def scale_boxes(img1_shape, boxes, img0_shape, ratio_pad=None, padding=True, xywh=False):
|
|
@@ -101,8 +105,10 @@ def scale_boxes(img1_shape, boxes, img0_shape, ratio_pad=None, padding=True, xyw
|
|
|
101
105
|
"""
|
|
102
106
|
if ratio_pad is None: # calculate from img0_shape
|
|
103
107
|
gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1]) # gain = old / new
|
|
104
|
-
pad =
|
|
105
|
-
(img1_shape[
|
|
108
|
+
pad = (
|
|
109
|
+
round((img1_shape[1] - img0_shape[1] * gain) / 2 - 0.1),
|
|
110
|
+
round((img1_shape[0] - img0_shape[0] * gain) / 2 - 0.1),
|
|
111
|
+
) # wh padding
|
|
106
112
|
else:
|
|
107
113
|
gain = ratio_pad[0][0]
|
|
108
114
|
pad = ratio_pad[1]
|
|
@@ -145,7 +151,7 @@ def nms_rotated(boxes, scores, threshold=0.45):
|
|
|
145
151
|
Returns:
|
|
146
152
|
"""
|
|
147
153
|
if len(boxes) == 0:
|
|
148
|
-
return np.empty((0,
|
|
154
|
+
return np.empty((0,), dtype=np.int8)
|
|
149
155
|
sorted_idx = torch.argsort(scores, descending=True)
|
|
150
156
|
boxes = boxes[sorted_idx]
|
|
151
157
|
ious = batch_probiou(boxes, boxes).triu_(diagonal=1)
|
|
@@ -199,8 +205,8 @@ def non_max_suppression(
|
|
|
199
205
|
"""
|
|
200
206
|
|
|
201
207
|
# Checks
|
|
202
|
-
assert 0 <= conf_thres <= 1, f
|
|
203
|
-
assert 0 <= iou_thres <= 1, f
|
|
208
|
+
assert 0 <= conf_thres <= 1, f"Invalid Confidence threshold {conf_thres}, valid values are between 0.0 and 1.0"
|
|
209
|
+
assert 0 <= iou_thres <= 1, f"Invalid IoU {iou_thres}, valid values are between 0.0 and 1.0"
|
|
204
210
|
if isinstance(prediction, (list, tuple)): # YOLOv8 model in validation model, output = (inference_out, loss_out)
|
|
205
211
|
prediction = prediction[0] # select only inference output
|
|
206
212
|
|
|
@@ -284,7 +290,7 @@ def non_max_suppression(
|
|
|
284
290
|
|
|
285
291
|
output[xi] = x[i]
|
|
286
292
|
if (time.time() - t) > time_limit:
|
|
287
|
-
LOGGER.warning(f
|
|
293
|
+
LOGGER.warning(f"WARNING ⚠️ NMS time limit {time_limit:.3f}s exceeded")
|
|
288
294
|
break # time limit exceeded
|
|
289
295
|
|
|
290
296
|
return output
|
|
@@ -378,7 +384,7 @@ def xyxy2xywh(x):
|
|
|
378
384
|
Returns:
|
|
379
385
|
y (np.ndarray | torch.Tensor): The bounding box coordinates in (x, y, width, height) format.
|
|
380
386
|
"""
|
|
381
|
-
assert x.shape[-1] == 4, f
|
|
387
|
+
assert x.shape[-1] == 4, f"input shape last dimension expected 4 but input shape is {x.shape}"
|
|
382
388
|
y = torch.empty_like(x) if isinstance(x, torch.Tensor) else np.empty_like(x) # faster than clone/copy
|
|
383
389
|
y[..., 0] = (x[..., 0] + x[..., 2]) / 2 # x center
|
|
384
390
|
y[..., 1] = (x[..., 1] + x[..., 3]) / 2 # y center
|
|
@@ -398,7 +404,7 @@ def xywh2xyxy(x):
|
|
|
398
404
|
Returns:
|
|
399
405
|
y (np.ndarray | torch.Tensor): The bounding box coordinates in (x1, y1, x2, y2) format.
|
|
400
406
|
"""
|
|
401
|
-
assert x.shape[-1] == 4, f
|
|
407
|
+
assert x.shape[-1] == 4, f"input shape last dimension expected 4 but input shape is {x.shape}"
|
|
402
408
|
y = torch.empty_like(x) if isinstance(x, torch.Tensor) else np.empty_like(x) # faster than clone/copy
|
|
403
409
|
dw = x[..., 2] / 2 # half-width
|
|
404
410
|
dh = x[..., 3] / 2 # half-height
|
|
@@ -423,7 +429,7 @@ def xywhn2xyxy(x, w=640, h=640, padw=0, padh=0):
|
|
|
423
429
|
y (np.ndarray | torch.Tensor): The coordinates of the bounding box in the format [x1, y1, x2, y2] where
|
|
424
430
|
x1,y1 is the top-left corner, x2,y2 is the bottom-right corner of the bounding box.
|
|
425
431
|
"""
|
|
426
|
-
assert x.shape[-1] == 4, f
|
|
432
|
+
assert x.shape[-1] == 4, f"input shape last dimension expected 4 but input shape is {x.shape}"
|
|
427
433
|
y = torch.empty_like(x) if isinstance(x, torch.Tensor) else np.empty_like(x) # faster than clone/copy
|
|
428
434
|
y[..., 0] = w * (x[..., 0] - x[..., 2] / 2) + padw # top left x
|
|
429
435
|
y[..., 1] = h * (x[..., 1] - x[..., 3] / 2) + padh # top left y
|
|
@@ -449,7 +455,7 @@ def xyxy2xywhn(x, w=640, h=640, clip=False, eps=0.0):
|
|
|
449
455
|
"""
|
|
450
456
|
if clip:
|
|
451
457
|
x = clip_boxes(x, (h - eps, w - eps))
|
|
452
|
-
assert x.shape[-1] == 4, f
|
|
458
|
+
assert x.shape[-1] == 4, f"input shape last dimension expected 4 but input shape is {x.shape}"
|
|
453
459
|
y = torch.empty_like(x) if isinstance(x, torch.Tensor) else np.empty_like(x) # faster than clone/copy
|
|
454
460
|
y[..., 0] = ((x[..., 0] + x[..., 2]) / 2) / w # x center
|
|
455
461
|
y[..., 1] = ((x[..., 1] + x[..., 3]) / 2) / h # y center
|
|
@@ -526,8 +532,11 @@ def xyxyxyxy2xywhr(corners):
|
|
|
526
532
|
# especially some objects are cut off by augmentations in dataloader.
|
|
527
533
|
(x, y), (w, h), angle = cv2.minAreaRect(pts)
|
|
528
534
|
rboxes.append([x, y, w, h, angle / 180 * np.pi])
|
|
529
|
-
rboxes =
|
|
530
|
-
rboxes, dtype=
|
|
535
|
+
rboxes = (
|
|
536
|
+
torch.tensor(rboxes, device=corners.device, dtype=corners.dtype)
|
|
537
|
+
if is_torch
|
|
538
|
+
else np.asarray(rboxes, dtype=points.dtype)
|
|
539
|
+
)
|
|
531
540
|
return rboxes
|
|
532
541
|
|
|
533
542
|
|
|
@@ -546,7 +555,7 @@ def xywhr2xyxyxyxy(center):
|
|
|
546
555
|
cos, sin = (np.cos, np.sin) if is_numpy else (torch.cos, torch.sin)
|
|
547
556
|
|
|
548
557
|
ctr = center[..., :2]
|
|
549
|
-
w, h, angle = (center[..., i:i + 1] for i in range(2, 5))
|
|
558
|
+
w, h, angle = (center[..., i : i + 1] for i in range(2, 5))
|
|
550
559
|
cos_value, sin_value = cos(angle), sin(angle)
|
|
551
560
|
vec1 = [w / 2 * cos_value, w / 2 * sin_value]
|
|
552
561
|
vec2 = [-h / 2 * sin_value, h / 2 * cos_value]
|
|
@@ -607,8 +616,9 @@ def resample_segments(segments, n=1000):
|
|
|
607
616
|
s = np.concatenate((s, s[0:1, :]), axis=0)
|
|
608
617
|
x = np.linspace(0, len(s) - 1, n)
|
|
609
618
|
xp = np.arange(len(s))
|
|
610
|
-
segments[i] =
|
|
611
|
-
|
|
619
|
+
segments[i] = (
|
|
620
|
+
np.concatenate([np.interp(x, xp, s[:, i]) for i in range(2)], dtype=np.float32).reshape(2, -1).T
|
|
621
|
+
) # segment xy
|
|
612
622
|
return segments
|
|
613
623
|
|
|
614
624
|
|
|
@@ -647,7 +657,7 @@ def process_mask_upsample(protos, masks_in, bboxes, shape):
|
|
|
647
657
|
"""
|
|
648
658
|
c, mh, mw = protos.shape # CHW
|
|
649
659
|
masks = (masks_in @ protos.float().view(c, -1)).sigmoid().view(-1, mh, mw)
|
|
650
|
-
masks = F.interpolate(masks[None], shape, mode=
|
|
660
|
+
masks = F.interpolate(masks[None], shape, mode="bilinear", align_corners=False)[0] # CHW
|
|
651
661
|
masks = crop_mask(masks, bboxes) # CHW
|
|
652
662
|
return masks.gt_(0.5)
|
|
653
663
|
|
|
@@ -680,7 +690,7 @@ def process_mask(protos, masks_in, bboxes, shape, upsample=False):
|
|
|
680
690
|
|
|
681
691
|
masks = crop_mask(masks, downsampled_bboxes) # CHW
|
|
682
692
|
if upsample:
|
|
683
|
-
masks = F.interpolate(masks[None], shape, mode=
|
|
693
|
+
masks = F.interpolate(masks[None], shape, mode="bilinear", align_corners=False)[0] # CHW
|
|
684
694
|
return masks.gt_(0.5)
|
|
685
695
|
|
|
686
696
|
|
|
@@ -724,7 +734,7 @@ def scale_masks(masks, shape, padding=True):
|
|
|
724
734
|
bottom, right = (int(round(mh - pad[1] + 0.1)), int(round(mw - pad[0] + 0.1)))
|
|
725
735
|
masks = masks[..., top:bottom, left:right]
|
|
726
736
|
|
|
727
|
-
masks = F.interpolate(masks, shape, mode=
|
|
737
|
+
masks = F.interpolate(masks, shape, mode="bilinear", align_corners=False) # NCHW
|
|
728
738
|
return masks
|
|
729
739
|
|
|
730
740
|
|
|
@@ -763,7 +773,7 @@ def scale_coords(img1_shape, coords, img0_shape, ratio_pad=None, normalize=False
|
|
|
763
773
|
return coords
|
|
764
774
|
|
|
765
775
|
|
|
766
|
-
def masks2segments(masks, strategy=
|
|
776
|
+
def masks2segments(masks, strategy="largest"):
|
|
767
777
|
"""
|
|
768
778
|
It takes a list of masks(n,h,w) and returns a list of segments(n,xy)
|
|
769
779
|
|
|
@@ -775,16 +785,16 @@ def masks2segments(masks, strategy='largest'):
|
|
|
775
785
|
segments (List): list of segment masks
|
|
776
786
|
"""
|
|
777
787
|
segments = []
|
|
778
|
-
for x in masks.int().cpu().numpy().astype(
|
|
788
|
+
for x in masks.int().cpu().numpy().astype("uint8"):
|
|
779
789
|
c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
|
|
780
790
|
if c:
|
|
781
|
-
if strategy ==
|
|
791
|
+
if strategy == "concat": # concatenate all segments
|
|
782
792
|
c = np.concatenate([x.reshape(-1, 2) for x in c])
|
|
783
|
-
elif strategy ==
|
|
793
|
+
elif strategy == "largest": # select largest segment
|
|
784
794
|
c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
|
|
785
795
|
else:
|
|
786
796
|
c = np.zeros((0, 2)) # no segments found
|
|
787
|
-
segments.append(c.astype(
|
|
797
|
+
segments.append(c.astype("float32"))
|
|
788
798
|
return segments
|
|
789
799
|
|
|
790
800
|
|
|
@@ -811,4 +821,4 @@ def clean_str(s):
|
|
|
811
821
|
Returns:
|
|
812
822
|
(str): a string with special characters replaced by an underscore _
|
|
813
823
|
"""
|
|
814
|
-
return re.sub(pattern=
|
|
824
|
+
return re.sub(pattern="[|@#!¡·$€%&()=?¿^*;:,¨´><+]", repl="_", string=s)
|
ultralytics/utils/patches.py
CHANGED
|
@@ -52,7 +52,7 @@ def imshow(winname: str, mat: np.ndarray):
|
|
|
52
52
|
winname (str): Name of the window.
|
|
53
53
|
mat (np.ndarray): Image to be shown.
|
|
54
54
|
"""
|
|
55
|
-
_imshow(winname.encode(
|
|
55
|
+
_imshow(winname.encode("unicode_escape").decode(), mat)
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
# PyTorch functions ----------------------------------------------------------------------------------------------------
|
|
@@ -72,6 +72,6 @@ def torch_save(*args, **kwargs):
|
|
|
72
72
|
except ImportError:
|
|
73
73
|
import pickle
|
|
74
74
|
|
|
75
|
-
if
|
|
76
|
-
kwargs[
|
|
75
|
+
if "pickle_module" not in kwargs:
|
|
76
|
+
kwargs["pickle_module"] = pickle # noqa
|
|
77
77
|
return _torch_save(*args, **kwargs)
|