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,241 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import time
5
+ import ctypes
6
+ from typing import TYPE_CHECKING, Any
7
+
8
+ import numpy as np
9
+
10
+ from edgefirst.validator.publishers.utils.logger import logger
11
+ from edgefirst.validator.runners.core import Runner
12
+
13
+ if TYPE_CHECKING:
14
+ from edgefirst.validator.evaluators import ModelParameters, TimerContext
15
+
16
+
17
+ class ONNXRunner(Runner):
18
+ """
19
+ Loads and runs ONNX models for inference.
20
+
21
+ Parameters
22
+ ----------
23
+ model: Any
24
+ This is typically the path to the model (.onnx)
25
+ or the loaded ONNX model.
26
+ parameters: ModelParameters
27
+ These are the model parameters set from the command line.
28
+ metadata: dict
29
+ The model metadata which contains information for decoding
30
+ the model outputs.
31
+ timer: TimerContext
32
+ A timer object for handling validation timings for the model.
33
+
34
+ Raises
35
+ ------
36
+ ImportError
37
+ Missing onnxruntime library.
38
+ FileNotFoundError
39
+ Raised if the path to the model does not exist.
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ model: Any,
45
+ parameters: ModelParameters,
46
+ metadata: dict,
47
+ timer: TimerContext
48
+ ):
49
+ super(ONNXRunner, self).__init__(model, parameters, timer=timer)
50
+
51
+ try:
52
+ import onnxruntime
53
+ except ImportError:
54
+ raise ImportError(
55
+ "onnxruntime or onnxruntime-gpu is needed to run ONNX models.")
56
+
57
+ if isinstance(model, str):
58
+ if not os.path.exists(model):
59
+ raise FileNotFoundError(
60
+ "The model '{}' does not exist.".format(model))
61
+
62
+ providers = self.select_providers()
63
+ logger(f"Selected Providers: {providers}", code="INFO")
64
+ self.model = onnxruntime.InferenceSession(
65
+ model, providers=providers)
66
+
67
+ self.graph_name = self.model.get_modelmeta().graph_name
68
+ self.output_names = [x.name for x in self.model.get_outputs()]
69
+ outputs = self.model.get_outputs()
70
+ self.init_decoder(metadata=metadata, outputs=outputs)
71
+
72
+ if self.parameters.warmup > 0:
73
+ self.warmup()
74
+
75
+ @staticmethod
76
+ def check_tensorrt_runtime() -> list:
77
+ """
78
+ The following libraries are needed to run ONNX
79
+ with TensorrtExecutionProvider.
80
+
81
+ - "libnvinfer.so"
82
+ - "libnvinfer_plugin.so"
83
+ - "libnvonnxparser.so"
84
+
85
+ Returns
86
+ -------
87
+ list
88
+ A list of the libraries that are missing.
89
+ """
90
+ required_libs = ["libnvinfer.so",
91
+ "libnvinfer_plugin.so", "libnvonnxparser.so"]
92
+ missing = []
93
+ for lib in required_libs:
94
+ try:
95
+ ctypes.CDLL(lib)
96
+ except OSError:
97
+ missing.append(lib)
98
+ return missing
99
+
100
+ def select_providers(self) -> list:
101
+ """
102
+ Specify the providers to load based on
103
+ the type of engine specified.
104
+
105
+ Returns
106
+ -------
107
+ list
108
+ A list of the selected providers to deploy.
109
+ """
110
+ import onnxruntime
111
+
112
+ selected_providers = ["CPUExecutionProvider"]
113
+ available_providers = onnxruntime.get_available_providers()
114
+ if self.parameters.engine.lower() == "npu":
115
+ preferred_providers = ["NnapiExecutionProvider",
116
+ "VsiNpuExecutionProvider",
117
+ "TensorrtExecutionProvider",
118
+ "CUDAExecutionProvider",
119
+ "CPUExecutionProvider"]
120
+ selected_providers = []
121
+ for i, provider in enumerate(preferred_providers):
122
+ if provider in available_providers:
123
+ if provider == "TensorrtExecutionProvider":
124
+ missing_libraries = self.check_tensorrt_runtime()
125
+ if missing_libraries:
126
+ logger(f"The libraries {missing_libraries} are " +
127
+ "needed for TensorrtExecutionProvider. " +
128
+ f"Falling back to {preferred_providers[i+1]}.",
129
+ code="WARNING")
130
+ continue
131
+ selected_providers.append(provider)
132
+ else:
133
+ logger(f"{provider} is not present in the system. " +
134
+ f"Falling back to {preferred_providers[i+1]}.",
135
+ code="WARNING")
136
+ if selected_providers in [["TensorrtExecutionProvider",
137
+ "CUDAExecutionProvider",
138
+ "CPUExecutionProvider"],
139
+ ["CUDAExecutionProvider",
140
+ "CPUExecutionProvider"]]:
141
+ self.parameters.engine = "gpu"
142
+ elif selected_providers == ["CPUExecutionProvider"]:
143
+ self.parameters.engine = "cpu"
144
+ elif self.parameters.engine.lower() == "gpu":
145
+ preferred_providers = ["TensorrtExecutionProvider",
146
+ "CUDAExecutionProvider",
147
+ "CPUExecutionProvider"]
148
+ selected_providers = []
149
+ for i, provider in enumerate(preferred_providers):
150
+ if provider in available_providers:
151
+ if provider == "TensorrtExecutionProvider":
152
+ missing_libraries = self.check_tensorrt_runtime()
153
+ if missing_libraries:
154
+ logger(f"The libraries {missing_libraries} are " +
155
+ "needed for TensorrtExecutionProvider. " +
156
+ f"Falling back to {preferred_providers[i+1]}.",
157
+ code="WARNING")
158
+ continue
159
+ selected_providers.append(provider)
160
+ else:
161
+ logger(f"{provider} is not present in the system. " +
162
+ f"Falling back to {preferred_providers[i+1]}.",
163
+ code="WARNING")
164
+ if selected_providers == ["CPUExecutionProvider"]:
165
+ self.parameters.engine = "cpu"
166
+ logger(
167
+ "TensorrtExecutionProvider and CUDAExecutionProvider is " +
168
+ "not present in the system. Falling back to CPUExecutionProvider.",
169
+ code="WARNING")
170
+ return selected_providers
171
+
172
+ def run_single_instance(self, image: np.ndarray) -> Any:
173
+ """
174
+ Run ONNX inference on a single image and record the timings.
175
+
176
+ Parameters
177
+ ----------
178
+ image: np.ndarray
179
+ The input image after being preprocessed.
180
+ Typically this is an RGB image array.
181
+
182
+ Returns
183
+ -------
184
+ Any
185
+ This could either return detection outputs after NMS.
186
+ np.ndarray
187
+ The prediction bounding boxes.. [[box1], [box2], ...].
188
+ np.ndarray
189
+ The prediction labels.. [cl1, cl2, ...].
190
+ np.ndarray
191
+ The prediction confidence scores.. [score, score, ...]
192
+ normalized between 0 and 1.
193
+ This could also return segmentation masks.
194
+ np.ndarray
195
+ """
196
+ # Inference
197
+ with self.timer.time("inference"):
198
+ outputs = self.model.run(self.output_names,
199
+ {self.model.get_inputs()[0].name: image})
200
+
201
+ # Postprocessing
202
+ return self.postprocessing(outputs)
203
+
204
+ def get_input_type(self) -> np.dtype:
205
+ """
206
+ This returns the input type of the model for the
207
+ input with shape in the form
208
+ (batch size, channels, height, width) or
209
+ (batch size, height, width, channels).
210
+
211
+ Returns
212
+ -------
213
+ np.dtype
214
+ The input type of the model.
215
+ """
216
+ if "float16" in self.model.get_inputs()[0].type:
217
+ return np.float16
218
+ elif "float" in self.model.get_inputs()[0].type:
219
+ return np.float32
220
+ elif "uint8" in self.model.get_inputs()[0].type:
221
+ return np.uint8
222
+ elif "int8" in self.model.get_inputs()[0].type:
223
+ return np.int8
224
+ return self.model.get_inputs()[0].type
225
+
226
+ def get_input_shape(self) -> np.ndarray:
227
+ """
228
+ This fetches the model input shape.
229
+
230
+ Returns
231
+ -------
232
+ np.ndarray
233
+ The model input shape
234
+ (batch size, channels, height, width) or
235
+ (batch size, height, width, channels).
236
+ """
237
+ for input in self.model.get_inputs():
238
+ if len(input.shape) == 4:
239
+ if input.shape[1] == 3 or input.shape[-1] == 3:
240
+ return input.shape
241
+ return self.model.get_inputs()[0].shape
@@ -0,0 +1,320 @@
1
+ from typing import Tuple, Union, List
2
+ import copy
3
+
4
+ import numpy as np
5
+
6
+ from edgefirst.validator.metrics.utils.math import sigmoid
7
+ from edgefirst.validator.datasets.utils.transformations import xcycwh2xyxy
8
+
9
+
10
+ def decode_mpk_boxes(
11
+ p: np.ndarray, anchors: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
12
+ """
13
+ Decodes ModelPack boxes into boxes and scores.
14
+
15
+ Parameters
16
+ ----------
17
+ p: np.ndarray
18
+ Raw model output with typical shapes such
19
+ as (1, 9, 15, 21) or (1, 17, 30, 21).
20
+ anchors: np.ndarray
21
+ Model anchors used for decoding the outputs
22
+ sometimes with shape (3, 3).
23
+
24
+ Returns
25
+ -------
26
+ boxes: np.ndarray
27
+ The decoded bounding boxes with shape (1, N, 1, 4).
28
+ scores: np.ndarray
29
+ The decoded scores with shape (1, N, nc) where nc is
30
+ the number of classes.
31
+ """
32
+ p = sigmoid(p)
33
+
34
+ na = anchors.shape[0]
35
+ nc = p.shape[-1] // na - 5
36
+ _, h, w, _ = p.shape
37
+
38
+ p = p.reshape((-1, h, w, na, nc + 5))
39
+ grid = np.meshgrid(np.arange(w), np.arange(h))
40
+ grid = np.expand_dims(np.stack(grid, axis=-1), axis=2)
41
+ grid = np.tile(np.expand_dims(grid, axis=0), [
42
+ 1, 1, 1, na, 1])
43
+
44
+ # Decoding
45
+ xy = p[..., 0:2]
46
+ wh = p[..., 2:4]
47
+ obj = p[..., 4:5]
48
+ probs = p[..., 5:]
49
+
50
+ scores = obj * probs
51
+
52
+ xy = (xy * 2.0 + grid - 0.5) / (w, h)
53
+ wh = (wh * 2) ** 2 * anchors * 0.5
54
+ xyxy = np.concatenate([
55
+ xy - wh,
56
+ xy + wh
57
+ ], axis=-1)
58
+ xyxy = xyxy.reshape((1, -1, 1, 4))
59
+ scores = scores.reshape(1, -1, nc)
60
+
61
+ return xyxy, scores
62
+
63
+
64
+ def decode_yolo_boxes(
65
+ p: np.ndarray,
66
+ with_masks: bool,
67
+ nc: int
68
+ ) -> Tuple[np.ndarray, np.ndarray, Union[np.ndarray, None]]:
69
+ """
70
+ Takes the output from Ultralytics models and decodes
71
+ boxes, scores, classes, and mask coefficients (segmentation models).
72
+
73
+ Parameters
74
+ ----------
75
+ p: np.ndarray
76
+ The model output tensor with shape (1, nc + 4, 8400) or
77
+ (1, nc + 4 + 32, 8400) for detection and segmentation respectively.
78
+ with_masks: bool
79
+ Slice the last 32 values from the output as the mask
80
+ proto coefficients.
81
+ nc: int
82
+ The number of labels.
83
+
84
+ Returns
85
+ -------
86
+ boxes: np.ndarray
87
+ The boxes tensor with shape (8400, 4).
88
+ scores: np.ndarray
89
+ The scores tensor with shape (8400,).
90
+ masks: Union[np.ndarray, None]
91
+ The masks tensor coefficients with shape (8400, 32).
92
+ Otherwise, if the model is detection, this will be None.
93
+ """
94
+ masks = None
95
+ if p.shape[0] == 1:
96
+ p = p[0]
97
+ # Only transpose if shapes are [116, 8400] or [85, 25200]
98
+ if p.shape[0] < p.shape[1]:
99
+ # Transposing shape (116, 8400) -> (8400, 116).
100
+ p = p.transpose((1, 0))
101
+ boxes = xcycwh2xyxy(boxes=p[:, 0:4])
102
+ if with_masks:
103
+ det_i = p.shape[1] - 32
104
+ scores = p[:, 4:det_i]
105
+ masks = p[:, det_i:] # Additional 32 protos from segmentation models.
106
+ else:
107
+ # YOLOv5 models contains [x, y, x, y, obj_conf, cls_conf] outputs.
108
+ if p.shape[1] == nc + 5:
109
+ scores = p[:, 5:]
110
+ scores *= p[:, 4:5] # conf = obj_conf * cls_conf # NOSONAR
111
+ # YOLOv8 and YOLOv11
112
+ else:
113
+ scores = p[:, 4:]
114
+ return boxes, scores, masks
115
+
116
+
117
+ def decode_yolox_boxes(
118
+ p: np.ndarray,
119
+ shape: tuple,
120
+ p6: bool = False
121
+ ) -> Tuple[np.ndarray, np.ndarray]:
122
+ """
123
+ Decodes YOLOx outputs into boxes and scores.
124
+
125
+ Parameters
126
+ ----------
127
+ p: np.ndarray
128
+ The raw YOLOx model outputs with shape (1, 8400, 85).
129
+ shape: tuple
130
+ The model input shape (height, width).
131
+ p6: bool
132
+ If True, enables support for YOLOX-P6 with stride 64 detection head.
133
+
134
+ Returns
135
+ -------
136
+ boxes: np.ndarray
137
+ The decoded boxes with shape (8400, 4).
138
+ scores: np.ndarray
139
+ The decoded scores with shape (8400, nc).
140
+ """
141
+ h, w = shape
142
+
143
+ grids = []
144
+ expanded_strides = []
145
+ strides = [8, 16, 32] if not p6 else [8, 16, 32, 64]
146
+
147
+ hsizes = [h // stride for stride in strides]
148
+ wsizes = [w // stride for stride in strides]
149
+ for hsize, wsize, stride in zip(hsizes, wsizes, strides):
150
+ xv, yv = np.meshgrid(np.arange(wsize), np.arange(hsize))
151
+ grid = np.stack((xv, yv), 2).reshape(1, -1, 2)
152
+ grids.append(grid)
153
+ shape = grid.shape[:2]
154
+ expanded_strides.append(np.full((*shape, 1), stride))
155
+
156
+ grids = np.concatenate(grids, 1)
157
+ expanded_strides = np.concatenate(expanded_strides, 1)
158
+ p[..., :2] = (p[..., :2] + grids) * expanded_strides
159
+ p[..., 2:4] = np.exp(p[..., 2:4]) * expanded_strides
160
+ predictions = p[0]
161
+
162
+ boxes = predictions[:, :4]
163
+ scores = predictions[:, 4:5] * predictions[:, 5:]
164
+
165
+ return boxes, scores
166
+
167
+
168
+ def decode_yolo_masks(masks: np.ndarray, protos: np.ndarray) -> np.ndarray:
169
+ """
170
+ Takes the output from Ultralytics segmentation models and
171
+ decodes instance segmentation masks from the model.
172
+
173
+ Parameters
174
+ ----------
175
+ masks: np.ndarray
176
+ The mask coefficients with shape (n, 32).
177
+ protos: np.ndarray
178
+ The raw output mask tensor with shape (1, h, w, 32).
179
+
180
+ Returns
181
+ -------
182
+ np.ndarray
183
+ The instance mask per object with shape (n, h, w).
184
+ """
185
+ # In case of shape (1, 32, h, w).
186
+ if protos.shape[1] == 32:
187
+ c, h, w = protos[0].shape
188
+ else:
189
+ h, w, c = protos[0].shape
190
+ protos = np.transpose(protos, (0, 3, 1, 2))
191
+ masks = np.matmul(masks, protos.reshape(c, -1)).reshape(-1, h, w)
192
+ return masks
193
+
194
+
195
+ def decode_mpk_masks(masks: np.ndarray) -> np.ndarray:
196
+ """
197
+ Decodes ModelPack masks into semantic segmentation.
198
+
199
+ Parameters
200
+ ----------
201
+ masks: np.ndarray
202
+ The raw segmentation masks from the model
203
+ with shape (1, h, w, nc).
204
+
205
+ Returns
206
+ -------
207
+ np.ndarray
208
+ The decoded semantic segmentation mask
209
+ with shape (1, h, w).
210
+ """
211
+ if len(masks.shape) == 3:
212
+ return np.array(masks, dtype=np.uint8)
213
+ return np.argmax(masks, axis=-1).astype(np.uint8)
214
+
215
+
216
+ def crop_masks(masks: np.ndarray, boxes: np.ndarray) -> np.ndarray:
217
+ """
218
+ Crops each instance mask to the bounding box.
219
+
220
+ Parameters
221
+ ----------
222
+ masks: np.ndarray
223
+ The instance mask per object with shape (n, h, w).
224
+ boxes: np.ndarray
225
+ Normalized box coordinates in [xmin, ymin, xmax, ymax]
226
+ format with shape (n, 4).
227
+
228
+ Returns
229
+ -------
230
+ np.ndarray
231
+ The instance mask per object cropped to the box dimensions
232
+ with shape (n, h, w).
233
+ """
234
+ _, h, w = masks.shape
235
+ x1, y1, x2, y2 = np.split(
236
+ boxes[:, :, np.newaxis], 4, axis=1) # shape (n, 1, 1)
237
+ r = np.arange(w, dtype=boxes.dtype)[None, None, :] # rows shape(1,1,w)
238
+ c = np.arange(h, dtype=boxes.dtype)[None, :, None] # cols shape(1,h,1)
239
+ return masks * ((r >= x1 * w) * (r < x2 * w)
240
+ * (c >= y1 * h) * (c < y2 * h))
241
+
242
+
243
+ def dequantize(x: np.ndarray, scale: float, zero_point: float) -> np.ndarray:
244
+ """
245
+ Dequantization of the model output tensor based on the scale
246
+ and zero point values.
247
+
248
+ Parameters
249
+ ----------
250
+ x: np.ndarray
251
+ Quantized model output tensor typically with uint8 or int8 dtypes.
252
+ scale: float
253
+ Quantization scale factor.
254
+ zero_point: float
255
+ Quantization shift factor for signed tensors.
256
+
257
+ Returns
258
+ -------
259
+ np.ndarray
260
+ Dequantized tensors typically float32 dtypes.
261
+ """
262
+ if scale > 0:
263
+ x = (x.astype(np.float32) - zero_point) * scale # re-scale
264
+ return x
265
+
266
+
267
+ def dequantize_kinara(
268
+ output_dict: dict,
269
+ method: str = "hal"
270
+ ) -> List[np.ndarray]:
271
+ """
272
+ Dequantize a list of quantized outputs from Kinara models.
273
+
274
+ Parameters
275
+ ----------
276
+ output_list : dict
277
+ List of quantized model outputs.
278
+ method: str
279
+ The method to use for performing the dequantization.
280
+ By default "hal" is used. Otherwise, NumPy operations are used.
281
+
282
+ Returns
283
+ -------
284
+ list of np.ndarray
285
+ List of dequantized outputs as float arrays.
286
+ """
287
+ num_outputs = len(output_dict)
288
+ dequantized_outputs = []
289
+ for i in range(num_outputs):
290
+ output: np.ndarray = output_dict[i].numpy_data
291
+ out_param = output_dict[i].params
292
+
293
+ if (not out_param.postprocess_param.is_struct_format
294
+ and not out_param.postprocess_param.is_float):
295
+
296
+ bpp = out_param.bpp
297
+ dtype = np.int8
298
+ if bpp == 1:
299
+ dtype = np.int8 if out_param.postprocess_param.is_signed else np.uint8
300
+ elif bpp == 2:
301
+ dtype = np.int16 if out_param.postprocess_param.is_signed else np.uint16
302
+ elif bpp == 4:
303
+ dtype = np.int32 if out_param.postprocess_param.is_signed else np.uint32
304
+
305
+ qn, offset = (out_param.postprocess_param.qn,
306
+ out_param.postprocess_param.offset)
307
+ buf = output.view(dtype=dtype)
308
+
309
+ if method == "hal":
310
+ dst_buffer = buf
311
+ else:
312
+ dst_buffer = (
313
+ (buf.astype(int) -
314
+ offset) *
315
+ qn).astype(
316
+ np.float32)
317
+ dequantized_outputs.append(dst_buffer)
318
+ else:
319
+ dequantized_outputs.append(output)
320
+ return dequantized_outputs