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,759 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Metrics:
|
|
5
|
+
"""
|
|
6
|
+
Container used to store the validation metrics of the model.
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
model: str
|
|
11
|
+
The path or name of the model.
|
|
12
|
+
dataset: str
|
|
13
|
+
The path or name of the validation dataset.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
model: str = "Model",
|
|
19
|
+
dataset: str = "Dataset",
|
|
20
|
+
):
|
|
21
|
+
self.__model = model
|
|
22
|
+
self.__dataset = dataset
|
|
23
|
+
self.__save_path = None
|
|
24
|
+
self.reset()
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def model(self) -> str:
|
|
28
|
+
"""
|
|
29
|
+
Attribute to access the model path/name.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
str
|
|
34
|
+
The model path/name.
|
|
35
|
+
"""
|
|
36
|
+
return self.__model
|
|
37
|
+
|
|
38
|
+
@model.setter
|
|
39
|
+
def model(self, model_path: str):
|
|
40
|
+
"""
|
|
41
|
+
Sets the model path/name.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
model_path: str
|
|
46
|
+
The model path/name.
|
|
47
|
+
"""
|
|
48
|
+
self.__model = model_path
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def dataset(self) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Attribute to access the dataset path/name.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
str
|
|
58
|
+
The dataset path/name.
|
|
59
|
+
"""
|
|
60
|
+
return self.__dataset
|
|
61
|
+
|
|
62
|
+
@dataset.setter
|
|
63
|
+
def dataset(self, dataset_path: str):
|
|
64
|
+
"""
|
|
65
|
+
Sets the dataset path/name.
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
dataset_path: str
|
|
70
|
+
The dataset path/name
|
|
71
|
+
"""
|
|
72
|
+
self.__dataset = dataset_path
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def save_path(self) -> str:
|
|
76
|
+
"""
|
|
77
|
+
Attribute to access the path to save the results.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
str
|
|
82
|
+
The path to save the results.
|
|
83
|
+
"""
|
|
84
|
+
return self.__save_path
|
|
85
|
+
|
|
86
|
+
@save_path.setter
|
|
87
|
+
def save_path(self, this_save_path: str):
|
|
88
|
+
"""
|
|
89
|
+
Sets the path to save the results.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
this_save_path: str
|
|
94
|
+
The path to save the results
|
|
95
|
+
"""
|
|
96
|
+
self.__save_path = this_save_path
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def ground_truths(self) -> int:
|
|
100
|
+
"""
|
|
101
|
+
Attribute to access the number of ground truths.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
int
|
|
106
|
+
The number of ground truths in the dataset.
|
|
107
|
+
"""
|
|
108
|
+
return self.__ground_truths
|
|
109
|
+
|
|
110
|
+
@ground_truths.setter
|
|
111
|
+
def ground_truths(self, gts: int):
|
|
112
|
+
"""
|
|
113
|
+
Sets the number of ground truths in the dataset.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
gts: int
|
|
118
|
+
This is the number of ground truths in the dataset.
|
|
119
|
+
"""
|
|
120
|
+
self.__ground_truths = gts
|
|
121
|
+
|
|
122
|
+
def add_ground_truths(self, gts: int):
|
|
123
|
+
"""
|
|
124
|
+
Adds the number of existing ground truths.
|
|
125
|
+
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
gts: int
|
|
129
|
+
The number of ground truths to add.
|
|
130
|
+
"""
|
|
131
|
+
self.__ground_truths += gts
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def predictions(self) -> int:
|
|
135
|
+
"""
|
|
136
|
+
Attribute to access the number of predictions.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
int
|
|
141
|
+
The total number of predictions.
|
|
142
|
+
"""
|
|
143
|
+
return self.__predictions
|
|
144
|
+
|
|
145
|
+
@predictions.setter
|
|
146
|
+
def predictions(self, prd: int):
|
|
147
|
+
"""
|
|
148
|
+
Sets the total number of predictions.
|
|
149
|
+
|
|
150
|
+
Parameters
|
|
151
|
+
----------
|
|
152
|
+
prd: int
|
|
153
|
+
This is the total number of predictions.
|
|
154
|
+
"""
|
|
155
|
+
self.__predictions = prd
|
|
156
|
+
|
|
157
|
+
def add_predictions(self, prd: int):
|
|
158
|
+
"""
|
|
159
|
+
Adds the number of existing predictions.
|
|
160
|
+
|
|
161
|
+
Parameters
|
|
162
|
+
----------
|
|
163
|
+
prd: int
|
|
164
|
+
The number of predictions to add.
|
|
165
|
+
"""
|
|
166
|
+
self.__predictions += prd
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def tp(self) -> int:
|
|
170
|
+
"""
|
|
171
|
+
Attribute to access the number of true positives.
|
|
172
|
+
|
|
173
|
+
Returns
|
|
174
|
+
-------
|
|
175
|
+
int
|
|
176
|
+
The total number of true positives.
|
|
177
|
+
"""
|
|
178
|
+
return self.__tp
|
|
179
|
+
|
|
180
|
+
@tp.setter
|
|
181
|
+
def tp(self, tps: int):
|
|
182
|
+
"""
|
|
183
|
+
Sets the total number of true positives.
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
tps: int
|
|
188
|
+
This is the total number of true positives.
|
|
189
|
+
"""
|
|
190
|
+
self.__tp = tps
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def fn(self) -> int:
|
|
194
|
+
"""
|
|
195
|
+
Attribute to access the number of false negatives.
|
|
196
|
+
|
|
197
|
+
Returns
|
|
198
|
+
-------
|
|
199
|
+
int
|
|
200
|
+
The total number of false negatives.
|
|
201
|
+
"""
|
|
202
|
+
self.__fn = self.ground_truths - (self.tp + self.cfp)
|
|
203
|
+
return self.__fn
|
|
204
|
+
|
|
205
|
+
@fn.setter
|
|
206
|
+
def fn(self, fns: int):
|
|
207
|
+
"""
|
|
208
|
+
Sets the total number of false negatives.
|
|
209
|
+
|
|
210
|
+
Parameters
|
|
211
|
+
----------
|
|
212
|
+
fns: int
|
|
213
|
+
This is the total number of false negatives.
|
|
214
|
+
"""
|
|
215
|
+
self.__fn = fns
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def cfp(self) -> int:
|
|
219
|
+
"""
|
|
220
|
+
Attribute to access the number of classification false positives.
|
|
221
|
+
|
|
222
|
+
Returns
|
|
223
|
+
-------
|
|
224
|
+
int
|
|
225
|
+
The total number of classification false positives.
|
|
226
|
+
"""
|
|
227
|
+
return self.__cfp
|
|
228
|
+
|
|
229
|
+
@cfp.setter
|
|
230
|
+
def cfp(self, fps: int):
|
|
231
|
+
"""
|
|
232
|
+
Sets the total number of classification false positives.
|
|
233
|
+
|
|
234
|
+
Parameters
|
|
235
|
+
----------
|
|
236
|
+
fps: int
|
|
237
|
+
This is the total number of classification false positives.
|
|
238
|
+
"""
|
|
239
|
+
self.__cfp = fps
|
|
240
|
+
|
|
241
|
+
@property
|
|
242
|
+
def lfp(self) -> int:
|
|
243
|
+
"""
|
|
244
|
+
Attribute to access the number of localization false positives.
|
|
245
|
+
|
|
246
|
+
Returns
|
|
247
|
+
-------
|
|
248
|
+
int
|
|
249
|
+
The total number of localization false positives.
|
|
250
|
+
"""
|
|
251
|
+
return self.__lfp
|
|
252
|
+
|
|
253
|
+
@lfp.setter
|
|
254
|
+
def lfp(self, fps: int):
|
|
255
|
+
"""
|
|
256
|
+
Sets the total number of localization false positives.
|
|
257
|
+
|
|
258
|
+
Parameters
|
|
259
|
+
----------
|
|
260
|
+
fps: int
|
|
261
|
+
This is the total number of localization false positives.
|
|
262
|
+
"""
|
|
263
|
+
self.__lfp = fps
|
|
264
|
+
|
|
265
|
+
@property
|
|
266
|
+
def precision(self) -> dict:
|
|
267
|
+
"""
|
|
268
|
+
Attribute to access the precision metric.
|
|
269
|
+
|
|
270
|
+
Returns
|
|
271
|
+
-------
|
|
272
|
+
dict:
|
|
273
|
+
The precision scores which contains "overall", "mean", and
|
|
274
|
+
"map" keys.
|
|
275
|
+
"""
|
|
276
|
+
return self.__precision
|
|
277
|
+
|
|
278
|
+
@precision.setter
|
|
279
|
+
def precision(self, this_precision: dict):
|
|
280
|
+
"""
|
|
281
|
+
Sets the precision metric.
|
|
282
|
+
|
|
283
|
+
Parameters
|
|
284
|
+
----------
|
|
285
|
+
this_precision: dict
|
|
286
|
+
The precision dictionary to set which contains
|
|
287
|
+
the keys "overall", "mean", and "map".
|
|
288
|
+
"""
|
|
289
|
+
self.__precision = this_precision
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def recall(self) -> dict:
|
|
293
|
+
"""
|
|
294
|
+
Attribute to access the recall metric.
|
|
295
|
+
|
|
296
|
+
Returns
|
|
297
|
+
-------
|
|
298
|
+
dict
|
|
299
|
+
The recall scores which contains keys "overall", "mean", and "mar".
|
|
300
|
+
"""
|
|
301
|
+
return self.__recall
|
|
302
|
+
|
|
303
|
+
@recall.setter
|
|
304
|
+
def recall(self, this_recall: dict):
|
|
305
|
+
"""
|
|
306
|
+
Sets the recall metric.
|
|
307
|
+
|
|
308
|
+
Parameters
|
|
309
|
+
----------
|
|
310
|
+
this_recall: dict
|
|
311
|
+
The recall to set which contains keys "overall", "mean", and "mar".
|
|
312
|
+
"""
|
|
313
|
+
self.__recall = this_recall
|
|
314
|
+
|
|
315
|
+
@property
|
|
316
|
+
def accuracy(self) -> dict:
|
|
317
|
+
"""
|
|
318
|
+
Attribute to access the accuracy metric.
|
|
319
|
+
|
|
320
|
+
Returns
|
|
321
|
+
-------
|
|
322
|
+
dict
|
|
323
|
+
The accuracy to set which contains keys "overall", "mean", and "macc".
|
|
324
|
+
"""
|
|
325
|
+
return self.__accuracy
|
|
326
|
+
|
|
327
|
+
@accuracy.setter
|
|
328
|
+
def accuracy(self, this_accuracy: dict):
|
|
329
|
+
"""
|
|
330
|
+
Sets the accuracy metric.
|
|
331
|
+
|
|
332
|
+
Parameters
|
|
333
|
+
----------
|
|
334
|
+
this_accuracy: dict
|
|
335
|
+
The accuracy to set which contains keys: "overall", "mean", "macc".
|
|
336
|
+
"""
|
|
337
|
+
self.__accuracy = this_accuracy
|
|
338
|
+
|
|
339
|
+
@property
|
|
340
|
+
def f1(self) -> dict:
|
|
341
|
+
"""
|
|
342
|
+
Attribute to access the F1 metric.
|
|
343
|
+
|
|
344
|
+
Returns
|
|
345
|
+
-------
|
|
346
|
+
dict
|
|
347
|
+
The F1 to set which contains keys: "overall", "mean", "mf1".
|
|
348
|
+
"""
|
|
349
|
+
return self.__f1
|
|
350
|
+
|
|
351
|
+
@f1.setter
|
|
352
|
+
def f1(self, this_f1: dict):
|
|
353
|
+
"""
|
|
354
|
+
Sets the F1 metric.
|
|
355
|
+
|
|
356
|
+
Parameters
|
|
357
|
+
----------
|
|
358
|
+
this_f1: dict
|
|
359
|
+
The F1 to set which contains keys: "overall", "mean", "mf1".
|
|
360
|
+
"""
|
|
361
|
+
self.__f1 = this_f1
|
|
362
|
+
|
|
363
|
+
@property
|
|
364
|
+
def iou(self) -> dict:
|
|
365
|
+
"""
|
|
366
|
+
Attribute to access the IoU metric.
|
|
367
|
+
|
|
368
|
+
Returns
|
|
369
|
+
-------
|
|
370
|
+
dict
|
|
371
|
+
The IoU to set which contains keys: "overall", "mean".
|
|
372
|
+
"""
|
|
373
|
+
return self.__iou
|
|
374
|
+
|
|
375
|
+
@iou.setter
|
|
376
|
+
def iou(self, this_iou: dict):
|
|
377
|
+
"""
|
|
378
|
+
Sets the IoU metric.
|
|
379
|
+
|
|
380
|
+
Parameters
|
|
381
|
+
----------
|
|
382
|
+
this_iou: dict
|
|
383
|
+
The IoU to set which contains keys: "overall", "mean".
|
|
384
|
+
"""
|
|
385
|
+
self.__iou = this_iou
|
|
386
|
+
|
|
387
|
+
@property
|
|
388
|
+
def true_predictions(self) -> int:
|
|
389
|
+
"""
|
|
390
|
+
Attribute to access the total number of true predictions.
|
|
391
|
+
|
|
392
|
+
Returns
|
|
393
|
+
-------
|
|
394
|
+
int
|
|
395
|
+
The total number of true predictions for segmentation.
|
|
396
|
+
"""
|
|
397
|
+
return self.__true_predictions
|
|
398
|
+
|
|
399
|
+
@true_predictions.setter
|
|
400
|
+
def true_predictions(self, tps: int):
|
|
401
|
+
"""
|
|
402
|
+
Sets the total number of true predictions for segmentation.
|
|
403
|
+
|
|
404
|
+
Parameters
|
|
405
|
+
----------
|
|
406
|
+
tps: int
|
|
407
|
+
This is the total number of true predictions for segmentation.
|
|
408
|
+
"""
|
|
409
|
+
self.__true_predictions = tps
|
|
410
|
+
|
|
411
|
+
def add_true_predictions(self, tps: int = 1):
|
|
412
|
+
"""
|
|
413
|
+
Adds the number of true predictions for segmentation.
|
|
414
|
+
|
|
415
|
+
Parameters
|
|
416
|
+
----------
|
|
417
|
+
tps: int
|
|
418
|
+
The number of true predictions to add for segmentation.
|
|
419
|
+
"""
|
|
420
|
+
self.__true_predictions += tps
|
|
421
|
+
|
|
422
|
+
@property
|
|
423
|
+
def false_predictions(self) -> int:
|
|
424
|
+
"""
|
|
425
|
+
Attribute to access the total number of false
|
|
426
|
+
predictions for segmentation.
|
|
427
|
+
|
|
428
|
+
Returns
|
|
429
|
+
-------
|
|
430
|
+
int
|
|
431
|
+
The total number of false predictions for segmentation.
|
|
432
|
+
"""
|
|
433
|
+
return self.__false_predictions
|
|
434
|
+
|
|
435
|
+
@false_predictions.setter
|
|
436
|
+
def false_predictions(self, fps: int):
|
|
437
|
+
"""
|
|
438
|
+
Sets the total total number of false predictions for segmentation.
|
|
439
|
+
|
|
440
|
+
Parameters
|
|
441
|
+
----------
|
|
442
|
+
fps: int
|
|
443
|
+
This is the total number of false prediction for segmentation.
|
|
444
|
+
"""
|
|
445
|
+
self.__false_predictions = fps
|
|
446
|
+
|
|
447
|
+
def add_false_predictions(self, fps: int = 1):
|
|
448
|
+
"""
|
|
449
|
+
Adds the number of false predictions for segmentation.
|
|
450
|
+
|
|
451
|
+
Parameters
|
|
452
|
+
----------
|
|
453
|
+
fps: int
|
|
454
|
+
The number of false predictions to add for segmentation.
|
|
455
|
+
"""
|
|
456
|
+
self.__false_predictions += fps
|
|
457
|
+
|
|
458
|
+
@property
|
|
459
|
+
def union(self) -> int:
|
|
460
|
+
"""
|
|
461
|
+
Attribute to access the number of union pixels.
|
|
462
|
+
|
|
463
|
+
Returns
|
|
464
|
+
-------
|
|
465
|
+
int
|
|
466
|
+
The number of ground truths and prediction pixels for the dataset.
|
|
467
|
+
"""
|
|
468
|
+
return self.__union
|
|
469
|
+
|
|
470
|
+
@union.setter
|
|
471
|
+
def union(self, uni: int):
|
|
472
|
+
"""
|
|
473
|
+
Sets the number of ground truths and
|
|
474
|
+
prediction pixels for the dataset.
|
|
475
|
+
|
|
476
|
+
Parameters
|
|
477
|
+
----------
|
|
478
|
+
uni: int
|
|
479
|
+
This is the number of union for this dataset.
|
|
480
|
+
"""
|
|
481
|
+
self.__union = uni
|
|
482
|
+
|
|
483
|
+
def add_union(self, uni: int = 1):
|
|
484
|
+
"""
|
|
485
|
+
Adds the number of existing union pixels.
|
|
486
|
+
|
|
487
|
+
Parameters
|
|
488
|
+
----------
|
|
489
|
+
uni: int
|
|
490
|
+
The number of union pixels to add.
|
|
491
|
+
"""
|
|
492
|
+
self.__union += uni
|
|
493
|
+
|
|
494
|
+
@property
|
|
495
|
+
def timings(self) -> dict:
|
|
496
|
+
"""
|
|
497
|
+
Attribute to access the model timings.
|
|
498
|
+
|
|
499
|
+
Returns
|
|
500
|
+
-------
|
|
501
|
+
dict
|
|
502
|
+
The model timings.
|
|
503
|
+
"""
|
|
504
|
+
return self.__timings
|
|
505
|
+
|
|
506
|
+
@timings.setter
|
|
507
|
+
def timings(self, this_timings: Union[dict, None]):
|
|
508
|
+
"""
|
|
509
|
+
Sets the timings of the model.
|
|
510
|
+
|
|
511
|
+
Parameters
|
|
512
|
+
----------
|
|
513
|
+
this_timings: Union[dict, None]
|
|
514
|
+
The model timings.
|
|
515
|
+
"""
|
|
516
|
+
self.__timings = this_timings
|
|
517
|
+
|
|
518
|
+
def reset(self):
|
|
519
|
+
"""
|
|
520
|
+
Resets the data for the metrics to the default state.
|
|
521
|
+
"""
|
|
522
|
+
self.__ground_truths = 0
|
|
523
|
+
# This is used for segmentation to contain
|
|
524
|
+
# total number of prediction pixels.
|
|
525
|
+
self.__predictions = 0
|
|
526
|
+
|
|
527
|
+
"""Detection Metrics"""
|
|
528
|
+
self.__tp = 0 # True Positives
|
|
529
|
+
self.__fn = 0 # False Negatives
|
|
530
|
+
self.__cfp = 0 # Classification False Positives
|
|
531
|
+
self.__lfp = 0 # Localization False Positives
|
|
532
|
+
|
|
533
|
+
self.__precision = {
|
|
534
|
+
"overall": 0,
|
|
535
|
+
# Storing YOLO mean precision or segmentation precision here.
|
|
536
|
+
"mean": 0,
|
|
537
|
+
"map": {
|
|
538
|
+
"0.50": 0,
|
|
539
|
+
"0.75": 0,
|
|
540
|
+
"0.50:0.95": 0,
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
self.__recall = {
|
|
545
|
+
"overall": 0,
|
|
546
|
+
"mean": 0, # Storing YOLO mean recall or segmentation recall here.
|
|
547
|
+
"mar": {
|
|
548
|
+
"0.50": 0,
|
|
549
|
+
"0.75": 0,
|
|
550
|
+
"0.50:0.95": 0,
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
self.__accuracy = {
|
|
555
|
+
"overall": 0,
|
|
556
|
+
"mean": 0, # Storing segmentation accuracy here.
|
|
557
|
+
"macc": {
|
|
558
|
+
"0.50": 0,
|
|
559
|
+
"0.75": 0,
|
|
560
|
+
"0.50:0.95": 0,
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
self.__f1 = {
|
|
565
|
+
"overall": 0,
|
|
566
|
+
"mean": 0, # Storing YOLO mean F1 score.
|
|
567
|
+
"maf1": {
|
|
568
|
+
"0.50": 0,
|
|
569
|
+
"0.75": 0,
|
|
570
|
+
"0.50:0.95": 0,
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
self.__iou = {
|
|
575
|
+
"overall": 0,
|
|
576
|
+
"mean": 0
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
"""Segmentation Metrics"""
|
|
580
|
+
self.__true_predictions = 0
|
|
581
|
+
self.__false_predictions = 0
|
|
582
|
+
self.__union = 0
|
|
583
|
+
|
|
584
|
+
self.__timings = {
|
|
585
|
+
'min_read_time': 0,
|
|
586
|
+
'max_read_time': 0,
|
|
587
|
+
'min_load_time': 0,
|
|
588
|
+
'max_load_time': 0,
|
|
589
|
+
'min_backbone_time': 0,
|
|
590
|
+
'max_backbone_time': 0,
|
|
591
|
+
'min_decode_time': 0,
|
|
592
|
+
'max_decode_time': 0,
|
|
593
|
+
'min_box_time': 0,
|
|
594
|
+
'max_box_time': 0,
|
|
595
|
+
'avg_read_time': 0,
|
|
596
|
+
'avg_load_time': 0,
|
|
597
|
+
'avg_backbone_time': 0,
|
|
598
|
+
'avg_decode_time': 0,
|
|
599
|
+
'avg_box_time': 0,
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
def to_dict(
|
|
603
|
+
self,
|
|
604
|
+
with_boxes: bool = True,
|
|
605
|
+
method: str = "ultralytics"
|
|
606
|
+
) -> dict:
|
|
607
|
+
"""
|
|
608
|
+
Convert the metrics container into a dictionary.
|
|
609
|
+
|
|
610
|
+
Parameters
|
|
611
|
+
----------
|
|
612
|
+
with_boxes: bool
|
|
613
|
+
If this is set to True, the dictionary
|
|
614
|
+
will only contain bounding box metrics.
|
|
615
|
+
If set to False, the dictionary
|
|
616
|
+
will contain segmentation metrics.
|
|
617
|
+
method: str
|
|
618
|
+
Specify the validation method. Options are
|
|
619
|
+
"ultralytics" (default), "edgefirst", "yolov7".
|
|
620
|
+
|
|
621
|
+
Returns
|
|
622
|
+
-------
|
|
623
|
+
dict
|
|
624
|
+
The metrics as a dictionary.
|
|
625
|
+
"""
|
|
626
|
+
metrics = dict()
|
|
627
|
+
|
|
628
|
+
if with_boxes:
|
|
629
|
+
if method in ["ultralytics", "yolov7"]:
|
|
630
|
+
metrics["ground_truth"] = self.ground_truths
|
|
631
|
+
metrics["precision"] = {k: v for k, v in self.precision.items()
|
|
632
|
+
if k != "overall"}
|
|
633
|
+
metrics["recall"] = {k: v for k, v in self.recall.items()
|
|
634
|
+
if k not in ["overall", "mar"]}
|
|
635
|
+
metrics["F1"] = {k: v for k, v in self.f1.items()
|
|
636
|
+
if k not in ["overall", "maf1"]}
|
|
637
|
+
else:
|
|
638
|
+
metrics["ground_truth"] = self.ground_truths
|
|
639
|
+
metrics["true_positives"] = self.tp
|
|
640
|
+
metrics["false_negatives"] = self.fn
|
|
641
|
+
metrics["classification_false_positives"] = self.cfp
|
|
642
|
+
metrics["localization_false_positives"] = self.lfp
|
|
643
|
+
metrics["precision"] = {k: v for k, v in self.precision.items()
|
|
644
|
+
if k != "mean"}
|
|
645
|
+
metrics["recall"] = {k: v for k, v in self.recall.items()
|
|
646
|
+
if k != "mean"}
|
|
647
|
+
metrics["accuracy"] = {k: v for k, v in self.accuracy.items()
|
|
648
|
+
if k != "mean"}
|
|
649
|
+
else:
|
|
650
|
+
metrics["ground_truth"] = self.ground_truths
|
|
651
|
+
metrics["true_predictions"] = self.true_predictions
|
|
652
|
+
metrics["false_predictions"] = self.false_predictions
|
|
653
|
+
metrics["union"] = self.union
|
|
654
|
+
metrics["precision"] = {k: v for k, v in self.precision.items()
|
|
655
|
+
if k != "map"}
|
|
656
|
+
metrics["recall"] = {k: v for k, v in self.recall.items()
|
|
657
|
+
if k != "mar"}
|
|
658
|
+
metrics["accuracy"] = {k: v for k, v in self.accuracy.items()
|
|
659
|
+
if k != "macc"}
|
|
660
|
+
metrics["F1"] = {k: v for k, v in self.f1.items()
|
|
661
|
+
if k not in ["mean", "maf1"]}
|
|
662
|
+
metrics["iou"] = {k: v for k, v in self.iou.items()
|
|
663
|
+
if k != "overall"}
|
|
664
|
+
|
|
665
|
+
metrics["timings"] = self.timings
|
|
666
|
+
return metrics
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
class MultitaskMetrics:
|
|
670
|
+
"""
|
|
671
|
+
Container for Multitask validation metrics
|
|
672
|
+
for segmentation and detection.
|
|
673
|
+
|
|
674
|
+
Parameters
|
|
675
|
+
----------
|
|
676
|
+
detection_metrics: Metrics
|
|
677
|
+
A container for detection metrics.
|
|
678
|
+
segmentation_metrics: Metrics
|
|
679
|
+
A container for segmentation metrics.
|
|
680
|
+
"""
|
|
681
|
+
|
|
682
|
+
def __init__(
|
|
683
|
+
self,
|
|
684
|
+
detection_metrics: Metrics,
|
|
685
|
+
segmentation_metrics: Metrics
|
|
686
|
+
):
|
|
687
|
+
self.detection_metrics = detection_metrics
|
|
688
|
+
self.segmentation_metrics = segmentation_metrics
|
|
689
|
+
|
|
690
|
+
self.__timings = {
|
|
691
|
+
'min_read_time': 0,
|
|
692
|
+
'max_read_time': 0,
|
|
693
|
+
'min_load_time': 0,
|
|
694
|
+
'max_load_time': 0,
|
|
695
|
+
'min_backbone_time': 0,
|
|
696
|
+
'max_backbone_time': 0,
|
|
697
|
+
'min_decode_time': 0,
|
|
698
|
+
'max_decode_time': 0,
|
|
699
|
+
'min_box_time': 0,
|
|
700
|
+
'max_box_time': 0,
|
|
701
|
+
'avg_read_time': 0,
|
|
702
|
+
'avg_load_time': 0,
|
|
703
|
+
'avg_backbone_time': 0,
|
|
704
|
+
'avg_decode_time': 0,
|
|
705
|
+
'avg_box_time': 0,
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
@property
|
|
709
|
+
def timings(self) -> dict:
|
|
710
|
+
"""
|
|
711
|
+
Attribute to access the model timings.
|
|
712
|
+
|
|
713
|
+
Returns
|
|
714
|
+
-------
|
|
715
|
+
dict
|
|
716
|
+
The model timings.
|
|
717
|
+
"""
|
|
718
|
+
return self.__timings
|
|
719
|
+
|
|
720
|
+
@timings.setter
|
|
721
|
+
def timings(self, this_timings: Union[dict, None]):
|
|
722
|
+
"""
|
|
723
|
+
Sets the timings of the model.
|
|
724
|
+
|
|
725
|
+
Parameters
|
|
726
|
+
----------
|
|
727
|
+
this_timings: Union[dict, None]
|
|
728
|
+
The model timings.
|
|
729
|
+
"""
|
|
730
|
+
self.__timings = this_timings
|
|
731
|
+
|
|
732
|
+
def to_dict(self, method: str = "ultralytics") -> dict:
|
|
733
|
+
"""
|
|
734
|
+
Conver the metrics container into a dictionary.
|
|
735
|
+
|
|
736
|
+
Parameters
|
|
737
|
+
----------
|
|
738
|
+
method: str
|
|
739
|
+
Specify the validation method. Options are
|
|
740
|
+
"ultralytics" (default), "edgefirst", "yolov7".
|
|
741
|
+
|
|
742
|
+
Returns
|
|
743
|
+
-------
|
|
744
|
+
dict
|
|
745
|
+
The metrics as a dictionary.
|
|
746
|
+
"""
|
|
747
|
+
|
|
748
|
+
metrics = dict()
|
|
749
|
+
detection = self.detection_metrics.to_dict(
|
|
750
|
+
with_boxes=True, method=method)
|
|
751
|
+
detection.pop("timings")
|
|
752
|
+
|
|
753
|
+
segmentation = self.segmentation_metrics.to_dict(with_boxes=False)
|
|
754
|
+
segmentation.pop("timings")
|
|
755
|
+
|
|
756
|
+
metrics["detection_metrics"] = detection
|
|
757
|
+
metrics["segmentation_metrics"] = segmentation
|
|
758
|
+
metrics["timings"] = self.timings
|
|
759
|
+
return metrics
|