27 std::ifstream ifs(fname);
28 if (ifs.is_open() ==
false)
LFATAL(
"Failed to open file " << fname);
30 size_t linenum = 1; std::map<int, std::string> ret;
int id = 0;
31 for (std::string line; std::getline(ifs, line); ++linenum)
33 size_t idx1 = line.find_first_not_of(
" \t");
if (idx1 == line.npos)
continue;
34 size_t idx2 = line.find_last_not_of(
" \t\r\n");
if (idx2 == line.npos)
continue;
35 if (line[idx1] ==
'#')
continue;
37 try {
id = std::stoi(line, &idx1); idx1 = line.find_first_not_of(
"0123456789 \t,:", idx1); }
catch (...) { }
39 std::string classname;
42 LERROR(fname <<
':' << linenum <<
": empty class name -- REPLACING BY 'unspecified'");
43 classname =
"unspecified";
45 else classname = line.substr(idx1, idx2 + 1 - idx1);
51 size_t len = classname.length();
52 if (len > 1 && classname[0] ==
'"' && classname[len-1] ==
'"') classname = classname.substr(1, len-2);
62 LINFO(
"Loaded " << ret.size() <<
" class names from " << fname);
70 auto itr = labels.find(
id);
71 if (itr == labels.end())
return std::to_string(
id);
79 for (
char const c : label) col = c + ((col << 5) - col);
80 col = (col & 0xffffff) | (alpha << 24);
85void jevois::dnn::topK(
float const * pfProb,
float * pfMaxProb, uint32_t * pMaxClass, uint32_t outputCount,
88 memset(pfMaxProb, 0xfe,
sizeof(
float) * topNum);
89 memset(pMaxClass, 0xff,
sizeof(
float) * topNum);
91 for (uint32_t j = 0; j < topNum; ++j)
93 for (uint32_t i = 0; i < outputCount; ++i)
96 for (k = 0; k < topNum; ++k)
if (i == pMaxClass[k])
break;
97 if (k != topNum)
continue;
99 if (pfProb[i] > pfMaxProb[j]) { pfMaxProb[j] = pfProb[i]; pMaxClass[j] = i; }
107 cv::MatSize
const & ms = m.size;
int const nd = ms.dims();
108 std::string ret = std::to_string(nd) +
"D ";
109 for (
int i = 0; i < nd; ++i) ret += std::to_string(ms[i]) + (i < nd-1 ?
"x" :
"");
118 TfLiteIntArray
const & dims = *t->dims;
119 std::string ret = std::to_string(dims.size) +
"D ";
120 for (
int i = 0; i < dims.size; ++i) ret += std::to_string(dims.data[i]) + (i < dims.size-1 ?
"x" :
"");
125 case kTfLiteNoType: ret +=
" NoType";
break;
126 case kTfLiteFloat32: ret +=
" 32F";
break;
127 case kTfLiteInt32: ret +=
" 32S";
break;
128 case kTfLiteUInt8: ret +=
" 8U";
break;
129 case kTfLiteInt64: ret +=
" 64S";
break;
130 case kTfLiteString: ret +=
" String";
break;
131 case kTfLiteBool: ret +=
" 8B";
break;
132 case kTfLiteInt16: ret +=
" 16S";
break;
133 case kTfLiteComplex64: ret +=
" 64C";
break;
134 case kTfLiteInt8: ret +=
" 8I";
break;
135 case kTfLiteFloat16: ret +=
" 16F";
break;
136 case kTfLiteFloat64: ret +=
" 64F";
break;
137 case kTfLiteComplex128: ret +=
" 128C";
break;
138 default: ret +=
" UnknownType";
break;
146 std::string ret = std::to_string(attr.dim_num) +
"D ";
147 for (uint32_t i = 0; i < attr.dim_num; ++i)
148 ret += std::to_string(attr.size[attr.dim_num-1-i]) + (i < attr.dim_num-1 ?
"x" :
"");
151 switch (attr.dtype.vx_type)
153 case VSI_NN_TYPE_UINT8: ret +=
" 8U";
break;
154 case VSI_NN_TYPE_INT8: ret +=
" 8S";
break;
155 case VSI_NN_TYPE_BOOL8: ret +=
" 8B";
break;
156 case VSI_NN_TYPE_UINT16: ret +=
" 16U";
break;
157 case VSI_NN_TYPE_INT16: ret +=
" 16S";
break;
158 case VSI_NN_TYPE_FLOAT16: ret +=
" 16F";
break;
159 case VSI_NN_TYPE_BFLOAT16: ret +=
" 16B";
break;
160 case VSI_NN_TYPE_UINT32: ret +=
" 32U";
break;
161 case VSI_NN_TYPE_INT32: ret +=
" 32S";
break;
162 case VSI_NN_TYPE_FLOAT32: ret +=
" 32F";
break;
163 case VSI_NN_TYPE_UINT64: ret +=
" 64U";
break;
164 case VSI_NN_TYPE_INT64: ret +=
" 64S";
break;
165 case VSI_NN_TYPE_FLOAT64: ret +=
" 64F";
break;
166 default:
throw std::range_error(
"shapestr: Unsupported tensor type " + std::to_string(attr.dtype.vx_type));
176 std::ostringstream os;
177 std::vector<int64_t> input_node_dims = ti.GetShape();
178 os << input_node_dims.size() <<
"D ";
179 for (int64_t d : input_node_dims) os << d <<
'x';
180 os.seekp(-1, os.cur);
182 switch (ti.GetElementType())
184 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED: os <<
" UNDEFINED";
break;
185 case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: os <<
" 32F";
break;
186 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: os <<
" 8U";
break;
187 case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: os <<
" 8S";
break;
188 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: os <<
" 16U";
break;
189 case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: os <<
" 16S";
break;
190 case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: os <<
" 32S";
break;
191 case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: os <<
" 64S";
break;
192 case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING: os <<
" STR";
break;
193 case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: os <<
" BOOL";
break;
194 case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: os <<
" 16F";
break;
195 case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: os <<
" 64F";
break;
196 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: os <<
" 32U";
break;
197 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: os <<
" 64U";
break;
198 case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64: os <<
" 64CPLX";
break;
199 case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128: os <<
" 128CPLX";
break;
200 case ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16: os <<
" 16B";
break;
201 default:
throw std::range_error(
"shapestr: Unsupported tensor type " + std::to_string(ti.GetElementType()));
212 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED:
return VSI_NN_TYPE_NONE;
213 case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT:
return VSI_NN_TYPE_FLOAT32;
214 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8:
return VSI_NN_TYPE_UINT8;
215 case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8:
return VSI_NN_TYPE_INT8;
216 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16:
return VSI_NN_TYPE_UINT16;
217 case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16:
return VSI_NN_TYPE_INT16;
218 case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32:
return VSI_NN_TYPE_INT32;
219 case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64:
return VSI_NN_TYPE_INT64;
220 case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL:
return VSI_NN_TYPE_BOOL8;
221 case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16:
return VSI_NN_TYPE_FLOAT16;
222 case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE:
return VSI_NN_TYPE_FLOAT64;
223 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32:
return VSI_NN_TYPE_UINT32;
224 case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64:
return VSI_NN_TYPE_UINT64;
225 case ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16:
return VSI_NN_TYPE_BFLOAT16;
229 default:
throw std::range_error(
"onnx2vsi: Unsupported tensor type " + std::to_string(t));
236 vsi_nn_tensor_attr_t attr; memset(&attr, 0,
sizeof(attr));
237 attr.dtype.fmt = VSI_NN_DIM_FMT_AUTO;
240 std::vector<int64_t>
const dims = ti.GetShape();
241 size_t const ds = dims.size();
243 for (
size_t i = 0; i < ds; ++i) attr.size[ds - 1 - i] = dims[i];
246 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_NONE;
279 std::vector<size_t> ret;
281 for (std::string
const & t : tok) ret.emplace_back(std::stoi(t));
290 case kTfLiteFloat32:
return CV_32F;
291 case kTfLiteInt32:
return CV_32S;
292 case kTfLiteUInt8:
return CV_8U;
293 case kTfLiteInt16:
return CV_16S;
294 case kTfLiteInt8:
return CV_8S;
295 case kTfLiteFloat16:
return CV_16F;
296 case kTfLiteFloat64:
return CV_64F;
303 default:
throw std::range_error(std::string(
"tf2cv: Unsupported type ") + TfLiteTypeGetName(t));
312 case VSI_NN_TYPE_UINT8:
return CV_8U;
313 case VSI_NN_TYPE_INT8:
return CV_8S;
314 case VSI_NN_TYPE_BOOL8:
return CV_8U;
315 case VSI_NN_TYPE_UINT16:
return CV_16U;
316 case VSI_NN_TYPE_INT16:
return CV_16S;
317 case VSI_NN_TYPE_FLOAT16:
return CV_16F;
320 case VSI_NN_TYPE_INT32:
return CV_32S;
321 case VSI_NN_TYPE_FLOAT32:
return CV_32F;
324 case VSI_NN_TYPE_FLOAT64:
return CV_64F;
325 default:
throw std::range_error(
"vsi2cv: Unsupported tensor type " + std::to_string(t));
334 case kTfLiteFloat32:
return VSI_NN_TYPE_FLOAT32;
335 case kTfLiteInt32:
return VSI_NN_TYPE_INT32;
336 case kTfLiteUInt8:
return VSI_NN_TYPE_UINT8;
337 case kTfLiteInt16:
return VSI_NN_TYPE_INT16;
338 case kTfLiteInt8:
return VSI_NN_TYPE_INT8;
339 case kTfLiteFloat16:
return VSI_NN_TYPE_FLOAT16;
340 case kTfLiteFloat64:
return VSI_NN_TYPE_FLOAT64;
341 case kTfLiteInt64:
return VSI_NN_TYPE_INT64;
342 case kTfLiteBool:
return VSI_NN_TYPE_BOOL8;
343 case kTfLiteNoType:
return VSI_NN_TYPE_NONE;
347 default:
throw std::range_error(std::string(
"tf2vsi: Unsupported type ") + TfLiteTypeGetName(t));
357 case HAILO_FORMAT_TYPE_AUTO:
return VSI_NN_TYPE_NONE;
break;
358 case HAILO_FORMAT_TYPE_UINT8:
return VSI_NN_TYPE_UINT8;
break;
359 case HAILO_FORMAT_TYPE_UINT16:
return VSI_NN_TYPE_UINT16;
break;
360 case HAILO_FORMAT_TYPE_FLOAT32:
return VSI_NN_TYPE_FLOAT32;
break;
361 default:
throw std::range_error(
"hailo2vsi: Unsupported tensor type " + std::to_string(t));
369 int tx = std::min(width - 1, std::max(0, r.x));
370 int ty = std::min(height - 1, std::max(0, r.y));
371 int bx = std::min(width - 1, std::max(0, r.x + r.width));
372 int by = std::min(height - 1, std::max(0, r.y + r.height));
373 r.x = tx; r.y = ty; r.width = bx - tx; r.height = by - ty;
379 float tx = std::min(width - 1.0F, std::max(0.0F, r.x));
380 float ty = std::min(height - 1.0F, std::max(0.0F, r.y));
381 float bx = std::min(width - 1.0F, std::max(0.0F, r.x + r.width));
382 float by = std::min(height - 1.0F, std::max(0.0F, r.y + r.height));
383 r.x = tx; r.y = ty; r.width = bx - tx; r.height = by - ty;
389 char const *
const specdef =
"[NCHW:|NHWC:|NA:|AUTO:]Type:[NxCxHxW|NxHxWxC|...][:QNT[:fl|:scale:zero]]";
390 std::vector<std::string> spectok =
jevois::split(specs,
",\\s*");
391 std::vector<vsi_nn_tensor_attr_t> ret;
393 for (std::string
const & spec : spectok)
395 vsi_nn_tensor_attr_t attr; memset(&attr, 0,
sizeof(attr));
399 if (tok.size() < 2)
throw std::runtime_error(
"parseTensorSpecs: Malformed tensor spec ["+spec+
"] not "+specdef);
403 if (tok[0] ==
"NCHW") { ++n; attr.dtype.fmt = VSI_NN_DIM_FMT_NCHW; }
404 else if (tok[0] ==
"NHWC") { ++n; attr.dtype.fmt = VSI_NN_DIM_FMT_NHWC; }
405 else if (tok[0] ==
"NA") { ++n; attr.dtype.fmt = VSI_NN_DIM_FMT_NA; }
406 else if (tok[0] ==
"AUTO") { ++n; attr.dtype.fmt = VSI_NN_DIM_FMT_AUTO; }
407 else attr.dtype.fmt = VSI_NN_DIM_FMT_AUTO;
410 if (tok.size() < n+2)
throw std::runtime_error(
"parseTensorSpecs: Malformed tensor spec ["+spec+
"] not "+specdef);
413 if (tok[n] ==
"8U") attr.dtype.vx_type = VSI_NN_TYPE_UINT8;
414 else if (tok[n] ==
"8S") attr.dtype.vx_type = VSI_NN_TYPE_INT8;
415 else if (tok[n] ==
"8B") attr.dtype.vx_type = VSI_NN_TYPE_BOOL8;
416 else if (tok[n] ==
"16U") attr.dtype.vx_type = VSI_NN_TYPE_UINT16;
417 else if (tok[n] ==
"16S") attr.dtype.vx_type = VSI_NN_TYPE_INT16;
418 else if (tok[n] ==
"16F") attr.dtype.vx_type = VSI_NN_TYPE_FLOAT16;
419 else if (tok[n] ==
"16B") attr.dtype.vx_type = VSI_NN_TYPE_BFLOAT16;
420 else if (tok[n] ==
"32U") attr.dtype.vx_type = VSI_NN_TYPE_UINT32;
421 else if (tok[n] ==
"32S") attr.dtype.vx_type = VSI_NN_TYPE_INT32;
422 else if (tok[n] ==
"32F") attr.dtype.vx_type = VSI_NN_TYPE_FLOAT32;
423 else if (tok[n] ==
"64U") attr.dtype.vx_type = VSI_NN_TYPE_UINT64;
424 else if (tok[n] ==
"64S") attr.dtype.vx_type = VSI_NN_TYPE_INT64;
425 else if (tok[n] ==
"64F") attr.dtype.vx_type = VSI_NN_TYPE_FLOAT64;
426 else throw std::range_error(
"parseTensorSpecs: Invalid tensor type [" + tok[n] +
"] in " + spec);
431 attr.dim_num = dims.size();
432 for (
size_t i = 0; i < attr.dim_num; ++i) attr.size[attr.dim_num - 1 - i] = dims[i];
436 if (n == tok.size() || tok[n] ==
"NONE")
438 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_NONE;
440 else if (tok[n] ==
"DFP")
442 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_DFP;
443 if (tok.size() != n+2)
444 throw std::range_error(
"parseTensorSpecs: In "+spec+
", DFP quantization needs :fl (" + specdef +
')');
445 attr.dtype.fl = std::stoi(tok[n+1]);
448 else if (tok[n] ==
"AA" || tok[n] ==
"AS")
450 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC;
451 if (tok.size() != n+3)
452 throw std::range_error(
"parseTensorSpecs: In "+spec+
", AA/AS quantization needs :scale:zero ("+specdef+
')');
453 attr.dtype.scale = std::stof(tok[n+1]);
454 attr.dtype.zero_point = std::stoi(tok[n+2]);
456 else if (tok[n] ==
"APS")
458 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_PERCHANNEL_SYMMETRIC;
459 throw std::range_error(
"parseTensorSpecs: In " + spec +
", AFFINE_PERCHANNEL_SYMMETRIC quant not yet supported");
461 else throw std::range_error(
"parseTensorSpecs: Invalid quantization type in " + spec);
464 ret.emplace_back(attr);
480 size_t const ndim = attr.dim_num;
481 std::vector<int> cvdims(ndim);
482 for (
size_t i = 0; i < ndim; ++i) cvdims[ndim - 1 - i] = attr.size[i];
489 switch (attr.dtype.fmt)
491 case VSI_NN_DIM_FMT_NHWC:
492 if (attr.dim_num < 3)
throw std::range_error(
"attrsize: need at least 3D, got " +
jevois::dnn::attrstr(attr));
493 return cv::Size(attr.size[1], attr.size[2]);
495 case VSI_NN_DIM_FMT_NCHW:
496 if (attr.dim_num < 2)
throw std::range_error(
"attrsize: need at least 2D, got " +
jevois::dnn::attrstr(attr));
497 return cv::Size(attr.size[0], attr.size[1]);
499 case VSI_NN_DIM_FMT_AUTO:
500 if (attr.dim_num < 2)
return cv::Size(attr.size[0], 1);
501 if (attr.dim_num < 3)
return cv::Size(attr.size[0], attr.size[1]);
503 if (attr.size[0] > attr.size[2])
return cv::Size(attr.size[0], attr.size[1]);
504 else return cv::Size(attr.size[1], attr.size[2]);
507 throw std::range_error(
"attrsize: cannot extract width and height, got " +
jevois::dnn::attrstr(attr));
517 switch (attr.dtype.fmt)
519 case VSI_NN_DIM_FMT_NCHW: ret +=
"NCHW:";
break;
520 case VSI_NN_DIM_FMT_NHWC: ret +=
"NHWC:";
break;
525 switch (attr.dtype.vx_type)
527 case VSI_NN_TYPE_UINT8: ret +=
"8U:";
break;
528 case VSI_NN_TYPE_INT8: ret +=
"8S:";
break;
529 case VSI_NN_TYPE_BOOL8: ret +=
"8B:";
break;
530 case VSI_NN_TYPE_UINT16: ret +=
"16U:";
break;
531 case VSI_NN_TYPE_INT16: ret +=
"16S:";
break;
532 case VSI_NN_TYPE_FLOAT16: ret +=
"16F:";
break;
533 case VSI_NN_TYPE_BFLOAT16: ret +=
"16B:";
break;
534 case VSI_NN_TYPE_UINT32: ret +=
"32U:";
break;
535 case VSI_NN_TYPE_INT32: ret +=
"32S:";
break;
536 case VSI_NN_TYPE_FLOAT32: ret +=
"32F:";
break;
537 case VSI_NN_TYPE_UINT64: ret +=
"64U:";
break;
538 case VSI_NN_TYPE_INT64: ret +=
"64S:";
break;
539 case VSI_NN_TYPE_FLOAT64: ret +=
"64F:";
break;
540 default: ret +=
"TYPE_UNKNOWN:";
544 for (uint32_t i = 0; i < attr.dim_num; ++i)
545 ret += std::to_string(attr.size[attr.dim_num - 1 - i]) + ((i<attr.dim_num-1) ?
'x' :
':');
548 switch (attr.dtype.qnt_type)
550 case VSI_NN_QNT_TYPE_NONE: ret +=
"NONE";
break;
551 case VSI_NN_QNT_TYPE_DFP: ret +=
"DFP:" + std::to_string(attr.dtype.fl);
break;
552 case VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC:
553 ret +=
"AA:" + std::to_string(attr.dtype.scale) +
':' + std::to_string(attr.dtype.zero_point);
555 case VSI_NN_QNT_TYPE_AFFINE_PERCHANNEL_SYMMETRIC: ret +=
"APS:unsupported";
break;
556 default: ret +=
"QUANT_UNKNOWN";
565 vsi_nn_tensor_attr_t attr; memset(&attr, 0,
sizeof(attr));
566 attr.dtype.fmt = VSI_NN_DIM_FMT_AUTO;
569 switch (t->quantization.type)
571 case kTfLiteNoQuantization:
572 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_NONE;
575 case kTfLiteAffineQuantization:
577 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC;
578 attr.dtype.scale = t->params.scale;
579 attr.dtype.zero_point = t->params.zero_point;
583 default:
LFATAL(
"unsupported quantization " << t->quantization.type);
586 TfLiteIntArray
const & dims = *t->dims;
587 attr.dim_num = dims.size;
588 for (
int i = 0; i < dims.size; ++i) attr.size[dims.size - 1 - i] = dims.data[i];
591 if (attr.dim_num == 4)
593 if (attr.size[0] > attr.size[2]) attr.dtype.fmt = VSI_NN_DIM_FMT_NCHW;
594 else attr.dtype.fmt = VSI_NN_DIM_FMT_NHWC;
604 vsi_nn_tensor_attr_t attr; memset(&attr, 0,
sizeof(attr));
606 attr.dtype.vx_type =
hailo2vsi(vi.format.type);
608 switch (vi.format.order)
610 case HAILO_FORMAT_ORDER_HAILO_NMS:
611 attr.dtype.fmt = VSI_NN_DIM_FMT_AUTO;
613 attr.size[0] = vi.nms_shape.number_of_classes;
614 attr.size[1] = vi.nms_shape.max_bboxes_per_class * 5;
617 case HAILO_FORMAT_ORDER_NHWC:
618 case HAILO_FORMAT_ORDER_FCR:
619 case HAILO_FORMAT_ORDER_F8CR:
620 attr.dtype.fmt = VSI_NN_DIM_FMT_NHWC;
622 attr.size[0] = vi.shape.features;
623 attr.size[1] = vi.shape.width;
624 attr.size[2] = vi.shape.height;
628 case HAILO_FORMAT_ORDER_NHW:
629 attr.dtype.fmt = VSI_NN_DIM_FMT_NHWC;
632 attr.size[1] = vi.shape.width;
633 attr.size[2] = vi.shape.height;
637 case HAILO_FORMAT_ORDER_NC:
638 attr.dtype.fmt = VSI_NN_DIM_FMT_NHWC;
642 attr.size[2] = vi.shape.features;
646 case HAILO_FORMAT_ORDER_NCHW:
647 attr.dtype.fmt = VSI_NN_DIM_FMT_NCHW;
649 attr.size[0] = vi.shape.features;
650 attr.size[1] = vi.shape.width;
651 attr.size[2] = vi.shape.height;
655 default:
throw std::range_error(
"tensorattr: Unsupported Hailo order " +std::to_string(vi.format.order));
659 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC;
660 attr.dtype.scale = vi.quant_info.qp_scale;
661 attr.dtype.zero_point = int32_t(vi.quant_info.qp_zp);
668size_t jevois::dnn::softmax(
float const * input,
size_t const n,
size_t const stride,
float const fac,
float * output,
671 if (stride == 0)
LFATAL(
"Cannot work with stride = 0");
674 float largest = -FLT_MAX;
size_t largest_idx = 0;
675 size_t const ns = n * stride;
677 for (
size_t i = 0; i < ns; i += stride)
if (input[i] > largest) { largest = input[i]; largest_idx = i; }
680 for (
size_t i = 0; i < ns; i += stride)
682 float const e = expf(input[i] - largest);
687 for (
size_t i = 0; i < ns; i += stride)
689 float const e = expf(input[i]/fac - largest/fac);
696 if (maxonly) output[largest_idx] /= sum;
697 else for (
size_t i = 0; i < ns; i += stride) output[i] /= sum;
707 if (blob.channels() != 1)
return false;
709 if (uint32_t(blob.size.dims()) != attr.dim_num)
return false;
711 for (
size_t i = 0; i < attr.dim_num; ++i)
712 if (
int(attr.size[attr.dim_num - 1 - i]) != blob.size[i])
return false;
720 if (m.depth() != CV_32F)
LFATAL(
"Tensor to quantize must be 32F");
724 size_t tot = 1;
for (
int d : adims) tot *= d;
726 if (tot != m.total() * m.channels())
731 switch (attr.dtype.qnt_type)
733 case VSI_NN_QNT_TYPE_NONE:
736 m.convertTo(ret, tt);
740 case VSI_NN_QNT_TYPE_DFP:
746 if (attr.dtype.fl > 7)
LFATAL(
"Invalid DFP fl value " << attr.dtype.fl <<
": must be in [0..7]");
748 m.convertTo(ret, tt, 1 << attr.dtype.fl, 0.0);
753 if (attr.dtype.fl > 15)
LFATAL(
"Invalid DFP fl value " << attr.dtype.fl <<
": must be in [0..15]");
755 m.convertTo(ret, tt, 1 << attr.dtype.fl, 0.0);
764 case VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC:
772 m.convertTo(ret, tt, 1.0 / attr.dtype.scale, attr.dtype.zero_point);
782 case VSI_NN_QNT_TYPE_AFFINE_PERCHANNEL_SYMMETRIC:
783 LFATAL(
"Affine per-channel symmetric not supported yet");
798 switch (attr.dtype.qnt_type)
800 case VSI_NN_QNT_TYPE_NONE:
803 m.convertTo(ret, CV_32F);
807 case VSI_NN_QNT_TYPE_DFP:
810 m.convertTo(ret, CV_32F, 1.0 / (1 << attr.dtype.fl), 0.0);
814 case VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC:
817 m.convertTo(ret, CV_32F);
818 if (attr.dtype.zero_point) ret -= attr.dtype.zero_point;
819 if (attr.dtype.scale != 1.0F) ret *= attr.dtype.scale;
823 case VSI_NN_QNT_TYPE_AFFINE_PERCHANNEL_SYMMETRIC:
824 LFATAL(
"Affine per-channel symmetric not supported yet");
827 LFATAL(
"Unknown quantization type " <<
int(attr.dtype.qnt_type));
834 cv::MatSize
const & rs = m.size;
835 size_t const ndims = rs.dims();
837 for (
size_t i = 0; i < ndims; ++i)
if (rs[i] == 1) --ret;
else break;
844 if (tensors.empty())
return cv::Mat();
845 if (tensors.size() == 1)
return tensors[0];
847 cv::MatSize ms = tensors[0].size;
848 int const ndims = ms.dims();
849 auto const typ = tensors[0].type();
852 if (axis < - ndims || axis >= ndims)
853 LFATAL(
"Incorrect axis " << axis <<
": must be in [" << -ndims <<
" ... " << ndims - 1 <<
']');
854 if (axis < 0) axis = ndims - axis;
857 size_t newsize = tensors[0].size[axis];
859 for (
size_t i = 1; i < tensors.size(); ++i)
861 if (tensors[i].type() != typ)
865 if (tensors[i].size.dims() != ndims)
866 LFATAL(
"Mismatched number of dimensions: " << ndims <<
" for tensors[0] vs. " <<
867 tensors[i].size.dims() <<
" for tensors[" << i <<
']');
869 newsize += tensors[i].size[axis];
873 for (
int a = 0; a < ndims; ++a)
875 for (
size_t i = 1; i < tensors.size(); ++i)
876 if (tensors[i].size[a] != ms[a])
877 LFATAL(
"Mismatched size for axis " << a <<
": tensors[0] has " << ms[a] <<
" while tensors[" <<
878 i <<
"] has " << tensors[i].size[a]);
882 cv::Mat ret(ndims, ms.p, typ);
883 unsigned char * optr = ret.data;
885 size_t numcopy = 1;
for (
int a = 0; a < axis; ++a) numcopy *= ms[a];
886 size_t elemsize =
jevois::cvBytesPerPix(typ);
for (
int a = axis + 1; a < ndims; ++a) elemsize *= ms[a];
888 for (
size_t n = 0; n < numcopy; ++n)
889 for (
size_t i = 0; i < tensors.size(); ++i)
891 size_t const axsize = tensors[i].size[axis];
892 unsigned char const * sptr = tensors[i].data + n * elemsize * axsize;
893 std::memcpy(optr, sptr, elemsize * axsize);
894 optr += elemsize * axsize;
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
int tf2cv(TfLiteType t)
Convert from TensorFlow data type to OpenCV.
int vsi2cv(vsi_nn_type_e t)
Convert from NPU data type to OpenCV.
size_t softmax(float const *input, size_t const n, size_t const stride, float const fac, float *output, bool maxonly)
Apply softmax to a float vector.
vsi_nn_tensor_attr_t tensorattr(TfLiteTensor const *t)
Get tensor shape and type attributes for a TensorFlow Lite tensor.
cv::Mat quantize(cv::Mat const &m, vsi_nn_tensor_attr_t const &attr)
Quantize from float32 to fixed-point according to the quantization spec in attr.
std::map< int, std::string > readLabelsFile(std::string const &fname)
Read a label file.
vsi_nn_type_e onnx2vsi(ONNXTensorElementDataType t)
Convert from ONNX-Runtime data type to vsi_nn.
std::vector< vsi_nn_tensor_attr_t > parseTensorSpecs(std::string const &specs)
Parse tensor specification.
void clamp(cv::Rect &r, int width, int height)
Clamp a rectangle to within given image width and height.
std::string attrstr(vsi_nn_tensor_attr_t const &attr)
Get a string describing the specs of a tensor, including quantification specs (not provided by shapes...
cv::Mat attrmat(vsi_nn_tensor_attr_t const &attr, void *dataptr=nullptr)
Construct a cv::Mat from attr and possibly data pointer.
size_t effectiveDims(cv::Mat const &m)
Returns the number of non-unit dims in a cv::Mat.
vsi_nn_type_e hailo2vsi(hailo_format_type_t t)
Convert from Hailo data type to vsi_nn.
cv::Mat concatenate(std::vector< cv::Mat > const &tensors, int axis)
Concatenate several tensors into one.
int stringToRGBA(std::string const &label, unsigned char alpha=128)
Compute a color from a label name.
cv::Size attrsize(vsi_nn_tensor_attr_t const &attr)
Get a tensor's (width, height) size in cv::Size format, skipping over other dimensions.
std::string getLabel(std::map< int, std::string > const &labels, int id)
Get a label from an id.
cv::Mat dequantize(cv::Mat const &m, vsi_nn_tensor_attr_t const &attr)
Dequantize an output to float32 according to the quantization spec in attr.
vsi_nn_type_e tf2vsi(TfLiteType t)
Convert from TensorFlow data type to vsi_nn.
void topK(float const *pfProb, float *pfMaxProb, uint32_t *pMaxClass, uint32_t outputCount, uint32_t topNum)
Get top-k entries and their indices.
std::string shapestr(cv::Mat const &m)
Get a string of the form: "nD AxBxC... TYPE" from an n-dimensional cv::Mat with data type TYPE.
std::vector< int > attrdims(vsi_nn_tensor_attr_t const &attr)
Get a tensor dims as a vector of int, useful to construct a matching cv::Mat.
std::vector< size_t > strshape(std::string const &str)
Get a vector of size_t from a string containing AxBxC...
bool attrmatch(vsi_nn_tensor_attr_t const &attr, cv::Mat const &blob)
Check that a cv::Mat blob matches exactly the spec of an attr.
unsigned int cvBytesPerPix(unsigned int cvtype)
Return the number of bytes per pixel for a given OpenCV pixel type.
std::string cvtypestr(unsigned int cvtype)
Convert cv::Mat::type() code to to a string (e.g., CV_8UC1, CV_32SC3, etc)
size_t replaceStringAll(std::string &str, std::string const &from, std::string const &to)
Replace all instances of 'from' with 'to'.
std::vector< std::string > split(std::string const &input, std::string const ®ex="\\s+")
Split string into vector of tokens using a regex to specify what to split on; default regex splits by...