edgefirst-validator 4.2.1__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.
- deepview/modelpack/utils/argmax.py +16 -0
- edgefirst/validator/__init__.py +1 -0
- edgefirst/validator/__main__.py +375 -0
- edgefirst/validator/datasets/__init__.py +118 -0
- edgefirst/validator/datasets/cache.py +296 -0
- edgefirst/validator/datasets/core.py +250 -0
- edgefirst/validator/datasets/darknet.py +446 -0
- edgefirst/validator/datasets/database.py +1067 -0
- edgefirst/validator/datasets/instance/__init__.py +4 -0
- edgefirst/validator/datasets/instance/core.py +222 -0
- edgefirst/validator/datasets/instance/detection.py +145 -0
- edgefirst/validator/datasets/instance/multitask.py +80 -0
- edgefirst/validator/datasets/instance/segmentation.py +120 -0
- edgefirst/validator/datasets/utils/fetch.py +682 -0
- edgefirst/validator/datasets/utils/readers.py +425 -0
- edgefirst/validator/datasets/utils/transformations.py +1695 -0
- edgefirst/validator/evaluators/__init__.py +17 -0
- edgefirst/validator/evaluators/callbacks/__init__.py +3 -0
- edgefirst/validator/evaluators/callbacks/core.py +192 -0
- edgefirst/validator/evaluators/callbacks/plots.py +900 -0
- edgefirst/validator/evaluators/callbacks/studio.py +234 -0
- edgefirst/validator/evaluators/core.py +257 -0
- edgefirst/validator/evaluators/detection.py +749 -0
- edgefirst/validator/evaluators/multitask.py +270 -0
- edgefirst/validator/evaluators/parameters/__init__.py +53 -0
- edgefirst/validator/evaluators/parameters/core.py +554 -0
- edgefirst/validator/evaluators/parameters/dataset.py +239 -0
- edgefirst/validator/evaluators/parameters/model.py +338 -0
- edgefirst/validator/evaluators/parameters/validation.py +528 -0
- edgefirst/validator/evaluators/segmentation.py +729 -0
- edgefirst/validator/evaluators/utils/__init__.py +3 -0
- edgefirst/validator/evaluators/utils/classify.py +292 -0
- edgefirst/validator/evaluators/utils/match.py +262 -0
- edgefirst/validator/evaluators/utils/timer.py +132 -0
- edgefirst/validator/metrics/__init__.py +9 -0
- edgefirst/validator/metrics/data/__init__.py +7 -0
- edgefirst/validator/metrics/data/label.py +668 -0
- edgefirst/validator/metrics/data/metrics.py +759 -0
- edgefirst/validator/metrics/data/plots.py +476 -0
- edgefirst/validator/metrics/data/stats.py +507 -0
- edgefirst/validator/metrics/detection.py +595 -0
- edgefirst/validator/metrics/segmentation.py +173 -0
- edgefirst/validator/metrics/utils/math.py +717 -0
- edgefirst/validator/publishers/__init__.py +3 -0
- edgefirst/validator/publishers/console.py +147 -0
- edgefirst/validator/publishers/studio.py +128 -0
- edgefirst/validator/publishers/tensorboard.py +119 -0
- edgefirst/validator/publishers/utils/logger.py +111 -0
- edgefirst/validator/publishers/utils/table.py +403 -0
- edgefirst/validator/runners/__init__.py +8 -0
- edgefirst/validator/runners/core.py +727 -0
- edgefirst/validator/runners/deepviewrt.py +177 -0
- edgefirst/validator/runners/hailo.py +263 -0
- edgefirst/validator/runners/keras.py +150 -0
- edgefirst/validator/runners/kinara.py +265 -0
- edgefirst/validator/runners/offline.py +228 -0
- edgefirst/validator/runners/onnx.py +241 -0
- edgefirst/validator/runners/processing/decode.py +320 -0
- edgefirst/validator/runners/processing/dvapi.py +4192 -0
- edgefirst/validator/runners/processing/nms.py +637 -0
- edgefirst/validator/runners/processing/outputs.py +507 -0
- edgefirst/validator/runners/tensorrt.py +321 -0
- edgefirst/validator/runners/tflite.py +221 -0
- edgefirst/validator/validate.py +843 -0
- edgefirst/validator/visualize/__init__.py +3 -0
- edgefirst/validator/visualize/detection.py +623 -0
- edgefirst/validator/visualize/segmentation.py +281 -0
- edgefirst/validator/visualize/utils/plots.py +635 -0
- edgefirst_validator-4.2.1.dist-info/METADATA +111 -0
- edgefirst_validator-4.2.1.dist-info/RECORD +73 -0
- edgefirst_validator-4.2.1.dist-info/WHEEL +5 -0
- edgefirst_validator-4.2.1.dist-info/entry_points.txt +2 -0
- edgefirst_validator-4.2.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Implementations for reading DarkNet datasets.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from typing import TYPE_CHECKING, List, Tuple
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
from edgefirst.validator.datasets import Dataset
|
|
13
|
+
from edgefirst.validator.datasets import (SegmentationInstance,
|
|
14
|
+
DetectionInstance,
|
|
15
|
+
MultitaskInstance)
|
|
16
|
+
from edgefirst.validator.publishers.utils.logger import logger
|
|
17
|
+
from edgefirst.validator.datasets.utils.fetch import (get_shape,
|
|
18
|
+
get_image_files,
|
|
19
|
+
classify_dataset,
|
|
20
|
+
get_annotation_files,
|
|
21
|
+
validate_dataset_source)
|
|
22
|
+
from edgefirst.validator.datasets.utils.readers import (read_detection_text_file,
|
|
23
|
+
read_segmentation_text_file)
|
|
24
|
+
from edgefirst.validator.datasets.utils.transformations import (preprocess_hal,
|
|
25
|
+
preprocess_native,
|
|
26
|
+
format_segments,
|
|
27
|
+
scale)
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from edgefirst.validator.evaluators import DatasetParameters, TimerContext
|
|
31
|
+
from edgefirst.validator.datasets import Instance
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class DarkNetDataset(Dataset):
|
|
35
|
+
"""
|
|
36
|
+
Reads Darknet format datasets.
|
|
37
|
+
Dataset format should be the same as coco128 at
|
|
38
|
+
`https://www.kaggle.com/datasets/ultralytics/coco128`.
|
|
39
|
+
Optionally, the images and text annotations can be in the same directory.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
source: str
|
|
44
|
+
The path to the source dataset.
|
|
45
|
+
parameters: DatasetParameters
|
|
46
|
+
This contains dataset parameters set from the command line.
|
|
47
|
+
timer: TimerContext
|
|
48
|
+
A timer object for handling validation timings for the model.
|
|
49
|
+
info_dataset: dict
|
|
50
|
+
Contains information such as:
|
|
51
|
+
|
|
52
|
+
.. code-block:: python
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
"classes": [list of unique labels],
|
|
56
|
+
"validation":
|
|
57
|
+
{
|
|
58
|
+
"images: 'path to the images',
|
|
59
|
+
"annotations": 'path to the annotations'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
*Note: the classes are optional and the path to the images
|
|
64
|
+
and annotations can be the same.*
|
|
65
|
+
|
|
66
|
+
Raises
|
|
67
|
+
------
|
|
68
|
+
ValueError
|
|
69
|
+
Raised if the provided path to the images or
|
|
70
|
+
annotations is not a string.
|
|
71
|
+
EmptyDatasetException
|
|
72
|
+
Raised if the provided path to the images or
|
|
73
|
+
text files does not contain any image files or
|
|
74
|
+
text files respectively.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def __init__(
|
|
78
|
+
self,
|
|
79
|
+
source: str,
|
|
80
|
+
parameters: DatasetParameters,
|
|
81
|
+
timer: TimerContext,
|
|
82
|
+
info_dataset: dict = None,
|
|
83
|
+
):
|
|
84
|
+
super(DarkNetDataset, self).__init__(
|
|
85
|
+
source=source,
|
|
86
|
+
parameters=parameters,
|
|
87
|
+
timer=timer,
|
|
88
|
+
info_dataset=info_dataset
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
if self.info_dataset is None:
|
|
92
|
+
self.info_dataset = classify_dataset(source)
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
images_path = self.info_dataset.get(
|
|
96
|
+
"dataset").get('validation').get('images')
|
|
97
|
+
annotations_path = self.info_dataset.get(
|
|
98
|
+
"dataset").get('validation').get('annotations')
|
|
99
|
+
except AttributeError:
|
|
100
|
+
images_path = self.info_dataset.get('validation').get('images')
|
|
101
|
+
annotations_path = self.info_dataset.get(
|
|
102
|
+
'validation').get('annotations')
|
|
103
|
+
|
|
104
|
+
self.image_source = validate_dataset_source(images_path)
|
|
105
|
+
self.annotation_source = validate_dataset_source(annotations_path)
|
|
106
|
+
|
|
107
|
+
labels = self.info_dataset.get('classes', None)
|
|
108
|
+
if labels is not None:
|
|
109
|
+
self.parameters.labels = [str(label) for label in labels]
|
|
110
|
+
|
|
111
|
+
self.images = get_image_files(self.image_source)
|
|
112
|
+
self.annotations = get_annotation_files(self.annotation_source)
|
|
113
|
+
# This is used to map the image name to the annotation file.
|
|
114
|
+
self.annotation_extension = os.path.splitext(self.annotations[0])[1]
|
|
115
|
+
|
|
116
|
+
def collect_samples(self) -> List[tuple]:
|
|
117
|
+
"""
|
|
118
|
+
Collect all samples in the dataset.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
List[tuple]
|
|
123
|
+
One instance contains the
|
|
124
|
+
(path to the image, path to the annotation).
|
|
125
|
+
"""
|
|
126
|
+
missing_annotations = 0
|
|
127
|
+
samples = list()
|
|
128
|
+
for image_path in self.images:
|
|
129
|
+
annotation_path = os.path.join(
|
|
130
|
+
self.annotation_source,
|
|
131
|
+
os.path.splitext(os.path.basename(image_path))[0] +
|
|
132
|
+
self.annotation_extension)
|
|
133
|
+
|
|
134
|
+
if os.path.exists(annotation_path):
|
|
135
|
+
samples.append((image_path, annotation_path))
|
|
136
|
+
else:
|
|
137
|
+
samples.append((image_path, None))
|
|
138
|
+
if self.parameters.show_missing_annotations:
|
|
139
|
+
logger(
|
|
140
|
+
"Could not find the annotation " +
|
|
141
|
+
"for this image: {}. ".format(
|
|
142
|
+
os.path.basename(image_path)) +
|
|
143
|
+
"Looking for {}".format(
|
|
144
|
+
os.path.splitext(
|
|
145
|
+
os.path.basename(image_path))[0] +
|
|
146
|
+
self.annotation_extension),
|
|
147
|
+
code="WARNING")
|
|
148
|
+
missing_annotations += 1
|
|
149
|
+
|
|
150
|
+
if not self.parameters.show_missing_annotations and missing_annotations > 0:
|
|
151
|
+
logger(
|
|
152
|
+
"There were {} images without annotations. ".format(
|
|
153
|
+
missing_annotations) + "To see the names of the images, " +
|
|
154
|
+
"enable --show_missing_annotations in the command line.",
|
|
155
|
+
code="WARNING")
|
|
156
|
+
|
|
157
|
+
if len(samples) == 0:
|
|
158
|
+
raise ValueError(
|
|
159
|
+
"There are no validation samples found in this dataset.")
|
|
160
|
+
return samples
|
|
161
|
+
|
|
162
|
+
def image(self,
|
|
163
|
+
image_path: str) -> Tuple[np.ndarray, np.ndarray, list, tuple]:
|
|
164
|
+
"""
|
|
165
|
+
Read and preprocess the image.
|
|
166
|
+
|
|
167
|
+
Parameters
|
|
168
|
+
----------
|
|
169
|
+
image_path: str
|
|
170
|
+
The path to the image in the dataset.
|
|
171
|
+
|
|
172
|
+
Returns
|
|
173
|
+
-------
|
|
174
|
+
image: np.ndarray
|
|
175
|
+
The image input after being preprocessed.
|
|
176
|
+
visual_image: np.ndarray
|
|
177
|
+
The image that is used for visualization post
|
|
178
|
+
letterbox, padding, resize transformations.
|
|
179
|
+
shapes: list
|
|
180
|
+
This is used to scale the bounding boxes of the ground
|
|
181
|
+
truth and the model detections based on the letterbox/padding
|
|
182
|
+
transformation.
|
|
183
|
+
|
|
184
|
+
.. code-block:: python
|
|
185
|
+
|
|
186
|
+
[[input_height, input_width],
|
|
187
|
+
[[scale_y, scale_x], [pad_w, pad_h]]]
|
|
188
|
+
image_shape: tuple
|
|
189
|
+
The original image dimensions.
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
# Read the image.
|
|
193
|
+
image = self.load_image(image_path,
|
|
194
|
+
backend=self.parameters.common.backend)
|
|
195
|
+
|
|
196
|
+
with self.timer.time("input"):
|
|
197
|
+
if self.parameters.common.backend == "hal":
|
|
198
|
+
image, visual_image, shapes, image_shape = preprocess_hal(
|
|
199
|
+
image=image,
|
|
200
|
+
shape=self.parameters.common.shape,
|
|
201
|
+
input_type=self.parameters.common.dtype,
|
|
202
|
+
dst=self.parameters.common.input_dst,
|
|
203
|
+
transpose=self.parameters.common.transpose,
|
|
204
|
+
input_tensor=self.parameters.common.input_tensor,
|
|
205
|
+
preprocessing=self.parameters.common.preprocessing,
|
|
206
|
+
normalization=self.parameters.common.norm,
|
|
207
|
+
quantization=self.parameters.common.input_quantization,
|
|
208
|
+
visualize=self.parameters.visualize
|
|
209
|
+
)
|
|
210
|
+
else:
|
|
211
|
+
image, visual_image, shapes, image_shape = preprocess_native(
|
|
212
|
+
image=image,
|
|
213
|
+
shape=self.parameters.common.shape,
|
|
214
|
+
input_type=self.parameters.common.dtype,
|
|
215
|
+
transpose=self.parameters.common.transpose,
|
|
216
|
+
input_tensor=self.parameters.common.input_tensor,
|
|
217
|
+
preprocessing=self.parameters.common.preprocessing,
|
|
218
|
+
normalization=self.parameters.common.norm,
|
|
219
|
+
quantization=self.parameters.common.input_quantization,
|
|
220
|
+
backend=self.parameters.common.backend
|
|
221
|
+
)
|
|
222
|
+
return image, visual_image, shapes, image_shape
|
|
223
|
+
|
|
224
|
+
def build_detection_instance(
|
|
225
|
+
self,
|
|
226
|
+
sample: Tuple[str, str]
|
|
227
|
+
) -> DetectionInstance:
|
|
228
|
+
"""
|
|
229
|
+
Builds a 2D detection instance container.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
sample: Tuple[str, str]
|
|
234
|
+
This contains the (image path, annotation path).
|
|
235
|
+
|
|
236
|
+
Returns
|
|
237
|
+
-------
|
|
238
|
+
DetectionInstance
|
|
239
|
+
The ground truth instance objects contains the 2D bounding boxes
|
|
240
|
+
and the labels representing the ground truth of the image.
|
|
241
|
+
"""
|
|
242
|
+
image_path, annotation_path = sample
|
|
243
|
+
|
|
244
|
+
image, visual_image, shapes, image_shape = self.image(image_path)
|
|
245
|
+
height, width = get_shape(image.shape)
|
|
246
|
+
|
|
247
|
+
annotations = read_detection_text_file(
|
|
248
|
+
annotation_path=annotation_path,
|
|
249
|
+
label_offset=self.parameters.label_offset,
|
|
250
|
+
shape=(height, width),
|
|
251
|
+
normalizer=self.normalizer,
|
|
252
|
+
transformer=self.transformer
|
|
253
|
+
)
|
|
254
|
+
boxes = annotations["boxes"]
|
|
255
|
+
labels = annotations["labels"]
|
|
256
|
+
|
|
257
|
+
# Transform the ground truth boxes based on the preprocessed image.
|
|
258
|
+
if len(boxes):
|
|
259
|
+
# Scale ground truth coordinates to center around objects
|
|
260
|
+
# in an image with letterbox transformation.
|
|
261
|
+
if self.parameters.common.preprocessing == "letterbox":
|
|
262
|
+
boxes = scale(
|
|
263
|
+
boxes=boxes,
|
|
264
|
+
w=shapes[1][0][1] * image_shape[1],
|
|
265
|
+
h=shapes[1][0][0] * image_shape[0],
|
|
266
|
+
padw=shapes[1][1][0],
|
|
267
|
+
padh=shapes[1][1][1],
|
|
268
|
+
)
|
|
269
|
+
# Scale ground truth coordinates to center around objects
|
|
270
|
+
# in an image with padding transformation.
|
|
271
|
+
elif self.parameters.common.preprocessing == "pad":
|
|
272
|
+
boxes = scale(
|
|
273
|
+
boxes=boxes,
|
|
274
|
+
w=shapes[1][0][1] * width,
|
|
275
|
+
h=shapes[1][0][0] * height,
|
|
276
|
+
)
|
|
277
|
+
# Scale ground truth coordinates to center around objects
|
|
278
|
+
# in an image with resize transformation.
|
|
279
|
+
else:
|
|
280
|
+
# Denormalize boxes
|
|
281
|
+
boxes *= np.array([width, height, width, height])
|
|
282
|
+
|
|
283
|
+
instance = DetectionInstance(image_path)
|
|
284
|
+
instance.image = image
|
|
285
|
+
instance.visual_image = visual_image
|
|
286
|
+
instance.height = height
|
|
287
|
+
instance.width = width
|
|
288
|
+
instance.boxes = boxes.astype(np.float32)
|
|
289
|
+
instance.labels = labels.astype(np.int32)
|
|
290
|
+
instance.shapes = shapes
|
|
291
|
+
instance.image_shape = image_shape
|
|
292
|
+
return instance
|
|
293
|
+
|
|
294
|
+
def build_segmentation_instance(
|
|
295
|
+
self, sample: Tuple[str, str]) -> SegmentationInstance:
|
|
296
|
+
"""
|
|
297
|
+
Builds a segmentation instance container.
|
|
298
|
+
|
|
299
|
+
Parameters
|
|
300
|
+
----------
|
|
301
|
+
sample: Tuple[str, str]
|
|
302
|
+
This contains the (image path, annotation path).
|
|
303
|
+
|
|
304
|
+
Returns
|
|
305
|
+
-------
|
|
306
|
+
SegmentationInstance
|
|
307
|
+
The ground truth instance objects contains the polygon, mask,
|
|
308
|
+
and the labels representing the ground truth of the image.
|
|
309
|
+
"""
|
|
310
|
+
image_path, annotation_path = sample
|
|
311
|
+
|
|
312
|
+
image, visual_image, shapes, image_shape = self.image(image_path)
|
|
313
|
+
height, width = get_shape(image.shape)
|
|
314
|
+
|
|
315
|
+
annotations = read_segmentation_text_file(
|
|
316
|
+
annotation_path=annotation_path,
|
|
317
|
+
label_offset=self.parameters.label_offset,
|
|
318
|
+
shape=image_shape,
|
|
319
|
+
normalizer=self.normalizer,
|
|
320
|
+
transformer=self.transformer
|
|
321
|
+
)
|
|
322
|
+
segments = annotations["segments"]
|
|
323
|
+
labels = annotations["labels"]
|
|
324
|
+
|
|
325
|
+
imgsz = shapes[0]
|
|
326
|
+
ratio_pad = shapes[1]
|
|
327
|
+
|
|
328
|
+
# Scale ground truth mask to center around objects
|
|
329
|
+
# in an image with padding transformation.
|
|
330
|
+
if self.parameters.common.preprocessing == "pad":
|
|
331
|
+
ratio_pad[1] = [0.0, 0.0]
|
|
332
|
+
|
|
333
|
+
masks, _ = format_segments(
|
|
334
|
+
segments=segments,
|
|
335
|
+
shape=imgsz,
|
|
336
|
+
ratio_pad=ratio_pad,
|
|
337
|
+
colors=labels,
|
|
338
|
+
semantic=self.parameters.common.semantic,
|
|
339
|
+
backend=self.parameters.common.backend
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
instance = SegmentationInstance(image_path)
|
|
343
|
+
instance.image = image
|
|
344
|
+
instance.visual_image = visual_image
|
|
345
|
+
instance.height = height
|
|
346
|
+
instance.width = width
|
|
347
|
+
instance.mask = masks
|
|
348
|
+
instance.shapes = shapes
|
|
349
|
+
instance.image_shape = image_shape
|
|
350
|
+
return instance
|
|
351
|
+
|
|
352
|
+
def build_multitask_instance(
|
|
353
|
+
self, sample: Tuple[str, str]) -> MultitaskInstance:
|
|
354
|
+
"""
|
|
355
|
+
Builds a multitask instance container.
|
|
356
|
+
|
|
357
|
+
Parameters
|
|
358
|
+
----------
|
|
359
|
+
sample: Tuple[str, str]
|
|
360
|
+
This contains the (image path, annotation path).
|
|
361
|
+
|
|
362
|
+
Returns
|
|
363
|
+
-------
|
|
364
|
+
MultitaskInstance
|
|
365
|
+
The ground truth instance objects contains the bounding boxes
|
|
366
|
+
and the segmentation mask representing the ground truth of
|
|
367
|
+
the image
|
|
368
|
+
"""
|
|
369
|
+
|
|
370
|
+
image_path, annotation_path = sample
|
|
371
|
+
|
|
372
|
+
image, visual_image, shapes, image_shape = self.image(image_path)
|
|
373
|
+
height, width = get_shape(image.shape)
|
|
374
|
+
|
|
375
|
+
annotations = read_segmentation_text_file(
|
|
376
|
+
annotation_path=annotation_path,
|
|
377
|
+
label_offset=self.parameters.label_offset,
|
|
378
|
+
shape=image_shape,
|
|
379
|
+
normalizer=self.normalizer,
|
|
380
|
+
transformer=self.transformer
|
|
381
|
+
)
|
|
382
|
+
segments = annotations["segments"]
|
|
383
|
+
labels = annotations["labels"]
|
|
384
|
+
boxes = annotations["boxes"]
|
|
385
|
+
|
|
386
|
+
imgsz = shapes[0]
|
|
387
|
+
ratio_pad = shapes[1]
|
|
388
|
+
|
|
389
|
+
# Format boxes
|
|
390
|
+
if len(boxes):
|
|
391
|
+
# Transform the ground truth boxes based on the preprocessed image.
|
|
392
|
+
# Scale ground truth coordinates to center around objects
|
|
393
|
+
# in an image with letterbox transformation.
|
|
394
|
+
if self.parameters.common.preprocessing == "letterbox":
|
|
395
|
+
boxes = scale(
|
|
396
|
+
boxes=boxes,
|
|
397
|
+
w=shapes[1][0][1] * image_shape[1],
|
|
398
|
+
h=shapes[1][0][0] * image_shape[0],
|
|
399
|
+
padw=shapes[1][1][0],
|
|
400
|
+
padh=shapes[1][1][1],
|
|
401
|
+
)
|
|
402
|
+
# Scale ground truth coordinates to center around objects
|
|
403
|
+
# in an image with padding transformation.
|
|
404
|
+
elif self.parameters.common.preprocessing == "pad":
|
|
405
|
+
boxes = scale(
|
|
406
|
+
boxes=boxes,
|
|
407
|
+
w=shapes[1][0][1] * width,
|
|
408
|
+
h=shapes[1][0][0] * height,
|
|
409
|
+
)
|
|
410
|
+
# Scale ground truth coordinates to center around objects
|
|
411
|
+
# in an image with resize transformation.
|
|
412
|
+
else:
|
|
413
|
+
# Denormalize boxes
|
|
414
|
+
boxes *= np.array([width, height, width, height])
|
|
415
|
+
|
|
416
|
+
# Scale ground truth mask to center around objects
|
|
417
|
+
# in an image with padding transformation.
|
|
418
|
+
if self.parameters.common.preprocessing == "pad":
|
|
419
|
+
ratio_pad[1] = [0.0, 0.0]
|
|
420
|
+
|
|
421
|
+
masks, sorted_idx = format_segments(
|
|
422
|
+
segments=segments,
|
|
423
|
+
shape=imgsz,
|
|
424
|
+
ratio_pad=ratio_pad,
|
|
425
|
+
colors=labels,
|
|
426
|
+
semantic=self.parameters.common.semantic,
|
|
427
|
+
backend=self.parameters.common.backend
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
if sorted_idx is not None and len(sorted_idx) > 0:
|
|
431
|
+
if len(labels):
|
|
432
|
+
labels = labels[sorted_idx]
|
|
433
|
+
if len(boxes):
|
|
434
|
+
boxes = boxes[sorted_idx]
|
|
435
|
+
|
|
436
|
+
instance = MultitaskInstance(image_path)
|
|
437
|
+
instance.image = image
|
|
438
|
+
instance.visual_image = visual_image
|
|
439
|
+
instance.height = height
|
|
440
|
+
instance.width = width
|
|
441
|
+
instance.boxes = boxes.astype(np.float32)
|
|
442
|
+
instance.labels = labels.astype(np.int32)
|
|
443
|
+
instance.mask = masks
|
|
444
|
+
instance.shapes = shapes
|
|
445
|
+
instance.image_shape = image_shape
|
|
446
|
+
return instance
|