dgenerate-ultralytics-headless 8.3.137__py3-none-any.whl → 8.3.224__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.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/METADATA +41 -34
- dgenerate_ultralytics_headless-8.3.224.dist-info/RECORD +285 -0
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/WHEEL +1 -1
- tests/__init__.py +7 -6
- tests/conftest.py +15 -39
- tests/test_cli.py +17 -17
- tests/test_cuda.py +17 -8
- tests/test_engine.py +36 -10
- tests/test_exports.py +98 -37
- tests/test_integrations.py +12 -15
- tests/test_python.py +126 -82
- tests/test_solutions.py +319 -135
- ultralytics/__init__.py +27 -9
- ultralytics/cfg/__init__.py +83 -87
- ultralytics/cfg/datasets/Argoverse.yaml +4 -4
- ultralytics/cfg/datasets/DOTAv1.5.yaml +2 -2
- ultralytics/cfg/datasets/DOTAv1.yaml +2 -2
- ultralytics/cfg/datasets/GlobalWheat2020.yaml +2 -2
- ultralytics/cfg/datasets/HomeObjects-3K.yaml +4 -5
- ultralytics/cfg/datasets/ImageNet.yaml +3 -3
- ultralytics/cfg/datasets/Objects365.yaml +24 -20
- ultralytics/cfg/datasets/SKU-110K.yaml +9 -9
- ultralytics/cfg/datasets/VOC.yaml +10 -13
- ultralytics/cfg/datasets/VisDrone.yaml +43 -33
- ultralytics/cfg/datasets/african-wildlife.yaml +5 -5
- ultralytics/cfg/datasets/brain-tumor.yaml +4 -5
- ultralytics/cfg/datasets/carparts-seg.yaml +5 -5
- ultralytics/cfg/datasets/coco-pose.yaml +26 -4
- ultralytics/cfg/datasets/coco.yaml +4 -4
- ultralytics/cfg/datasets/coco128-seg.yaml +2 -2
- ultralytics/cfg/datasets/coco128.yaml +2 -2
- ultralytics/cfg/datasets/coco8-grayscale.yaml +103 -0
- ultralytics/cfg/datasets/coco8-multispectral.yaml +2 -2
- ultralytics/cfg/datasets/coco8-pose.yaml +23 -2
- ultralytics/cfg/datasets/coco8-seg.yaml +2 -2
- ultralytics/cfg/datasets/coco8.yaml +2 -2
- ultralytics/cfg/datasets/construction-ppe.yaml +32 -0
- ultralytics/cfg/datasets/crack-seg.yaml +5 -5
- ultralytics/cfg/datasets/dog-pose.yaml +32 -4
- ultralytics/cfg/datasets/dota8-multispectral.yaml +2 -2
- ultralytics/cfg/datasets/dota8.yaml +2 -2
- ultralytics/cfg/datasets/hand-keypoints.yaml +29 -4
- ultralytics/cfg/datasets/lvis.yaml +9 -9
- ultralytics/cfg/datasets/medical-pills.yaml +4 -5
- ultralytics/cfg/datasets/open-images-v7.yaml +7 -10
- ultralytics/cfg/datasets/package-seg.yaml +5 -5
- ultralytics/cfg/datasets/signature.yaml +4 -4
- ultralytics/cfg/datasets/tiger-pose.yaml +20 -4
- ultralytics/cfg/datasets/xView.yaml +5 -5
- ultralytics/cfg/default.yaml +96 -93
- ultralytics/cfg/trackers/botsort.yaml +16 -17
- ultralytics/cfg/trackers/bytetrack.yaml +9 -11
- ultralytics/data/__init__.py +4 -4
- ultralytics/data/annotator.py +12 -12
- ultralytics/data/augment.py +531 -564
- ultralytics/data/base.py +76 -81
- ultralytics/data/build.py +206 -42
- ultralytics/data/converter.py +179 -78
- ultralytics/data/dataset.py +121 -121
- ultralytics/data/loaders.py +114 -91
- ultralytics/data/split.py +28 -15
- ultralytics/data/split_dota.py +67 -48
- ultralytics/data/utils.py +110 -89
- ultralytics/engine/exporter.py +422 -460
- ultralytics/engine/model.py +224 -252
- ultralytics/engine/predictor.py +94 -89
- ultralytics/engine/results.py +345 -595
- ultralytics/engine/trainer.py +231 -134
- ultralytics/engine/tuner.py +279 -73
- ultralytics/engine/validator.py +53 -46
- ultralytics/hub/__init__.py +26 -28
- ultralytics/hub/auth.py +30 -16
- ultralytics/hub/google/__init__.py +34 -36
- ultralytics/hub/session.py +53 -77
- ultralytics/hub/utils.py +23 -109
- ultralytics/models/__init__.py +1 -1
- ultralytics/models/fastsam/__init__.py +1 -1
- ultralytics/models/fastsam/model.py +36 -18
- ultralytics/models/fastsam/predict.py +33 -44
- ultralytics/models/fastsam/utils.py +4 -5
- ultralytics/models/fastsam/val.py +12 -14
- ultralytics/models/nas/__init__.py +1 -1
- ultralytics/models/nas/model.py +16 -20
- ultralytics/models/nas/predict.py +12 -14
- ultralytics/models/nas/val.py +4 -5
- ultralytics/models/rtdetr/__init__.py +1 -1
- ultralytics/models/rtdetr/model.py +9 -9
- ultralytics/models/rtdetr/predict.py +22 -17
- ultralytics/models/rtdetr/train.py +20 -16
- ultralytics/models/rtdetr/val.py +79 -59
- ultralytics/models/sam/__init__.py +8 -2
- ultralytics/models/sam/amg.py +53 -38
- ultralytics/models/sam/build.py +29 -31
- ultralytics/models/sam/model.py +33 -38
- ultralytics/models/sam/modules/blocks.py +159 -182
- ultralytics/models/sam/modules/decoders.py +38 -47
- ultralytics/models/sam/modules/encoders.py +114 -133
- ultralytics/models/sam/modules/memory_attention.py +38 -31
- ultralytics/models/sam/modules/sam.py +114 -93
- ultralytics/models/sam/modules/tiny_encoder.py +268 -291
- ultralytics/models/sam/modules/transformer.py +59 -66
- ultralytics/models/sam/modules/utils.py +55 -72
- ultralytics/models/sam/predict.py +745 -341
- ultralytics/models/utils/loss.py +118 -107
- ultralytics/models/utils/ops.py +118 -71
- ultralytics/models/yolo/__init__.py +1 -1
- ultralytics/models/yolo/classify/predict.py +28 -26
- ultralytics/models/yolo/classify/train.py +50 -81
- ultralytics/models/yolo/classify/val.py +68 -61
- ultralytics/models/yolo/detect/predict.py +12 -15
- ultralytics/models/yolo/detect/train.py +56 -46
- ultralytics/models/yolo/detect/val.py +279 -223
- ultralytics/models/yolo/model.py +167 -86
- ultralytics/models/yolo/obb/predict.py +7 -11
- ultralytics/models/yolo/obb/train.py +23 -25
- ultralytics/models/yolo/obb/val.py +107 -99
- ultralytics/models/yolo/pose/__init__.py +1 -1
- ultralytics/models/yolo/pose/predict.py +12 -14
- ultralytics/models/yolo/pose/train.py +31 -69
- ultralytics/models/yolo/pose/val.py +119 -254
- ultralytics/models/yolo/segment/predict.py +21 -25
- ultralytics/models/yolo/segment/train.py +12 -66
- ultralytics/models/yolo/segment/val.py +126 -305
- ultralytics/models/yolo/world/train.py +53 -45
- ultralytics/models/yolo/world/train_world.py +51 -32
- ultralytics/models/yolo/yoloe/__init__.py +7 -7
- ultralytics/models/yolo/yoloe/predict.py +30 -37
- ultralytics/models/yolo/yoloe/train.py +89 -71
- ultralytics/models/yolo/yoloe/train_seg.py +15 -17
- ultralytics/models/yolo/yoloe/val.py +56 -41
- ultralytics/nn/__init__.py +9 -11
- ultralytics/nn/autobackend.py +179 -107
- ultralytics/nn/modules/__init__.py +67 -67
- ultralytics/nn/modules/activation.py +8 -7
- ultralytics/nn/modules/block.py +302 -323
- ultralytics/nn/modules/conv.py +61 -104
- ultralytics/nn/modules/head.py +488 -186
- ultralytics/nn/modules/transformer.py +183 -123
- ultralytics/nn/modules/utils.py +15 -20
- ultralytics/nn/tasks.py +327 -203
- ultralytics/nn/text_model.py +81 -65
- ultralytics/py.typed +1 -0
- ultralytics/solutions/__init__.py +12 -12
- ultralytics/solutions/ai_gym.py +19 -27
- ultralytics/solutions/analytics.py +36 -26
- ultralytics/solutions/config.py +29 -28
- ultralytics/solutions/distance_calculation.py +23 -24
- ultralytics/solutions/heatmap.py +17 -19
- ultralytics/solutions/instance_segmentation.py +21 -19
- ultralytics/solutions/object_blurrer.py +16 -17
- ultralytics/solutions/object_counter.py +48 -53
- ultralytics/solutions/object_cropper.py +22 -16
- ultralytics/solutions/parking_management.py +61 -58
- ultralytics/solutions/queue_management.py +19 -19
- ultralytics/solutions/region_counter.py +63 -50
- ultralytics/solutions/security_alarm.py +22 -25
- ultralytics/solutions/similarity_search.py +107 -60
- ultralytics/solutions/solutions.py +343 -262
- ultralytics/solutions/speed_estimation.py +35 -31
- ultralytics/solutions/streamlit_inference.py +104 -40
- ultralytics/solutions/templates/similarity-search.html +31 -24
- ultralytics/solutions/trackzone.py +24 -24
- ultralytics/solutions/vision_eye.py +11 -12
- ultralytics/trackers/__init__.py +1 -1
- ultralytics/trackers/basetrack.py +18 -27
- ultralytics/trackers/bot_sort.py +48 -39
- ultralytics/trackers/byte_tracker.py +94 -94
- ultralytics/trackers/track.py +7 -16
- ultralytics/trackers/utils/gmc.py +37 -69
- ultralytics/trackers/utils/kalman_filter.py +68 -76
- ultralytics/trackers/utils/matching.py +13 -17
- ultralytics/utils/__init__.py +251 -275
- ultralytics/utils/autobatch.py +19 -7
- ultralytics/utils/autodevice.py +68 -38
- ultralytics/utils/benchmarks.py +169 -130
- ultralytics/utils/callbacks/base.py +12 -13
- ultralytics/utils/callbacks/clearml.py +14 -15
- ultralytics/utils/callbacks/comet.py +139 -66
- ultralytics/utils/callbacks/dvc.py +19 -27
- ultralytics/utils/callbacks/hub.py +8 -6
- ultralytics/utils/callbacks/mlflow.py +6 -10
- ultralytics/utils/callbacks/neptune.py +11 -19
- ultralytics/utils/callbacks/platform.py +73 -0
- ultralytics/utils/callbacks/raytune.py +3 -4
- ultralytics/utils/callbacks/tensorboard.py +9 -12
- ultralytics/utils/callbacks/wb.py +33 -30
- ultralytics/utils/checks.py +163 -114
- ultralytics/utils/cpu.py +89 -0
- ultralytics/utils/dist.py +24 -20
- ultralytics/utils/downloads.py +176 -146
- ultralytics/utils/errors.py +11 -13
- ultralytics/utils/events.py +113 -0
- ultralytics/utils/export/__init__.py +7 -0
- ultralytics/utils/{export.py → export/engine.py} +81 -63
- ultralytics/utils/export/imx.py +294 -0
- ultralytics/utils/export/tensorflow.py +217 -0
- ultralytics/utils/files.py +33 -36
- ultralytics/utils/git.py +137 -0
- ultralytics/utils/instance.py +105 -120
- ultralytics/utils/logger.py +404 -0
- ultralytics/utils/loss.py +99 -61
- ultralytics/utils/metrics.py +649 -478
- ultralytics/utils/nms.py +337 -0
- ultralytics/utils/ops.py +263 -451
- ultralytics/utils/patches.py +70 -31
- ultralytics/utils/plotting.py +253 -223
- ultralytics/utils/tal.py +48 -61
- ultralytics/utils/torch_utils.py +244 -251
- ultralytics/utils/tqdm.py +438 -0
- ultralytics/utils/triton.py +22 -23
- ultralytics/utils/tuner.py +11 -10
- dgenerate_ultralytics_headless-8.3.137.dist-info/RECORD +0 -272
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/entry_points.txt +0 -0
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/licenses/LICENSE +0 -0
- {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/top_level.txt +0 -0
ultralytics/utils/instance.py
CHANGED
|
@@ -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
|
from collections import abc
|
|
4
6
|
from itertools import repeat
|
|
5
7
|
from numbers import Number
|
|
6
|
-
from typing import List
|
|
7
8
|
|
|
8
9
|
import numpy as np
|
|
9
10
|
|
|
@@ -11,7 +12,7 @@ from .ops import ltwh2xywh, ltwh2xyxy, resample_segments, xywh2ltwh, xywh2xyxy,
|
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
def _ntuple(n):
|
|
14
|
-
"""
|
|
15
|
+
"""Create a function that converts input to n-tuple by repeating singleton values."""
|
|
15
16
|
|
|
16
17
|
def parse(x):
|
|
17
18
|
"""Parse input to return n-tuple by repeating singleton values n times."""
|
|
@@ -32,23 +33,34 @@ __all__ = ("Bboxes", "Instances") # tuple or list
|
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
class Bboxes:
|
|
35
|
-
"""
|
|
36
|
-
A class for handling bounding boxes.
|
|
36
|
+
"""A class for handling bounding boxes in multiple formats.
|
|
37
37
|
|
|
38
|
-
The class supports various bounding box formats like 'xyxy', 'xywh', and 'ltwh'
|
|
39
|
-
Bounding box data should be provided
|
|
38
|
+
The class supports various bounding box formats like 'xyxy', 'xywh', and 'ltwh' and provides methods for format
|
|
39
|
+
conversion, scaling, and area calculation. Bounding box data should be provided as numpy arrays.
|
|
40
40
|
|
|
41
41
|
Attributes:
|
|
42
42
|
bboxes (np.ndarray): The bounding boxes stored in a 2D numpy array with shape (N, 4).
|
|
43
43
|
format (str): The format of the bounding boxes ('xyxy', 'xywh', or 'ltwh').
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
Methods:
|
|
46
|
+
convert: Convert bounding box format from one type to another.
|
|
47
|
+
areas: Calculate the area of bounding boxes.
|
|
48
|
+
mul: Multiply bounding box coordinates by scale factor(s).
|
|
49
|
+
add: Add offset to bounding box coordinates.
|
|
50
|
+
concatenate: Concatenate multiple Bboxes objects.
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
Create bounding boxes in YOLO format
|
|
54
|
+
>>> bboxes = Bboxes(np.array([[100, 50, 150, 100]]), format="xywh")
|
|
55
|
+
>>> bboxes.convert("xyxy")
|
|
56
|
+
>>> print(bboxes.areas())
|
|
57
|
+
|
|
58
|
+
Notes:
|
|
46
59
|
This class does not handle normalization or denormalization of bounding boxes.
|
|
47
60
|
"""
|
|
48
61
|
|
|
49
|
-
def __init__(self, bboxes, format="xyxy") -> None:
|
|
50
|
-
"""
|
|
51
|
-
Initialize the Bboxes class with bounding box data in a specified format.
|
|
62
|
+
def __init__(self, bboxes: np.ndarray, format: str = "xyxy") -> None:
|
|
63
|
+
"""Initialize the Bboxes class with bounding box data in a specified format.
|
|
52
64
|
|
|
53
65
|
Args:
|
|
54
66
|
bboxes (np.ndarray): Array of bounding boxes with shape (N, 4) or (4,).
|
|
@@ -60,11 +72,9 @@ class Bboxes:
|
|
|
60
72
|
assert bboxes.shape[1] == 4
|
|
61
73
|
self.bboxes = bboxes
|
|
62
74
|
self.format = format
|
|
63
|
-
# self.normalized = normalized
|
|
64
75
|
|
|
65
|
-
def convert(self, format):
|
|
66
|
-
"""
|
|
67
|
-
Convert bounding box format from one type to another.
|
|
76
|
+
def convert(self, format: str) -> None:
|
|
77
|
+
"""Convert bounding box format from one type to another.
|
|
68
78
|
|
|
69
79
|
Args:
|
|
70
80
|
format (str): Target format for conversion, one of 'xyxy', 'xywh', or 'ltwh'.
|
|
@@ -81,37 +91,20 @@ class Bboxes:
|
|
|
81
91
|
self.bboxes = func(self.bboxes)
|
|
82
92
|
self.format = format
|
|
83
93
|
|
|
84
|
-
def areas(self):
|
|
85
|
-
"""
|
|
94
|
+
def areas(self) -> np.ndarray:
|
|
95
|
+
"""Calculate the area of bounding boxes."""
|
|
86
96
|
return (
|
|
87
97
|
(self.bboxes[:, 2] - self.bboxes[:, 0]) * (self.bboxes[:, 3] - self.bboxes[:, 1]) # format xyxy
|
|
88
98
|
if self.format == "xyxy"
|
|
89
99
|
else self.bboxes[:, 3] * self.bboxes[:, 2] # format xywh or ltwh
|
|
90
100
|
)
|
|
91
101
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
# return
|
|
95
|
-
# assert (self.bboxes <= 1.0).all()
|
|
96
|
-
# self.bboxes[:, 0::2] *= w
|
|
97
|
-
# self.bboxes[:, 1::2] *= h
|
|
98
|
-
# self.normalized = False
|
|
99
|
-
#
|
|
100
|
-
# def normalize(self, w, h):
|
|
101
|
-
# if self.normalized:
|
|
102
|
-
# return
|
|
103
|
-
# assert (self.bboxes > 1.0).any()
|
|
104
|
-
# self.bboxes[:, 0::2] /= w
|
|
105
|
-
# self.bboxes[:, 1::2] /= h
|
|
106
|
-
# self.normalized = True
|
|
107
|
-
|
|
108
|
-
def mul(self, scale):
|
|
109
|
-
"""
|
|
110
|
-
Multiply bounding box coordinates by scale factor(s).
|
|
102
|
+
def mul(self, scale: int | tuple | list) -> None:
|
|
103
|
+
"""Multiply bounding box coordinates by scale factor(s).
|
|
111
104
|
|
|
112
105
|
Args:
|
|
113
|
-
scale (int | tuple | list): Scale factor(s) for four coordinates.
|
|
114
|
-
|
|
106
|
+
scale (int | tuple | list): Scale factor(s) for four coordinates. If int, the same scale is applied to all
|
|
107
|
+
coordinates.
|
|
115
108
|
"""
|
|
116
109
|
if isinstance(scale, Number):
|
|
117
110
|
scale = to_4tuple(scale)
|
|
@@ -122,13 +115,12 @@ class Bboxes:
|
|
|
122
115
|
self.bboxes[:, 2] *= scale[2]
|
|
123
116
|
self.bboxes[:, 3] *= scale[3]
|
|
124
117
|
|
|
125
|
-
def add(self, offset):
|
|
126
|
-
"""
|
|
127
|
-
Add offset to bounding box coordinates.
|
|
118
|
+
def add(self, offset: int | tuple | list) -> None:
|
|
119
|
+
"""Add offset to bounding box coordinates.
|
|
128
120
|
|
|
129
121
|
Args:
|
|
130
|
-
offset (int | tuple | list): Offset(s) for four coordinates.
|
|
131
|
-
|
|
122
|
+
offset (int | tuple | list): Offset(s) for four coordinates. If int, the same offset is applied to all
|
|
123
|
+
coordinates.
|
|
132
124
|
"""
|
|
133
125
|
if isinstance(offset, Number):
|
|
134
126
|
offset = to_4tuple(offset)
|
|
@@ -139,23 +131,22 @@ class Bboxes:
|
|
|
139
131
|
self.bboxes[:, 2] += offset[2]
|
|
140
132
|
self.bboxes[:, 3] += offset[3]
|
|
141
133
|
|
|
142
|
-
def __len__(self):
|
|
143
|
-
"""Return the number of boxes."""
|
|
134
|
+
def __len__(self) -> int:
|
|
135
|
+
"""Return the number of bounding boxes."""
|
|
144
136
|
return len(self.bboxes)
|
|
145
137
|
|
|
146
138
|
@classmethod
|
|
147
|
-
def concatenate(cls, boxes_list:
|
|
148
|
-
"""
|
|
149
|
-
Concatenate a list of Bboxes objects into a single Bboxes object.
|
|
139
|
+
def concatenate(cls, boxes_list: list[Bboxes], axis: int = 0) -> Bboxes:
|
|
140
|
+
"""Concatenate a list of Bboxes objects into a single Bboxes object.
|
|
150
141
|
|
|
151
142
|
Args:
|
|
152
|
-
boxes_list (
|
|
143
|
+
boxes_list (list[Bboxes]): A list of Bboxes objects to concatenate.
|
|
153
144
|
axis (int, optional): The axis along which to concatenate the bounding boxes.
|
|
154
145
|
|
|
155
146
|
Returns:
|
|
156
147
|
(Bboxes): A new Bboxes object containing the concatenated bounding boxes.
|
|
157
148
|
|
|
158
|
-
|
|
149
|
+
Notes:
|
|
159
150
|
The input should be a list or tuple of Bboxes objects.
|
|
160
151
|
"""
|
|
161
152
|
assert isinstance(boxes_list, (list, tuple))
|
|
@@ -167,23 +158,18 @@ class Bboxes:
|
|
|
167
158
|
return boxes_list[0]
|
|
168
159
|
return cls(np.concatenate([b.bboxes for b in boxes_list], axis=axis))
|
|
169
160
|
|
|
170
|
-
def __getitem__(self, index) ->
|
|
171
|
-
"""
|
|
172
|
-
Retrieve a specific bounding box or a set of bounding boxes using indexing.
|
|
161
|
+
def __getitem__(self, index: int | np.ndarray | slice) -> Bboxes:
|
|
162
|
+
"""Retrieve a specific bounding box or a set of bounding boxes using indexing.
|
|
173
163
|
|
|
174
164
|
Args:
|
|
175
|
-
index (int | slice | np.ndarray): The index, slice, or boolean array to select
|
|
176
|
-
the desired bounding boxes.
|
|
165
|
+
index (int | slice | np.ndarray): The index, slice, or boolean array to select the desired bounding boxes.
|
|
177
166
|
|
|
178
167
|
Returns:
|
|
179
168
|
(Bboxes): A new Bboxes object containing the selected bounding boxes.
|
|
180
169
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
Note:
|
|
185
|
-
When using boolean indexing, make sure to provide a boolean array with the same
|
|
186
|
-
length as the number of bounding boxes.
|
|
170
|
+
Notes:
|
|
171
|
+
When using boolean indexing, make sure to provide a boolean array with the same length as the number of
|
|
172
|
+
bounding boxes.
|
|
187
173
|
"""
|
|
188
174
|
if isinstance(index, int):
|
|
189
175
|
return Bboxes(self.bboxes[index].reshape(1, -1))
|
|
@@ -193,8 +179,11 @@ class Bboxes:
|
|
|
193
179
|
|
|
194
180
|
|
|
195
181
|
class Instances:
|
|
196
|
-
"""
|
|
197
|
-
|
|
182
|
+
"""Container for bounding boxes, segments, and keypoints of detected objects in an image.
|
|
183
|
+
|
|
184
|
+
This class provides a unified interface for handling different types of object annotations including bounding boxes,
|
|
185
|
+
segmentation masks, and keypoints. It supports various operations like scaling, normalization, clipping, and format
|
|
186
|
+
conversion.
|
|
198
187
|
|
|
199
188
|
Attributes:
|
|
200
189
|
_bboxes (Bboxes): Internal object for handling bounding box operations.
|
|
@@ -216,6 +205,7 @@ class Instances:
|
|
|
216
205
|
concatenate: Concatenate multiple Instances objects.
|
|
217
206
|
|
|
218
207
|
Examples:
|
|
208
|
+
Create instances with bounding boxes and segments
|
|
219
209
|
>>> instances = Instances(
|
|
220
210
|
... bboxes=np.array([[10, 10, 30, 30], [20, 20, 40, 40]]),
|
|
221
211
|
... segments=[np.array([[5, 5], [10, 10]]), np.array([[15, 15], [20, 20]])],
|
|
@@ -223,25 +213,30 @@ class Instances:
|
|
|
223
213
|
... )
|
|
224
214
|
"""
|
|
225
215
|
|
|
226
|
-
def __init__(
|
|
227
|
-
|
|
228
|
-
|
|
216
|
+
def __init__(
|
|
217
|
+
self,
|
|
218
|
+
bboxes: np.ndarray,
|
|
219
|
+
segments: np.ndarray = None,
|
|
220
|
+
keypoints: np.ndarray = None,
|
|
221
|
+
bbox_format: str = "xywh",
|
|
222
|
+
normalized: bool = True,
|
|
223
|
+
) -> None:
|
|
224
|
+
"""Initialize the Instances object with bounding boxes, segments, and keypoints.
|
|
229
225
|
|
|
230
226
|
Args:
|
|
231
|
-
bboxes (np.ndarray): Bounding boxes
|
|
232
|
-
segments (
|
|
233
|
-
keypoints (np.ndarray, optional): Keypoints
|
|
234
|
-
bbox_format (str
|
|
235
|
-
normalized (bool
|
|
227
|
+
bboxes (np.ndarray): Bounding boxes with shape (N, 4).
|
|
228
|
+
segments (np.ndarray, optional): Segmentation masks.
|
|
229
|
+
keypoints (np.ndarray, optional): Keypoints with shape (N, 17, 3) in format (x, y, visible).
|
|
230
|
+
bbox_format (str): Format of bboxes.
|
|
231
|
+
normalized (bool): Whether the coordinates are normalized.
|
|
236
232
|
"""
|
|
237
233
|
self._bboxes = Bboxes(bboxes=bboxes, format=bbox_format)
|
|
238
234
|
self.keypoints = keypoints
|
|
239
235
|
self.normalized = normalized
|
|
240
236
|
self.segments = segments
|
|
241
237
|
|
|
242
|
-
def convert_bbox(self, format):
|
|
243
|
-
"""
|
|
244
|
-
Convert bounding box format.
|
|
238
|
+
def convert_bbox(self, format: str) -> None:
|
|
239
|
+
"""Convert bounding box format.
|
|
245
240
|
|
|
246
241
|
Args:
|
|
247
242
|
format (str): Target format for conversion, one of 'xyxy', 'xywh', or 'ltwh'.
|
|
@@ -249,13 +244,12 @@ class Instances:
|
|
|
249
244
|
self._bboxes.convert(format=format)
|
|
250
245
|
|
|
251
246
|
@property
|
|
252
|
-
def bbox_areas(self):
|
|
247
|
+
def bbox_areas(self) -> np.ndarray:
|
|
253
248
|
"""Calculate the area of bounding boxes."""
|
|
254
249
|
return self._bboxes.areas()
|
|
255
250
|
|
|
256
|
-
def scale(self, scale_w, scale_h, bbox_only=False):
|
|
257
|
-
"""
|
|
258
|
-
Scale coordinates by given factors.
|
|
251
|
+
def scale(self, scale_w: float, scale_h: float, bbox_only: bool = False):
|
|
252
|
+
"""Scale coordinates by given factors.
|
|
259
253
|
|
|
260
254
|
Args:
|
|
261
255
|
scale_w (float): Scale factor for width.
|
|
@@ -271,9 +265,8 @@ class Instances:
|
|
|
271
265
|
self.keypoints[..., 0] *= scale_w
|
|
272
266
|
self.keypoints[..., 1] *= scale_h
|
|
273
267
|
|
|
274
|
-
def denormalize(self, w, h):
|
|
275
|
-
"""
|
|
276
|
-
Convert normalized coordinates to absolute coordinates.
|
|
268
|
+
def denormalize(self, w: int, h: int) -> None:
|
|
269
|
+
"""Convert normalized coordinates to absolute coordinates.
|
|
277
270
|
|
|
278
271
|
Args:
|
|
279
272
|
w (int): Image width.
|
|
@@ -289,9 +282,8 @@ class Instances:
|
|
|
289
282
|
self.keypoints[..., 1] *= h
|
|
290
283
|
self.normalized = False
|
|
291
284
|
|
|
292
|
-
def normalize(self, w, h):
|
|
293
|
-
"""
|
|
294
|
-
Convert absolute coordinates to normalized coordinates.
|
|
285
|
+
def normalize(self, w: int, h: int) -> None:
|
|
286
|
+
"""Convert absolute coordinates to normalized coordinates.
|
|
295
287
|
|
|
296
288
|
Args:
|
|
297
289
|
w (int): Image width.
|
|
@@ -307,9 +299,8 @@ class Instances:
|
|
|
307
299
|
self.keypoints[..., 1] /= h
|
|
308
300
|
self.normalized = True
|
|
309
301
|
|
|
310
|
-
def add_padding(self, padw, padh):
|
|
311
|
-
"""
|
|
312
|
-
Add padding to coordinates.
|
|
302
|
+
def add_padding(self, padw: int, padh: int) -> None:
|
|
303
|
+
"""Add padding to coordinates.
|
|
313
304
|
|
|
314
305
|
Args:
|
|
315
306
|
padw (int): Padding width.
|
|
@@ -323,9 +314,8 @@ class Instances:
|
|
|
323
314
|
self.keypoints[..., 0] += padw
|
|
324
315
|
self.keypoints[..., 1] += padh
|
|
325
316
|
|
|
326
|
-
def __getitem__(self, index) ->
|
|
327
|
-
"""
|
|
328
|
-
Retrieve a specific instance or a set of instances using indexing.
|
|
317
|
+
def __getitem__(self, index: int | np.ndarray | slice) -> Instances:
|
|
318
|
+
"""Retrieve a specific instance or a set of instances using indexing.
|
|
329
319
|
|
|
330
320
|
Args:
|
|
331
321
|
index (int | slice | np.ndarray): The index, slice, or boolean array to select the desired instances.
|
|
@@ -333,9 +323,9 @@ class Instances:
|
|
|
333
323
|
Returns:
|
|
334
324
|
(Instances): A new Instances object containing the selected boxes, segments, and keypoints if present.
|
|
335
325
|
|
|
336
|
-
|
|
337
|
-
When using boolean indexing, make sure to provide a boolean array with the same
|
|
338
|
-
|
|
326
|
+
Notes:
|
|
327
|
+
When using boolean indexing, make sure to provide a boolean array with the same length as the number of
|
|
328
|
+
instances.
|
|
339
329
|
"""
|
|
340
330
|
segments = self.segments[index] if len(self.segments) else self.segments
|
|
341
331
|
keypoints = self.keypoints[index] if self.keypoints is not None else None
|
|
@@ -349,9 +339,8 @@ class Instances:
|
|
|
349
339
|
normalized=self.normalized,
|
|
350
340
|
)
|
|
351
341
|
|
|
352
|
-
def flipud(self, h):
|
|
353
|
-
"""
|
|
354
|
-
Flip coordinates vertically.
|
|
342
|
+
def flipud(self, h: int) -> None:
|
|
343
|
+
"""Flip coordinates vertically.
|
|
355
344
|
|
|
356
345
|
Args:
|
|
357
346
|
h (int): Image height.
|
|
@@ -367,9 +356,8 @@ class Instances:
|
|
|
367
356
|
if self.keypoints is not None:
|
|
368
357
|
self.keypoints[..., 1] = h - self.keypoints[..., 1]
|
|
369
358
|
|
|
370
|
-
def fliplr(self, w):
|
|
371
|
-
"""
|
|
372
|
-
Flip coordinates horizontally.
|
|
359
|
+
def fliplr(self, w: int) -> None:
|
|
360
|
+
"""Flip coordinates horizontally.
|
|
373
361
|
|
|
374
362
|
Args:
|
|
375
363
|
w (int): Image width.
|
|
@@ -385,9 +373,8 @@ class Instances:
|
|
|
385
373
|
if self.keypoints is not None:
|
|
386
374
|
self.keypoints[..., 0] = w - self.keypoints[..., 0]
|
|
387
375
|
|
|
388
|
-
def clip(self, w, h):
|
|
389
|
-
"""
|
|
390
|
-
Clip coordinates to stay within image boundaries.
|
|
376
|
+
def clip(self, w: int, h: int) -> None:
|
|
377
|
+
"""Clip coordinates to stay within image boundaries.
|
|
391
378
|
|
|
392
379
|
Args:
|
|
393
380
|
w (int): Image width.
|
|
@@ -409,10 +396,11 @@ class Instances:
|
|
|
409
396
|
| (self.keypoints[..., 1] < 0)
|
|
410
397
|
| (self.keypoints[..., 1] > h)
|
|
411
398
|
] = 0.0
|
|
399
|
+
self.keypoints[..., 0] = self.keypoints[..., 0].clip(0, w)
|
|
400
|
+
self.keypoints[..., 1] = self.keypoints[..., 1].clip(0, h)
|
|
412
401
|
|
|
413
|
-
def remove_zero_area_boxes(self):
|
|
414
|
-
"""
|
|
415
|
-
Remove zero-area boxes, i.e. after clipping some boxes may have zero width or height.
|
|
402
|
+
def remove_zero_area_boxes(self) -> np.ndarray:
|
|
403
|
+
"""Remove zero-area boxes, i.e. after clipping some boxes may have zero width or height.
|
|
416
404
|
|
|
417
405
|
Returns:
|
|
418
406
|
(np.ndarray): Boolean array indicating which boxes were kept.
|
|
@@ -426,9 +414,8 @@ class Instances:
|
|
|
426
414
|
self.keypoints = self.keypoints[good]
|
|
427
415
|
return good
|
|
428
416
|
|
|
429
|
-
def update(self, bboxes, segments=None, keypoints=None):
|
|
430
|
-
"""
|
|
431
|
-
Update instance variables.
|
|
417
|
+
def update(self, bboxes: np.ndarray, segments: np.ndarray = None, keypoints: np.ndarray = None):
|
|
418
|
+
"""Update instance variables.
|
|
432
419
|
|
|
433
420
|
Args:
|
|
434
421
|
bboxes (np.ndarray): New bounding boxes.
|
|
@@ -441,27 +428,25 @@ class Instances:
|
|
|
441
428
|
if keypoints is not None:
|
|
442
429
|
self.keypoints = keypoints
|
|
443
430
|
|
|
444
|
-
def __len__(self):
|
|
445
|
-
"""Return the
|
|
431
|
+
def __len__(self) -> int:
|
|
432
|
+
"""Return the number of instances."""
|
|
446
433
|
return len(self.bboxes)
|
|
447
434
|
|
|
448
435
|
@classmethod
|
|
449
|
-
def concatenate(cls, instances_list:
|
|
450
|
-
"""
|
|
451
|
-
Concatenate a list of Instances objects into a single Instances object.
|
|
436
|
+
def concatenate(cls, instances_list: list[Instances], axis=0) -> Instances:
|
|
437
|
+
"""Concatenate a list of Instances objects into a single Instances object.
|
|
452
438
|
|
|
453
439
|
Args:
|
|
454
|
-
instances_list (
|
|
440
|
+
instances_list (list[Instances]): A list of Instances objects to concatenate.
|
|
455
441
|
axis (int, optional): The axis along which the arrays will be concatenated.
|
|
456
442
|
|
|
457
443
|
Returns:
|
|
458
|
-
(Instances): A new Instances object containing the concatenated bounding boxes,
|
|
459
|
-
|
|
444
|
+
(Instances): A new Instances object containing the concatenated bounding boxes, segments, and keypoints if
|
|
445
|
+
present.
|
|
460
446
|
|
|
461
|
-
|
|
462
|
-
The `Instances` objects in the list should have the same properties, such as
|
|
463
|
-
|
|
464
|
-
coordinates are normalized.
|
|
447
|
+
Notes:
|
|
448
|
+
The `Instances` objects in the list should have the same properties, such as the format of the bounding
|
|
449
|
+
boxes, whether keypoints are present, and if the coordinates are normalized.
|
|
465
450
|
"""
|
|
466
451
|
assert isinstance(instances_list, (list, tuple))
|
|
467
452
|
if not instances_list:
|
|
@@ -494,6 +479,6 @@ class Instances:
|
|
|
494
479
|
return cls(cat_boxes, cat_segments, cat_keypoints, bbox_format, normalized)
|
|
495
480
|
|
|
496
481
|
@property
|
|
497
|
-
def bboxes(self):
|
|
482
|
+
def bboxes(self) -> np.ndarray:
|
|
498
483
|
"""Return bounding boxes."""
|
|
499
484
|
return self._bboxes.bboxes
|