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.
Files changed (73) hide show
  1. deepview/modelpack/utils/argmax.py +16 -0
  2. edgefirst/validator/__init__.py +1 -0
  3. edgefirst/validator/__main__.py +375 -0
  4. edgefirst/validator/datasets/__init__.py +118 -0
  5. edgefirst/validator/datasets/cache.py +296 -0
  6. edgefirst/validator/datasets/core.py +250 -0
  7. edgefirst/validator/datasets/darknet.py +446 -0
  8. edgefirst/validator/datasets/database.py +1067 -0
  9. edgefirst/validator/datasets/instance/__init__.py +4 -0
  10. edgefirst/validator/datasets/instance/core.py +222 -0
  11. edgefirst/validator/datasets/instance/detection.py +145 -0
  12. edgefirst/validator/datasets/instance/multitask.py +80 -0
  13. edgefirst/validator/datasets/instance/segmentation.py +120 -0
  14. edgefirst/validator/datasets/utils/fetch.py +682 -0
  15. edgefirst/validator/datasets/utils/readers.py +425 -0
  16. edgefirst/validator/datasets/utils/transformations.py +1695 -0
  17. edgefirst/validator/evaluators/__init__.py +17 -0
  18. edgefirst/validator/evaluators/callbacks/__init__.py +3 -0
  19. edgefirst/validator/evaluators/callbacks/core.py +192 -0
  20. edgefirst/validator/evaluators/callbacks/plots.py +900 -0
  21. edgefirst/validator/evaluators/callbacks/studio.py +234 -0
  22. edgefirst/validator/evaluators/core.py +257 -0
  23. edgefirst/validator/evaluators/detection.py +749 -0
  24. edgefirst/validator/evaluators/multitask.py +270 -0
  25. edgefirst/validator/evaluators/parameters/__init__.py +53 -0
  26. edgefirst/validator/evaluators/parameters/core.py +554 -0
  27. edgefirst/validator/evaluators/parameters/dataset.py +239 -0
  28. edgefirst/validator/evaluators/parameters/model.py +338 -0
  29. edgefirst/validator/evaluators/parameters/validation.py +528 -0
  30. edgefirst/validator/evaluators/segmentation.py +729 -0
  31. edgefirst/validator/evaluators/utils/__init__.py +3 -0
  32. edgefirst/validator/evaluators/utils/classify.py +292 -0
  33. edgefirst/validator/evaluators/utils/match.py +262 -0
  34. edgefirst/validator/evaluators/utils/timer.py +132 -0
  35. edgefirst/validator/metrics/__init__.py +9 -0
  36. edgefirst/validator/metrics/data/__init__.py +7 -0
  37. edgefirst/validator/metrics/data/label.py +668 -0
  38. edgefirst/validator/metrics/data/metrics.py +759 -0
  39. edgefirst/validator/metrics/data/plots.py +476 -0
  40. edgefirst/validator/metrics/data/stats.py +507 -0
  41. edgefirst/validator/metrics/detection.py +595 -0
  42. edgefirst/validator/metrics/segmentation.py +173 -0
  43. edgefirst/validator/metrics/utils/math.py +717 -0
  44. edgefirst/validator/publishers/__init__.py +3 -0
  45. edgefirst/validator/publishers/console.py +147 -0
  46. edgefirst/validator/publishers/studio.py +128 -0
  47. edgefirst/validator/publishers/tensorboard.py +119 -0
  48. edgefirst/validator/publishers/utils/logger.py +111 -0
  49. edgefirst/validator/publishers/utils/table.py +403 -0
  50. edgefirst/validator/runners/__init__.py +8 -0
  51. edgefirst/validator/runners/core.py +727 -0
  52. edgefirst/validator/runners/deepviewrt.py +177 -0
  53. edgefirst/validator/runners/hailo.py +263 -0
  54. edgefirst/validator/runners/keras.py +150 -0
  55. edgefirst/validator/runners/kinara.py +265 -0
  56. edgefirst/validator/runners/offline.py +228 -0
  57. edgefirst/validator/runners/onnx.py +241 -0
  58. edgefirst/validator/runners/processing/decode.py +320 -0
  59. edgefirst/validator/runners/processing/dvapi.py +4192 -0
  60. edgefirst/validator/runners/processing/nms.py +637 -0
  61. edgefirst/validator/runners/processing/outputs.py +507 -0
  62. edgefirst/validator/runners/tensorrt.py +321 -0
  63. edgefirst/validator/runners/tflite.py +221 -0
  64. edgefirst/validator/validate.py +843 -0
  65. edgefirst/validator/visualize/__init__.py +3 -0
  66. edgefirst/validator/visualize/detection.py +623 -0
  67. edgefirst/validator/visualize/segmentation.py +281 -0
  68. edgefirst/validator/visualize/utils/plots.py +635 -0
  69. edgefirst_validator-4.2.1.dist-info/METADATA +111 -0
  70. edgefirst_validator-4.2.1.dist-info/RECORD +73 -0
  71. edgefirst_validator-4.2.1.dist-info/WHEEL +5 -0
  72. edgefirst_validator-4.2.1.dist-info/entry_points.txt +2 -0
  73. edgefirst_validator-4.2.1.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.2.1"
@@ -0,0 +1,375 @@
1
+ import argparse
2
+
3
+ try:
4
+ import ctypes
5
+ import inspect
6
+ from pathlib import Path
7
+
8
+ import nvidia
9
+
10
+ nvpath = Path(inspect.getfile(nvidia)).parent
11
+ cudnn = nvpath / 'cudnn' / 'lib' / 'libcudnn.so.9'
12
+ if cudnn.exists():
13
+ ctypes.CDLL(cudnn.as_posix(), mode=ctypes.RTLD_GLOBAL)
14
+ except ImportError:
15
+ pass
16
+
17
+ from edgefirst.validator import __version__
18
+ from edgefirst.validator.validate import validate
19
+
20
+
21
+ def main():
22
+ parser = argparse.ArgumentParser(
23
+ description=('EdgeFirst Validator'),
24
+ formatter_class=argparse.RawTextHelpFormatter
25
+ )
26
+ parser.add_argument(
27
+ '-V', '--version',
28
+ help="Print the package version.",
29
+ action='version',
30
+ version=__version__
31
+ )
32
+ parser.add_argument(
33
+ 'model',
34
+ help=("The path to the model: \n"
35
+ "- TensorFlow or Keras (**/*.pb), (.h5), (.keras) \n"
36
+ "- TFLite (.tflite) \n"
37
+ "- ONNX (.onnx) \n"
38
+ "- DeepViewRT (.rtm) \n"
39
+ "- Offline (directory of model annotations)."),
40
+ metavar='model.onnx',
41
+ nargs="?",
42
+ type=str,
43
+ default="yolov5s.onnx"
44
+ )
45
+ parser.add_argument(
46
+ 'dataset',
47
+ help=("The absolute or relative path "
48
+ "to the dataset folder or YAML file."),
49
+ metavar='dataset.yaml',
50
+ nargs="?",
51
+ type=str,
52
+ default='samples/coco128.yaml'
53
+ )
54
+
55
+ studio_parser = parser.add_argument_group(
56
+ title="EdgeFirst Studio Parameters",
57
+ description=("Specify the interface parameters "
58
+ "for a direct communication with EdgeFirst Studio.")
59
+ )
60
+ studio_parser.add_argument(
61
+ '--token',
62
+ help="EdgeFirst Studio authentication token.",
63
+ type=str,
64
+ )
65
+ studio_parser.add_argument(
66
+ '--server',
67
+ help="EdgeFirst Studio server.",
68
+ type=str,
69
+ )
70
+ studio_parser.add_argument(
71
+ '--username',
72
+ help="EdgeFirst Studio username.",
73
+ type=str,
74
+ )
75
+ studio_parser.add_argument(
76
+ '--password',
77
+ help="EdgeFirst Studio password.",
78
+ type=str,
79
+ )
80
+ studio_parser.add_argument(
81
+ '--session-id',
82
+ help="Specify the validator session ID from EdgeFirst Studio.",
83
+ type=str,
84
+ )
85
+
86
+ model_parser = parser.add_argument_group(
87
+ title="Model Parameters",
88
+ description="Specify how the model should be run with these parameters."
89
+ )
90
+ model_parser.add_argument(
91
+ '--config',
92
+ help=("Specify the path to 'edgefirst.yaml' "
93
+ "containing the model metadata. This overrides "
94
+ "the metadata embedded in the model."),
95
+ type=str
96
+ )
97
+ model_parser.add_argument(
98
+ '--model-labels',
99
+ help=("Specify the path to the model labels file. This artifact is a "
100
+ "labels.txt file containing model string labels. This is "
101
+ "used to align model output indices to the ground truth indices."),
102
+ type=str,
103
+ )
104
+ model_parser.add_argument(
105
+ '-i', '--nms-iou-threshold',
106
+ help="NMS IoU threshold for valid predictions.",
107
+ default=0.70,
108
+ type=float
109
+ )
110
+ model_parser.add_argument(
111
+ '-t', '--nms-score-threshold',
112
+ help="Set the NMS score threshold for valid scores.",
113
+ default=0.001,
114
+ type=float
115
+ )
116
+ model_parser.add_argument(
117
+ '-m', '--max-detections',
118
+ help="Number of maximum detections for NMS.",
119
+ default=300,
120
+ type=int
121
+ )
122
+ model_parser.add_argument(
123
+ '-e', '--engine',
124
+ help=("Inference Engine. Options include 'cpu', 'gpu', "
125
+ "or a path to the NPU delegate '/usr/lib/libvx_delegate.so'."),
126
+ default='npu',
127
+ type=str
128
+ )
129
+ model_parser.add_argument(
130
+ '-s', '--nms',
131
+ help=("Specify the NMS algorithm. "
132
+ "Default to use the NMS from the HAL decoder."),
133
+ choices=['hal', 'numpy', 'tensorflow', 'torch'],
134
+ default='numpy',
135
+ type=str
136
+ )
137
+ model_parser.add_argument(
138
+ '-n', '--norm',
139
+ help=("Normalization method applied to input images.\n "
140
+ "- raw (default, no processing)\n "
141
+ "- unsigned (0...1)\n "
142
+ "- signed (-1...1)\n "
143
+ "- imagenet (standardization using imagenet)\n "),
144
+ choices=['raw', 'unsigned', 'signed', 'imagenet'],
145
+ default='unsigned',
146
+ type=str
147
+ )
148
+ model_parser.add_argument(
149
+ '-p', '--preprocessing',
150
+ help=("The type of image preprocessing to perform. \n"
151
+ "- letterbox: YOLOv5, YOLOv7 implementation. \n"
152
+ "- pad: Image padding based on YOLOx implementation. \n"
153
+ "- resize: Does not maintain aspect ratio."),
154
+ choices=['letterbox', 'pad', 'resize'],
155
+ default='letterbox',
156
+ type=str
157
+ )
158
+ model_parser.add_argument(
159
+ '-b', '--box-format',
160
+ help=("box format to reorient the bounding box "
161
+ "coordinates: 'xcycwh' (yolo), 'xywh' (coco), "
162
+ "'xyxy' (pascalvoc)."),
163
+ choices=['xcycwh', 'xywh', 'xyxy'],
164
+ default='xyxy',
165
+ type=str
166
+ )
167
+ model_parser.add_argument(
168
+ '-w', '--warmup',
169
+ help="The number of model warmup iterations.",
170
+ default=5,
171
+ type=int
172
+ )
173
+ model_parser.add_argument(
174
+ '-l', '--label-offset',
175
+ help="Label offset when mapping index to string representations.",
176
+ default=0,
177
+ type=int
178
+ )
179
+ model_parser.add_argument(
180
+ '--class-nms',
181
+ help=("By default class-agnostic NMS is deployed. "
182
+ "Specify this option to deploy class-based NMS. "),
183
+ action='store_true'
184
+ )
185
+ model_parser.add_argument(
186
+ '--override',
187
+ help=("This parameter is set to True by default. "
188
+ "When specified, this will use the model "
189
+ "parameters specified in the model metadata "
190
+ "to validate the model. Otherwise, the "
191
+ "command line parameters set are applied."),
192
+ action='store_false'
193
+ )
194
+
195
+ dataset_parser = parser.add_argument_group(
196
+ title="Dataset Parameters",
197
+ description="Specify how the dataset should be read with these parameters."
198
+ )
199
+ dataset_parser.add_argument(
200
+ '--cache',
201
+ help=("Specify the path to cache the dataset "
202
+ "or an existing dataset cache. A dataset cache is an LMDB file."),
203
+ metavar="cache/val.db",
204
+ type=str,
205
+ )
206
+ dataset_parser.add_argument(
207
+ '--dataset-labels',
208
+ help=("Specify the path to the dataset labels.txt file. \n"
209
+ "This can be stored inside the dataset folder "
210
+ "to avoid having to specify this path. \n"
211
+ "Otherwise, the YAML file can embed the labels. \n"
212
+ "This is used to map dataset indices to strings representations."),
213
+ type=str
214
+ )
215
+ dataset_parser.add_argument(
216
+ '--annotation-format',
217
+ help=("Specify the format of the annotations: "
218
+ "'xcycwh' (yolo), 'xywh' (coco), 'xyxy' (pascalvoc)."),
219
+ choices=['xcycwh', 'xywh', 'xyxy'],
220
+ default='xcycwh',
221
+ type=str
222
+ )
223
+ dataset_parser.add_argument(
224
+ '--absolute-annotations',
225
+ help=("This specifies that the annotations "
226
+ "are not normalized to the image dimensions. "
227
+ "Otherwise, by default the annotations "
228
+ "are normalized."),
229
+ action='store_false'
230
+ )
231
+ dataset_parser.add_argument(
232
+ '--gt-label-offset',
233
+ help=("The label offset to use for the ground truth "
234
+ "mapping integer labels to string labels."),
235
+ default=0,
236
+ type=int
237
+ )
238
+ dataset_parser.add_argument(
239
+ '--backend',
240
+ help="Specify the library to use for input preprocessing",
241
+ choices=["hal", "opencv", "pillow"],
242
+ default="pillow",
243
+ type=str
244
+ )
245
+ dataset_parser.add_argument(
246
+ '--show-missing-annotations',
247
+ help="List the images without annotations on the terminal",
248
+ action='store_true'
249
+ )
250
+
251
+ val_parser = parser.add_argument_group(
252
+ title="Validation Parameters",
253
+ description=("Specify additional validation settings "
254
+ "for metric computations and visualizations.")
255
+ )
256
+ val_parser.add_argument(
257
+ '--method',
258
+ help=("Specify the validation method to deploy. "
259
+ "The method to reproduce metrics from Ultralytics "
260
+ "or other validator sources such as YOLOv7 or "
261
+ "internal Au-Zone validation methods and metrics."),
262
+ choices=["ultralytics", "yolov7", "edgefirst"],
263
+ default="ultralytics",
264
+ type=str
265
+ )
266
+ val_parser.add_argument(
267
+ '--validation-iou',
268
+ help=("Validation IoU threshold "
269
+ "to consider as true positives. Detections with IoU "
270
+ "lower than this threshold are classified as "
271
+ "localization false positives. This is used in the "
272
+ "edgefirst method of validation."),
273
+ default=0.50,
274
+ type=float
275
+ )
276
+ val_parser.add_argument(
277
+ '--validation-score',
278
+ help=("Validation Score threshold used in the edgefirst "
279
+ "method of validation."),
280
+ default=0.00,
281
+ type=float
282
+ )
283
+ val_parser.add_argument(
284
+ '--metric',
285
+ help=("Specify the metric to use when "
286
+ "matching model predictions to ground truth."),
287
+ choices=['iou', 'centerpoint'],
288
+ default='iou',
289
+ type=str
290
+ )
291
+ val_parser.add_argument(
292
+ '--matching-leniency',
293
+ help=("Distance metric to be considered a valid match "
294
+ "when using the 'centerpoint' metric. "
295
+ "Default is 2 where the distance is no "
296
+ "more than twice the size of the bounding box. \n"),
297
+ default=2,
298
+ type=int
299
+ )
300
+ val_parser.add_argument(
301
+ '--clamp-boxes',
302
+ help=("The value to clamp the minimum width or height "
303
+ "of the bounding boxes of the ground truth and "
304
+ "predictions in pixels."),
305
+ type=int
306
+ )
307
+ val_parser.add_argument(
308
+ '--ignore-boxes',
309
+ help=("Ignore the bounding boxes "
310
+ "of the detections and the ground truth with "
311
+ "height or width less than this value in pixels."),
312
+ type=int
313
+ )
314
+ val_parser.add_argument(
315
+ '--display',
316
+ help=("How many images to display into tensorboard "
317
+ "or to save in disk. By default it is (-1) all "
318
+ "the images are saved. but any integer can be passed."),
319
+ default=-1,
320
+ type=int
321
+ )
322
+ val_parser.add_argument(
323
+ '--suppress-plots',
324
+ help=("Specify to exclude the plots data in the "
325
+ "JSON summary and/or save the plots as images if "
326
+ "visualize or tensorboard parameter is set."),
327
+ action="store_false"
328
+ )
329
+ val_parser.add_argument(
330
+ '--visualize',
331
+ help=("Path to store visualizations "
332
+ "(images with bounding boxes "
333
+ "or segmentation masks) in disk."),
334
+ type=str
335
+ )
336
+ val_parser.add_argument(
337
+ '--tensorboard',
338
+ help="Path to store *.tfevents files in disk needed for Tensorboard.",
339
+ type=str
340
+ )
341
+ val_parser.add_argument(
342
+ '--json-out',
343
+ help=("Path to save the validation JSON files in disk. These files "
344
+ "are typically formatted as ApexCharts for EdgeFirst Studio "
345
+ "visualizations."),
346
+ type=str
347
+ )
348
+ val_parser.add_argument(
349
+ '--csv',
350
+ help=("Path to save a CSV file to store the metrics into a table. "
351
+ "If the CSV file already exists, it appends a new row to "
352
+ "the contents. Otherwise the CSV file is created."),
353
+ metavar="metrics.csv",
354
+ type=str
355
+ )
356
+ val_parser.add_argument(
357
+ '--include-background',
358
+ help=("This is used for segmentation. "
359
+ "This allows evaluation of the "
360
+ "background class as part of validation."),
361
+ action="store_true"
362
+ )
363
+ val_parser.add_argument(
364
+ '--exclude-symbols',
365
+ help=("Specify whether to exclude symbols when "
366
+ "logging messages on the terminal."),
367
+ action="store_false"
368
+ )
369
+ args = parser.parse_args()
370
+
371
+ validate(args)
372
+
373
+
374
+ if __name__ == '__main__':
375
+ main()
@@ -0,0 +1,118 @@
1
+ import os
2
+
3
+ from edgefirst.validator.datasets.instance import (Instance, DetectionInstance,
4
+ SegmentationInstance,
5
+ MultitaskInstance)
6
+ from edgefirst.validator.datasets.core import Dataset
7
+ from edgefirst.validator.datasets.darknet import DarkNetDataset
8
+ from edgefirst.validator.datasets.database import (EdgeFirstDatabase,
9
+ LMDBDatabase)
10
+ from edgefirst.validator.datasets.cache import StudioCache
11
+
12
+ from edgefirst.validator.datasets.utils.fetch import download_and_extract
13
+ from edgefirst.validator.publishers.utils.logger import logger
14
+
15
+
16
+ def instantiate_dataset(
17
+ info_dataset: dict,
18
+ parameters,
19
+ timer
20
+ ) -> Dataset:
21
+ """
22
+ This function instantiates either darknet or tfrecord
23
+ format dataset objects.
24
+
25
+ Parameters
26
+ ----------
27
+ info_dataset: dict
28
+ If the dataset is Darknet, this contains information such as:
29
+
30
+ .. code-block:: python
31
+
32
+ {
33
+ "classes": [list of unique labels],
34
+ "type": "darknet",
35
+ "validation":
36
+ {
37
+ "images: 'path to the images',
38
+ "annotations": 'path to the annotations'
39
+ },
40
+ }
41
+
42
+ *Note: the classes are optional and the path to the images
43
+ and annotations can be the same.*
44
+
45
+ If the dataset is tfrecord, this contains information such as:
46
+
47
+ .. code-block:: python
48
+
49
+ {
50
+ "classes": [list of unique labels],
51
+ "validation": {
52
+ "path": path to the *.tfrecord files.
53
+ }
54
+ }
55
+ parameters: DatasetParameters
56
+ A container for the dataset parameters set from the command line.
57
+ timer: TimerContext
58
+ A timer object for handling validation timings for the model.
59
+
60
+ Returns
61
+ -------
62
+ Dataset
63
+ This object is returned depending on the type of the dataset provided.
64
+
65
+ Raises
66
+ ------
67
+ InvalidDatasetSourceException
68
+ Raised if the path to the images or annotations is None.
69
+ DatasetNotFoundException
70
+ Raised if the provided path to the images or
71
+ annotations does not exist.
72
+ ValueError
73
+ Raised if the provided path to the images or
74
+ annotations is not a string.
75
+ EmptyDatasetException
76
+ Raised if the provided path to the images or
77
+ text files does not contain any image files or
78
+ text files respectively.
79
+ """
80
+ if "download" in info_dataset.keys():
81
+ url = info_dataset.get("download")
82
+ download_path = os.path.join(os.getcwd(),
83
+ f"samples/{os.path.basename(url)}")
84
+ if not os.path.exists(download_path):
85
+ download_and_extract(url=url, download_path=download_path)
86
+
87
+ try:
88
+ ds_format = info_dataset.get('type')
89
+ if ds_format is None:
90
+ ds_format = info_dataset.get("dataset").get("format")
91
+ except AttributeError:
92
+ logger("Dataset was not properly read. Ensure the dataset " +
93
+ "structure follows images/validate and labels/validate.",
94
+ code="ERROR")
95
+
96
+ if ds_format in [None, "darknet"]:
97
+ return DarkNetDataset(
98
+ source=parameters.dataset_path,
99
+ parameters=parameters,
100
+ timer=timer,
101
+ info_dataset=info_dataset,
102
+ )
103
+ elif ds_format == "lmdb":
104
+ return LMDBDatabase(
105
+ source=parameters.dataset_path,
106
+ parameters=parameters,
107
+ timer=timer,
108
+ info_dataset=info_dataset,
109
+ )
110
+ elif ds_format == "edgefirst":
111
+ return EdgeFirstDatabase(
112
+ source=parameters.dataset_path,
113
+ parameters=parameters,
114
+ timer=timer,
115
+ info_dataset=info_dataset,
116
+ )
117
+ else:
118
+ raise TypeError(f"Dataset format {ds_format} is not recognized.")