edgefirst-validator 4.1.12__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.
Files changed (78) hide show
  1. deepview/modelpack/utils/argmax.py +16 -0
  2. edgefirst/validator/__init__.py +1 -0
  3. edgefirst/validator/__main__.py +336 -0
  4. edgefirst/validator/datasets/__init__.py +131 -0
  5. edgefirst/validator/datasets/arrow.py +147 -0
  6. edgefirst/validator/datasets/cache.py +258 -0
  7. edgefirst/validator/datasets/core.py +245 -0
  8. edgefirst/validator/datasets/darknet.py +432 -0
  9. edgefirst/validator/datasets/database.py +1353 -0
  10. edgefirst/validator/datasets/instance/__init__.py +8 -0
  11. edgefirst/validator/datasets/instance/core.py +223 -0
  12. edgefirst/validator/datasets/instance/detection.py +348 -0
  13. edgefirst/validator/datasets/instance/fusion.py +22 -0
  14. edgefirst/validator/datasets/instance/multitask.py +80 -0
  15. edgefirst/validator/datasets/instance/pose.py +51 -0
  16. edgefirst/validator/datasets/instance/segmentation.py +120 -0
  17. edgefirst/validator/datasets/tfrecord.py +243 -0
  18. edgefirst/validator/datasets/utils/fetch.py +856 -0
  19. edgefirst/validator/datasets/utils/readers.py +598 -0
  20. edgefirst/validator/datasets/utils/transformations.py +1878 -0
  21. edgefirst/validator/evaluators/__init__.py +16 -0
  22. edgefirst/validator/evaluators/callbacks/__init__.py +3 -0
  23. edgefirst/validator/evaluators/callbacks/core.py +194 -0
  24. edgefirst/validator/evaluators/callbacks/plots.py +857 -0
  25. edgefirst/validator/evaluators/callbacks/studio.py +128 -0
  26. edgefirst/validator/evaluators/core.py +255 -0
  27. edgefirst/validator/evaluators/detection.py +795 -0
  28. edgefirst/validator/evaluators/multitask.py +294 -0
  29. edgefirst/validator/evaluators/parameters/__init__.py +53 -0
  30. edgefirst/validator/evaluators/parameters/core.py +443 -0
  31. edgefirst/validator/evaluators/parameters/dataset.py +176 -0
  32. edgefirst/validator/evaluators/parameters/model.py +288 -0
  33. edgefirst/validator/evaluators/parameters/validation.py +529 -0
  34. edgefirst/validator/evaluators/pose.py +155 -0
  35. edgefirst/validator/evaluators/segmentation.py +975 -0
  36. edgefirst/validator/evaluators/utils/__init__.py +2 -0
  37. edgefirst/validator/evaluators/utils/classify.py +284 -0
  38. edgefirst/validator/evaluators/utils/match.py +262 -0
  39. edgefirst/validator/metrics/__init__.py +12 -0
  40. edgefirst/validator/metrics/data/__init__.py +9 -0
  41. edgefirst/validator/metrics/data/label.py +727 -0
  42. edgefirst/validator/metrics/data/metrics.py +753 -0
  43. edgefirst/validator/metrics/data/plots.py +447 -0
  44. edgefirst/validator/metrics/data/stats.py +690 -0
  45. edgefirst/validator/metrics/detection.py +588 -0
  46. edgefirst/validator/metrics/pose.py +80 -0
  47. edgefirst/validator/metrics/segmentation.py +171 -0
  48. edgefirst/validator/metrics/utils/math.py +698 -0
  49. edgefirst/validator/publishers/__init__.py +3 -0
  50. edgefirst/validator/publishers/console.py +78 -0
  51. edgefirst/validator/publishers/studio.py +107 -0
  52. edgefirst/validator/publishers/tensorboard.py +118 -0
  53. edgefirst/validator/publishers/utils/logger.py +111 -0
  54. edgefirst/validator/publishers/utils/table.py +434 -0
  55. edgefirst/validator/runners/__init__.py +7 -0
  56. edgefirst/validator/runners/core.py +644 -0
  57. edgefirst/validator/runners/deepviewrt.py +169 -0
  58. edgefirst/validator/runners/hailo.py +281 -0
  59. edgefirst/validator/runners/keras.py +219 -0
  60. edgefirst/validator/runners/offline.py +228 -0
  61. edgefirst/validator/runners/onnx.py +332 -0
  62. edgefirst/validator/runners/processing/decode.py +105 -0
  63. edgefirst/validator/runners/processing/nms.py +824 -0
  64. edgefirst/validator/runners/processing/postprocess.py +520 -0
  65. edgefirst/validator/runners/processing/preprocess.py +134 -0
  66. edgefirst/validator/runners/tensorrt.py +352 -0
  67. edgefirst/validator/runners/tflite.py +272 -0
  68. edgefirst/validator/validate.py +701 -0
  69. edgefirst/validator/visualize/__init__.py +4 -0
  70. edgefirst/validator/visualize/detection.py +946 -0
  71. edgefirst/validator/visualize/pose.py +243 -0
  72. edgefirst/validator/visualize/segmentation.py +377 -0
  73. edgefirst/validator/visualize/utils/plots.py +686 -0
  74. edgefirst_validator-4.1.12.dist-info/METADATA +114 -0
  75. edgefirst_validator-4.1.12.dist-info/RECORD +78 -0
  76. edgefirst_validator-4.1.12.dist-info/WHEEL +5 -0
  77. edgefirst_validator-4.1.12.dist-info/entry_points.txt +2 -0
  78. edgefirst_validator-4.1.12.dist-info/top_level.txt +2 -0
@@ -0,0 +1,16 @@
1
+ from keras.saving import register_keras_serializable
2
+ import tensorflow as tf
3
+ import keras
4
+
5
+
6
+ @register_keras_serializable(package="deepview.modelpack.utils")
7
+ class Argmax(keras.layers.Layer):
8
+ def __init__(self, **kwargs):
9
+ super().__init__(**kwargs)
10
+
11
+ def call(self, x):
12
+ return tf.argmax(x, axis=-1, output_type=tf.int32)
13
+
14
+ def get_config(self):
15
+ return super().get_config()
16
+
@@ -0,0 +1 @@
1
+ __version__ = "4.1.12"
@@ -0,0 +1,336 @@
1
+ import argparse
2
+
3
+ from edgefirst.validator import __version__
4
+ from edgefirst.validator.validate import validate
5
+
6
+ try:
7
+ import ctypes
8
+ import inspect
9
+ from pathlib import Path
10
+
11
+ import nvidia
12
+
13
+ nvpath = Path(inspect.getfile(nvidia)).parent
14
+ cudnn = nvpath / 'cudnn' / 'lib' / 'libcudnn.so.9'
15
+ if cudnn.exists():
16
+ ctypes.CDLL(cudnn.as_posix(), mode=ctypes.RTLD_GLOBAL)
17
+ except ImportError:
18
+ pass
19
+
20
+
21
+ def main():
22
+ parser = argparse.ArgumentParser(
23
+ description=('EdgeFirst Validator'),
24
+ formatter_class=argparse.RawTextHelpFormatter
25
+ )
26
+ parser.add_argument('-V', '--version',
27
+ help="Print the package version.",
28
+ action='version',
29
+ version=__version__
30
+ )
31
+ parser.add_argument('model',
32
+ help=("The path to the model: \n"
33
+ "- DeepViewRT (.rtm) \n"
34
+ "- TensorFlow or Keras (**/*.pb), (.h5), (.keras) \n"
35
+ "- TFlite (.tflite) \n"
36
+ "- ONNX (.onnx) \n"
37
+ "- Hailo (.hef) \n"
38
+ "- Offline (directory of model annotations)."),
39
+ metavar='model.onnx',
40
+ nargs="?",
41
+ type=str,
42
+ default="yolov5s.onnx"
43
+ )
44
+ parser.add_argument('dataset',
45
+ help=("The absolute or relative path "
46
+ "to the dataset folder or YAML file."),
47
+ metavar='dataset.yaml',
48
+ nargs="?",
49
+ type=str,
50
+ default='samples/coco128.yaml'
51
+ )
52
+
53
+ studio_parser = parser.add_argument_group(
54
+ title="EdgeFirst Studio Parameters",
55
+ description=("Specify the interface parameters "
56
+ "for a direct communication with EdgeFirst Studio.")
57
+ )
58
+ studio_parser.add_argument('--token',
59
+ help="EdgeFirst Studio authentication token.",
60
+ type=str,
61
+ )
62
+ studio_parser.add_argument('--username',
63
+ help="EdgeFirst Studio username.",
64
+ type=str,
65
+ )
66
+ studio_parser.add_argument('--password',
67
+ help="EdgeFirst Studio password.",
68
+ type=str,
69
+ )
70
+ studio_parser.add_argument('--server',
71
+ help="EdgeFirst Studio server.",
72
+ type=str,
73
+ choices=['test', 'stage', 'saas'],
74
+ default='saas'
75
+ )
76
+ studio_parser.add_argument('--session-id',
77
+ help=("Specify the validator session ID "
78
+ "for posting results."),
79
+ type=str,
80
+ )
81
+
82
+ model_parser = parser.add_argument_group(
83
+ title="Model Parameters",
84
+ description="Specify how the model should be run with these parameters."
85
+ )
86
+ parser.add_argument('--config',
87
+ help=("Specify the path to 'edgefirst.yaml' "
88
+ "containing the model metadata. This overrides "
89
+ "the metadata embedded in the model."),
90
+ type=str
91
+ )
92
+ model_parser.add_argument('--model-labels',
93
+ help=("Specify the path to the model labels file "
94
+ "This artifact is a labels.txt file "
95
+ "containing model string labels. This is "
96
+ "used to map model output indices to strings."),
97
+ type=str,
98
+ )
99
+ model_parser.add_argument('-i', '--nms-iou-threshold',
100
+ help="NMS IoU threshold for valid predictions.",
101
+ default=0.70,
102
+ type=float
103
+ )
104
+ model_parser.add_argument('-t', '--nms-score-threshold',
105
+ help="Set the NMS score threshold for valid scores.",
106
+ default=0.001,
107
+ type=float
108
+ )
109
+ model_parser.add_argument('-m', '--max-detections',
110
+ help="Number of maximum detections for NMS.",
111
+ default=300,
112
+ type=int
113
+ )
114
+ model_parser.add_argument('-e', '--engine',
115
+ help=("Inference Engine. Options include 'cpu', 'gpu', "
116
+ "or a path the NPU delegate '/usr/lib/libvx_delegate.so'."),
117
+ default='npu',
118
+ type=str
119
+ )
120
+ model_parser.add_argument('-s', '--nms',
121
+ help="Specify the NMS algorithm. Default to use 'numpy'.",
122
+ choices=['numpy', 'tensorflow', 'torch'],
123
+ default='tensorflow',
124
+ type=str
125
+ )
126
+ model_parser.add_argument('-n', '--norm',
127
+ help=("Normalization method applied to input images.\n "
128
+ "- raw (default, no processing)\n "
129
+ "- unsigned (0...1)\n "
130
+ "- signed (-1...1)\n "
131
+ "- whitening (per-image standardization/whitening)\n "
132
+ "- imagenet (standardization using imagenet)\n "),
133
+ choices=[
134
+ 'raw', 'unsigned', 'signed', 'imagenet'],
135
+ default='unsigned',
136
+ type=str
137
+ )
138
+ model_parser.add_argument('-p', '--preprocessing',
139
+ help=("The type of image preprocessing to perform. \n"
140
+ "- letterbox: YOLOv5, YOLOv7 implementation. \n"
141
+ "- pad: Image padding based on YOLOx implementation. \n"
142
+ "- resize: Does not maintain aspect ratio. (default)"),
143
+ choices=['letterbox', 'pad', 'resize'],
144
+ default='letterbox',
145
+ type=str
146
+ )
147
+ model_parser.add_argument('-b', '--box-format',
148
+ help=("box format to reorient the bounding box "
149
+ "coordinates: 'xcycwh', 'xywh', 'xyxy', etc).\n"),
150
+ choices=['yolo', 'coco', 'pascalvoc'],
151
+ default='pascalvoc',
152
+ type=str
153
+ )
154
+ model_parser.add_argument('-w', '--warmup',
155
+ help="The number of model warmup iterations.",
156
+ default=5,
157
+ type=int
158
+ )
159
+ model_parser.add_argument('-l', '--label-offset',
160
+ help="Label offset when mapping index to string representations.",
161
+ default=0,
162
+ type=int
163
+ )
164
+ model_parser.add_argument('--override',
165
+ help=("This parameter is set to True by default "
166
+ "When specified, this will use the model "
167
+ "parameters specified in the model metadata "
168
+ "to validate the model. Otherwise, the "
169
+ "command line parameters can be set."),
170
+ action='store_false')
171
+
172
+ dataset_parser = parser.add_argument_group(
173
+ title="Dataset Parameters",
174
+ description="Specify how the dataset should be read with these parameters."
175
+ )
176
+ dataset_parser.add_argument('--cache',
177
+ help=("Specify the path to the dataset cache. "
178
+ "A dataset cache is an LMDB file."),
179
+ metavar="cache/val.db",
180
+ type=str,
181
+ )
182
+ dataset_parser.add_argument('--dataset-labels',
183
+ help=("Absolute or relative path "
184
+ "to the labels.txt file. \n"
185
+ "This can be stored inside the dataset folder "
186
+ "to avoid having to specify this path. \n"
187
+ "Otherwise, the YAML file can embed the labels. \n"
188
+ "This is used to map dataset indices to strings."),
189
+ type=str
190
+ )
191
+ dataset_parser.add_argument('--suppress-local-reader',
192
+ help=("Specify whether to use deepview-dataset methods "
193
+ "for reading datasets. \n"
194
+ "Otherwise, by default use local validator methods."),
195
+ action='store_false'
196
+ )
197
+ dataset_parser.add_argument('--show-missing-annotations',
198
+ help=("List the images without "
199
+ "annotations on the terminal"),
200
+ action='store_true'
201
+ )
202
+ dataset_parser.add_argument('--absolute-annotations',
203
+ help=("This specifies that the annotations "
204
+ "are not normalized to the image dimensions. "
205
+ "Otherwise, by default the annotations "
206
+ "are normalized."),
207
+ action='store_false'
208
+ )
209
+ dataset_parser.add_argument('--annotation-format',
210
+ help=("Specify the format of the annotations: "
211
+ "'yolo', 'coco', 'pascalvoc'."),
212
+ choices=['yolo', 'coco', 'pascalvoc'],
213
+ default='yolo',
214
+ type=str
215
+ )
216
+ dataset_parser.add_argument('--gt-label-offset',
217
+ help=("The label offset to use for the ground truth "
218
+ "mapping integer labels to string labels. "
219
+ "This is typically set to 1 for segmentation "
220
+ "as datasets include the background class."),
221
+ default=0,
222
+ type=int
223
+ )
224
+
225
+ val_parser = parser.add_argument_group(
226
+ title="Validation Parameters",
227
+ description=("Specify additional validation settings "
228
+ "for metric computations and visualizations.")
229
+ )
230
+ val_parser.add_argument('--validate',
231
+ help="Specify the validation task. By default 'vision'.",
232
+ choices=['vision', 'fusion', 'pose'],
233
+ default='vision',
234
+ type=str
235
+ )
236
+ val_parser.add_argument('--method',
237
+ help=("Specify the validation method to deploy. "
238
+ "The method to reproduce metrics from Ultralytics "
239
+ "or other validator sources such as YOLOv7 or "
240
+ "internal Au-Zone validation methods and metrics."),
241
+ choices=["ultralytics", "yolov7", "edgefirst"],
242
+ default="ultralytics",
243
+ type=str
244
+ )
245
+ val_parser.add_argument('--validation-iou',
246
+ help=("Validation IoU threshold "
247
+ "to consider as true positives. Detections with IoU "
248
+ "lower than this threshold are classified as "
249
+ "localization false positives. This is used in the "
250
+ "edgefirst method of validation."),
251
+ default=0.50,
252
+ type=float
253
+ )
254
+ val_parser.add_argument('--validation-score',
255
+ help=("Validation Score threshold used in the edgefirst "
256
+ "method of validation."),
257
+ default=0.00,
258
+ type=float
259
+ )
260
+ val_parser.add_argument('--metric',
261
+ help=("Specify the metric to use when "
262
+ "matching model predictions to ground truth."),
263
+ choices=['iou', 'centerpoint'],
264
+ default='iou',
265
+ type=str
266
+ )
267
+ val_parser.add_argument('--matching-leniency',
268
+ help=("Distance metric to be considered a valid match "
269
+ "when using the 'centerpoint' metric. "
270
+ "Default is 2 where the distance is no "
271
+ "more than twice the size of the bounding box. \n"),
272
+ default=2,
273
+ type=int
274
+ )
275
+ val_parser.add_argument('--clamp-boxes',
276
+ help=("The value to clamp the minimum width or height "
277
+ "of the bounding boxes of the ground truth and "
278
+ "predictions in pixels."),
279
+ type=int
280
+ )
281
+ val_parser.add_argument('--ignore-boxes',
282
+ help=("Ignore the bounding boxes "
283
+ "of the detections and the ground truth with "
284
+ "height or width less than this value in pixels."),
285
+ type=int
286
+ )
287
+ val_parser.add_argument('--display',
288
+ help=("How many images to display into tensorboard "
289
+ "or to save in disk. By default it is (-1) all "
290
+ "the images are saved. but any integer can be passed."),
291
+ default=-1,
292
+ type=int
293
+ )
294
+ val_parser.add_argument('--suppress-plots',
295
+ help=("Specify to exclude the plots data in the "
296
+ "JSON summary and/or save the plots as images if "
297
+ "visualize or tensorboard parameter is set."),
298
+ action="store_false"
299
+ )
300
+ val_parser.add_argument('--visualize',
301
+ help=("Path to store visualizations "
302
+ "(images with bounding boxes "
303
+ "or segmentation masks) in disk."),
304
+ default=None,
305
+ type=str
306
+ )
307
+ val_parser.add_argument('--tensorboard',
308
+ help=("Path to store *.tfevents files in disk"
309
+ "needed for Tensorboard."),
310
+ default=None,
311
+ type=str
312
+ )
313
+ val_parser.add_argument('--json-out',
314
+ help=("Path to save the validation "
315
+ "JSON files in disk."),
316
+ default=None,
317
+ type=str
318
+ )
319
+ val_parser.add_argument('--include-background',
320
+ help=("This is used for segmentation. "
321
+ "This allows evaluation of the "
322
+ "background class as part of validation."),
323
+ action="store_true"
324
+ )
325
+ val_parser.add_argument('--exclude-symbols',
326
+ help=("Specify whether to exclude symbols when "
327
+ "logging messages on the terminal."),
328
+ action="store_false"
329
+ )
330
+ args = parser.parse_args()
331
+
332
+ validate(args)
333
+
334
+
335
+ if __name__ == '__main__':
336
+ main()
@@ -0,0 +1,131 @@
1
+ import os
2
+
3
+ from edgefirst.validator.datasets.instance import (Instance, DetectionInstance,
4
+ RadarDetectionInstance,
5
+ SegmentationInstance,
6
+ Detection3DInstance,
7
+ MultitaskInstance,
8
+ FusionInstance,
9
+ PoseInstance)
10
+ from edgefirst.validator.datasets.core import Dataset, BaseDataset
11
+ from edgefirst.validator.datasets.tfrecord import TFRecordDataset
12
+ from edgefirst.validator.datasets.darknet import DarkNetDataset
13
+ from edgefirst.validator.datasets.arrow import ArrowDataset
14
+ from edgefirst.validator.datasets.database import (Database, EdgeFirstDatabase,
15
+ DarknetDatabase, LMDBDatabase)
16
+ from edgefirst.validator.datasets.cache import StudioCache
17
+
18
+ from edgefirst.validator.datasets.utils.fetch import download_and_extract
19
+ from edgefirst.validator.publishers.utils.logger import logger
20
+
21
+
22
+ def instantiate_dataset(
23
+ info_dataset: dict,
24
+ parameters,
25
+ ) -> Dataset:
26
+ """
27
+ This function instantiates either darknet or tfrecord
28
+ format dataset objects.
29
+
30
+ Parameters
31
+ ----------
32
+ info_dataset: dict
33
+ If the dataset is Darknet, this contains information such as:
34
+
35
+ .. code-block:: python
36
+
37
+ {
38
+ "classes": [list of unique labels],
39
+ "type": "darknet",
40
+ "validation":
41
+ {
42
+ "images: 'path to the images',
43
+ "annotations": 'path to the annotations'
44
+ },
45
+ }
46
+
47
+ *Note: the classes are optional and the path to the images
48
+ and annotations can be the same.*
49
+
50
+ If the dataset is tfrecord, this contains information such as:
51
+
52
+ .. code-block:: python
53
+
54
+ {
55
+ "classes": [list of unique labels],
56
+ "validation": {
57
+ "path": path to the *.tfrecord files.
58
+ }
59
+ }
60
+ parameters: DatasetParameters
61
+ A container for the dataset parameters set from the command line.
62
+
63
+ Returns
64
+ -------
65
+ Dataset
66
+ This object is returned depending on the type of the dataset provided.
67
+
68
+ Raises
69
+ ------
70
+ InvalidDatasetSourceException
71
+ Raised if the path to the images or annotations is None.
72
+ DatasetNotFoundException
73
+ Raised if the provided path to the images or
74
+ annotations does not exist.
75
+ ValueError
76
+ Raised if the provided path to the images or
77
+ annotations is not a string.
78
+ EmptyDatasetException
79
+ Raised if the provided path to the images or
80
+ text files does not contain any image files or
81
+ text files respectively.
82
+ """
83
+ if isinstance(info_dataset, dict):
84
+ if "download" in info_dataset.keys():
85
+ url = info_dataset.get("download")
86
+ download_path = os.path.join(os.getcwd(),
87
+ f"samples/{os.path.basename(url)}")
88
+ if not os.path.exists(download_path):
89
+ download_and_extract(url=url, download_path=download_path)
90
+
91
+ try:
92
+ ds_format = info_dataset.get('type')
93
+ if ds_format is None:
94
+ ds_format = info_dataset.get("dataset").get("format")
95
+ except AttributeError:
96
+ logger("Dataset was not properly read. Ensure the dataset " +
97
+ "structure follows images/validate and labels/validate.",
98
+ code="ERROR")
99
+ if ds_format in [None, "tfrecord"]:
100
+ return TFRecordDataset(
101
+ source=parameters.dataset_path,
102
+ parameters=parameters,
103
+ info_dataset=info_dataset,
104
+ )
105
+ elif ds_format == "darknet":
106
+ return DarkNetDataset(
107
+ source=parameters.dataset_path,
108
+ parameters=parameters,
109
+ info_dataset=info_dataset,
110
+ )
111
+ elif ds_format == "arrow":
112
+ return ArrowDataset(
113
+ source=parameters.dataset_path,
114
+ parameters=parameters,
115
+ info_dataset=info_dataset,
116
+ )
117
+ elif ds_format == "lmdb":
118
+ return LMDBDatabase(
119
+ source=parameters.dataset_path,
120
+ parameters=parameters
121
+ )
122
+ elif ds_format == "edgefirst":
123
+ return EdgeFirstDatabase(
124
+ source=parameters.dataset_path,
125
+ parameters=parameters,
126
+ )
127
+ else:
128
+ return BaseDataset(
129
+ source=parameters.dataset_path,
130
+ iterator=info_dataset
131
+ )
@@ -0,0 +1,147 @@
1
+ """
2
+ Implementations for reading Arrow datasets.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import os
8
+ from typing import TYPE_CHECKING
9
+
10
+ import numpy as np
11
+
12
+ from edgefirst.validator.datasets import Dataset
13
+ from edgefirst.validator.datasets import DetectionInstance
14
+ from edgefirst.validator.publishers.utils.logger import logger
15
+ from edgefirst.validator.datasets.utils.fetch import (classify_dataset,
16
+ validate_dataset_source)
17
+
18
+ if TYPE_CHECKING:
19
+ from edgefirst.validator.evaluators import DatasetParameters
20
+
21
+
22
+ class ArrowDataset(Dataset):
23
+ """
24
+ Reads Arrow datasets.
25
+
26
+ Parameters
27
+ ----------
28
+ source: str
29
+ The path to the source dataset.
30
+ parameters: DatasetParameters
31
+ This contains dataset parameters set from the command line.
32
+ info_dataset: dict
33
+ Contains information such as:
34
+
35
+ .. code-block:: python
36
+
37
+ {
38
+ "classes": [list of unique labels],
39
+ "validation":
40
+ {
41
+ "images: 'path to the images arrow files',
42
+ "annotations": 'path to the annotations arrow files'
43
+ }
44
+ }
45
+
46
+ *Note: the classes are optional and the path to the images
47
+ and annotations can be the same.*
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ source: str,
53
+ parameters: DatasetParameters,
54
+ info_dataset: dict = None,
55
+ ):
56
+ super(ArrowDataset, self).__init__(
57
+ source=source,
58
+ parameters=parameters
59
+ )
60
+
61
+ if info_dataset is None:
62
+ info_dataset = classify_dataset(source)
63
+
64
+ try:
65
+ self.image_source = info_dataset.get(
66
+ "dataset").get('validation').get('images')
67
+ self.annotation_source = info_dataset.get(
68
+ "dataset").get('validation').get('annotations')
69
+ except AttributeError:
70
+ self.image_source = validate_dataset_source(
71
+ info_dataset.get('validation').get('images'))
72
+ self.annotation_source = validate_dataset_source(
73
+ info_dataset.get('validation').get('annotations'))
74
+
75
+ try:
76
+ from deepview.datasets.readers import PolarsDetectionReader # type: ignore
77
+ except ImportError:
78
+ logger(
79
+ "Dependency missing: deepview-datasets is needed for polar datasets.",
80
+ code="ERROR")
81
+ self.reader = PolarsDetectionReader(
82
+ inputs=self.image_source,
83
+ annotations=self.annotation_source,
84
+ )
85
+
86
+ labels = info_dataset.get('classes', None)
87
+ if labels is not None:
88
+ self.parameters.labels = [str(label) for label in labels]
89
+ else:
90
+ self.parameters.labels = self.reader.classes
91
+
92
+ def build_dataset(self):
93
+ """
94
+ Allows iteration in the dataset.
95
+
96
+ Returns
97
+ -------
98
+ Iterator
99
+ Contains the images and boxes.
100
+ """
101
+ return self.reader
102
+
103
+ def read_sample(self, sample: tuple) -> DetectionInstance:
104
+ """
105
+ Reads one sample from the dataset.
106
+
107
+ Parameters
108
+ ----------
109
+ sample: tuple
110
+ This contains the (image, boxes).
111
+
112
+ Returns
113
+ -------
114
+ DetectionInstance
115
+ The ground truth instance objects contains the bounding boxes
116
+ and the labels representing the ground truth of the image.
117
+ """
118
+ if self.parameters.common.with_boxes:
119
+ image = sample[0].astype(np.uint8)
120
+ height, width, _ = image.shape
121
+ boxes = sample[1]
122
+
123
+ image_path = self.reader.get_instance_id()
124
+ # Add file extension to allow image saving in disk.
125
+ if os.path.splitext(image_path)[-1] == "":
126
+ image_path += ".png"
127
+
128
+ instance = DetectionInstance(image_path)
129
+ instance.height = height
130
+ instance.width = width
131
+ instance.image = image
132
+
133
+ labels = (np.squeeze(boxes[..., 4:5].astype(np.int32), axis=1) +
134
+ self.parameters.label_offset)
135
+ boxes = boxes[..., 0:4]
136
+
137
+ if len(boxes) > 0:
138
+ boxes = self.normalizer(
139
+ boxes, (height, width)) if self.normalizer else boxes
140
+ boxes = self.transformer(boxes) if self.transformer else boxes
141
+
142
+ instance.boxes = boxes
143
+ instance.labels = labels
144
+ return instance
145
+ else:
146
+ raise NotImplementedError(
147
+ "Only 'with_boxes' is currently supported for Arrow datasets.")