+
+float ObjectDecoder::decodeYOLOScore(int idx, int nameIdx)
+{
+ auto it = mMeta._tensor_info.begin();
+ std::advance(it, nameIdx);
+
+ float score = mTensorBuffer.getValue<float>(it->first, idx);
+ if (mMeta.GetScoreType() == INFERENCE_SCORE_TYPE_SIGMOID) {
+ score = PostProcess::sigmoid(score);
+ }
+
+ return score;
+}
+Box ObjectDecoder::decodeYOLOBox(int idx, float score, int label, int offset, int nameIdx)
+{
+ auto it = mMeta._tensor_info.begin();
+ std::advance(it, nameIdx);
+
+ // assume type is (cx,cy,w,h)
+ // left or cx
+ float cx = mTensorBuffer.getValue<float>(it->first, idx * mBoxOffset + offset + mMeta.GetBoxOrder()[0]);
+ // top or cy
+ float cy = mTensorBuffer.getValue<float>(it->first, idx * mBoxOffset + offset + mMeta.GetBoxOrder()[1]);
+ // right or width
+ float cWidth = mTensorBuffer.getValue<float>(it->first, idx * mBoxOffset + offset + mMeta.GetBoxOrder()[2]);
+ // bottom or height
+ float cHeight = mTensorBuffer.getValue<float>(it->first, idx * mBoxOffset + offset + mMeta.GetBoxOrder()[3]);
+
+ if (mMeta.GetScoreType() == INFERENCE_SCORE_TYPE_SIGMOID) {
+ cx = PostProcess::sigmoid(cx);
+ cy = PostProcess::sigmoid(cy);
+ cWidth = PostProcess::sigmoid(cWidth);
+ cHeight = PostProcess::sigmoid(cHeight);
+ }
+
+ LOGI("cx:%.2f, cy:%.2f, cW:%.2f, cH:%.2f", cx, cy, cWidth, cHeight);
+ // convert type to ORIGIN_CENTER if ORIGIN_LEFTTOP
+ if (mMeta.GetBoxType() == INFERENCE_BOX_TYPE_ORIGIN_LEFTTOP) {
+ float tmpCx = cx;
+ float tmpCy = cy;
+ cx = (cx + cWidth) * 0.5f; // (left + right)/2
+ cy = (cy + cHeight) * 0.5f; // (top + bottom)/2
+ cWidth = cWidth - tmpCx; // right - left
+ cHeight = cHeight - tmpCy; // bottom - top
+ }
+
+ // convert coordinate to RATIO if PIXEL
+ if (mMeta.GetScoreCoordinate() == INFERENCE_BOX_COORDINATE_TYPE_PIXEL) {
+ cx /= mScaleW;
+ cy /= mScaleH;
+ cWidth /= mScaleW;
+ cHeight /= mScaleH;
+ }
+
+ Box box = { .index = label, .score = score, .location = cv::Rect2f(cx, cy, cWidth, cHeight) };
+
+ return box;
+}
+void ObjectDecoder::decodeYOLO(BoxesList &boxesList)
+{
+ box::DecodeInfo &decodeInfo = mMeta.GetBoxDecodeInfo();
+ box::AnchorParam &yoloAnchor = decodeInfo.anchorParam;
+
+ //offsetAnchors is 3 which is number of BOX
+ mNumberOfOjects = mBoxOffset / yoloAnchor.offsetAnchors - 5;
+ boxesList.resize(mNumberOfOjects);
+
+ for (auto strideIdx = 0; strideIdx < yoloAnchor.offsetAnchors; strideIdx++) {
+ auto &stride = yoloAnchor.strides[strideIdx];
+ //for each stride
+ int startAnchorIdx = 0;
+ int endAnchorIdx = (static_cast<int>(mScaleW) / stride * static_cast<int>(mScaleH) / stride);
+
+ for (int anchorIdx = startAnchorIdx; anchorIdx < endAnchorIdx; anchorIdx++) {
+ // for each grid cell
+ for (int offset = 0; offset < yoloAnchor.offsetAnchors; ++offset) {
+ //for each BOX
+ //handle order is (H,W,A)
+ float boxScore =
+ decodeYOLOScore(anchorIdx * mBoxOffset + (mNumberOfOjects + 5) * offset + 4, strideIdx);
+
+ auto anchorBox = decodeInfo.vAnchorBoxes[strideIdx][anchorIdx * yoloAnchor.offsetAnchors + offset];
+
+ for (int objIdx = 0; objIdx < mNumberOfOjects; ++objIdx) { //each box to every object
+ float objScore = decodeYOLOScore(
+ anchorIdx * mBoxOffset + (mNumberOfOjects + 5) * offset + 5 + objIdx, strideIdx);
+
+ if (boxScore * objScore < mMeta.GetScoreThreshold())
+ continue;
+ Box box = decodeYOLOBox(anchorIdx, objScore, objIdx, (mNumberOfOjects + 5) * offset, strideIdx);
+
+ if (!decodeInfo.vAnchorBoxes.empty()) {
+ box.location.x = (box.location.x * 2 + anchorBox.x) * stride / mScaleW;
+ box.location.y = (box.location.y * 2 + anchorBox.y) * stride / mScaleH;
+ box.location.width =
+ (box.location.width * 2) * (box.location.width * 2) * anchorBox.width / mScaleW;
+
+ box.location.height =
+ (box.location.height * 2) * (box.location.height * 2) * anchorBox.height / mScaleH;
+ }
+ boxesList[objIdx].push_back(box);
+ }
+ }
+ }
+ }
+}