Regarding doubts about ultra_light_320.onnx convert into tensorrt

Please provide complete information as applicable to your setup.

• Hardware Platform (Jetson / GPU) - Jetson Nano
• DeepStream Version - 6.0.1
• JetPack Version (valid for Jetson only) - 4.6.3
• TensorRT Version - 8.4
• NVIDIA GPU Driver Version (valid for GPU only) 10.2
• Issue Type( questions, new requirements, bugs) - how to convert ultra_light_320.onnx into tesnorrt and also we have converted into tensorrt format even though it does not work properly,could you give me a proper solution regarding this.
• How to reproduce the issue ? (This is for bugs. Including which sample app is using, the configuration files content, the command line used and other details for reproducing)
• Requirement details( This is for new requirement. Including the module name-for which plugin or for which sample application, the function description)

  1. which deepstream sample are you testing? the deepsttream app can generate engine if setting onnx path.

how to make custom box parser for an ultra_light_320.onnx,could you tell me how to do it .

first please understand the meaning of model’s outputs. if you can get the correct result from thirdpart tool, you can port the postprocess code; or you can implement own postprocess code. please refer to sample opt\nvidia\deepstream\deepstream-6.2\sources\objectDetector_Yolo\nvdsinfer_custom_impl_Yolo\nvdsparsebbox_Yolo.cpp

ok tq

/*

  • Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
  • Permission is hereby granted, free of charge, to any person obtaining a
  • copy of this software and associated documentation files (the “Software”),
  • to deal in the Software without restriction, including without limitation
  • the rights to use, copy, modify, merge, publish, distribute, sublicense,
  • and/or sell copies of the Software, and to permit persons to whom the
  • Software is furnished to do so, subject to the following conditions:
  • The above copyright notice and this permission notice shall be included in
  • all copies or substantial portions of the Software.
  • THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  • IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  • FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  • THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  • LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  • FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  • DEALINGS IN THE SOFTWARE.
    */

include
include
include
include
include
include
include <unordered_map>
include “nvdsinfer_custom_impl.h”
include “trt_utils.h”

static const int NUM_CLASSES_YOLO = 80;

extern “C” bool NvDsInferParseCustomYoloV3(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList);

extern “C” bool NvDsInferParseCustomYoloV3Tiny(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList);

extern “C” bool NvDsInferParseCustomYoloV2(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList);

extern “C” bool NvDsInferParseCustomYoloV2Tiny(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList);

/* This is a sample bounding box parsing function for the sample YoloV3 detector model */
static NvDsInferParseObjectInfo convertBBox(const float& bx, const float& by, const float& bw,
const float& bh, const int& stride, const uint& netW,
const uint& netH)
{
NvDsInferParseObjectInfo b;
// Restore coordinates to network input resolution
float xCenter = bx * stride;
float yCenter = by * stride;
float x0 = xCenter - bw / 2;
float y0 = yCenter - bh / 2;
float x1 = x0 + bw;
float y1 = y0 + bh;

x0 = clamp(x0, 0, netW);
y0 = clamp(y0, 0, netH);
x1 = clamp(x1, 0, netW);
y1 = clamp(y1, 0, netH);

b.left = x0;
b.width = clamp(x1 - x0, 0, netW);
b.top = y0;
b.height = clamp(y1 - y0, 0, netH);

return b;

}

static void addBBoxProposal(const float bx, const float by, const float bw, const float bh,
const uint stride, const uint& netW, const uint& netH, const int maxIndex,
const float maxProb, std::vector& binfo)
{
NvDsInferParseObjectInfo bbi = convertBBox(bx, by, bw, bh, stride, netW, netH);
if (bbi.width < 1 || bbi.height < 1) return;

bbi.detectionConfidence = maxProb;
bbi.classId = maxIndex;
binfo.push_back(bbi);

}

static std::vector
decodeYoloV2Tensor(
const float* detections, const std::vector &anchors,
const uint gridSizeW, const uint gridSizeH, const uint stride, const uint numBBoxes,
const uint numOutputClasses, const uint& netW,
const uint& netH)
{
std::vector binfo;
for (uint y = 0; y < gridSizeH; ++y) {
for (uint x = 0; x < gridSizeW; ++x) {
for (uint b = 0; b < numBBoxes; ++b)
{
const float pw = anchors[b * 2];
const float ph = anchors[b * 2 + 1];

            const int numGridCells = gridSizeH * gridSizeW;
            const int bbindex = y * gridSizeW + x;
            const float bx
                = x + detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 0)];
            const float by
                = y + detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 1)];
            const float bw
                = pw * exp (detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 2)]);
            const float bh
                = ph * exp (detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 3)]);

            const float objectness
                = detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 4)];

            float maxProb = 0.0f;
            int maxIndex = -1;

            for (uint i = 0; i < numOutputClasses; ++i)
            {
                float prob
                    = (detections[bbindex
                                  + numGridCells * (b * (5 + numOutputClasses) + (5 + i))]);

                if (prob > maxProb)
                {
                    maxProb = prob;
                    maxIndex = i;
                }
            }
            maxProb = objectness * maxProb;

            addBBoxProposal(bx, by, bw, bh, stride, netW, netH, maxIndex, maxProb, binfo);
        }
    }
}
return binfo;

}

static std::vector
decodeYoloV3Tensor(
const float* detections, const std::vector &mask, const std::vector &anchors,
const uint gridSizeW, const uint gridSizeH, const uint stride, const uint numBBoxes,
const uint numOutputClasses, const uint& netW,
const uint& netH)
{
std::vector binfo;
for (uint y = 0; y < gridSizeH; ++y) {
for (uint x = 0; x < gridSizeW; ++x) {
for (uint b = 0; b < numBBoxes; ++b)
{
const float pw = anchors[mask[b] * 2];
const float ph = anchors[mask[b] * 2 + 1];

            const int numGridCells = gridSizeH * gridSizeW;
            const int bbindex = y * gridSizeW + x;
            const float bx
                = x + detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 0)];
            const float by
                = y + detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 1)];
            const float bw
                = pw * detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 2)];
            const float bh
                = ph * detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 3)];

            const float objectness
                = detections[bbindex + numGridCells * (b * (5 + numOutputClasses) + 4)];

            float maxProb = 0.0f;
            int maxIndex = -1;

            for (uint i = 0; i < numOutputClasses; ++i)
            {
                float prob
                    = (detections[bbindex
                                  + numGridCells * (b * (5 + numOutputClasses) + (5 + i))]);

                if (prob > maxProb)
                {
                    maxProb = prob;
                    maxIndex = i;
                }
            }
            maxProb = objectness * maxProb;

            addBBoxProposal(bx, by, bw, bh, stride, netW, netH, maxIndex, maxProb, binfo);
        }
    }
}
return binfo;

}

static inline std::vector<const NvDsInferLayerInfo*>
SortLayers(const std::vector & outputLayersInfo)
{
std::vector<const NvDsInferLayerInfo*> outLayers;
for (auto const &layer : outputLayersInfo) {
outLayers.push_back (&layer);
}
std::sort(outLayers.begin(), outLayers.end(),
(const NvDsInferLayerInfo* a, const NvDsInferLayerInfo* b) {
return a->inferDims.d[1] < b->inferDims.d[1];
});
return outLayers;
}

static bool NvDsInferParseYoloV3(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList,
const std::vector &anchors,
const std::vector<std::vector> &masks)
{
const uint kNUM_BBOXES = 3;

const std::vector<const NvDsInferLayerInfo*> sortedLayers =
    SortLayers (outputLayersInfo);

if (sortedLayers.size() != masks.size()) {
    std::cerr << "ERROR: yoloV3 output layer.size: " << sortedLayers.size()
              << " does not match mask.size: " << masks.size() << std::endl;
    return false;
}

if (NUM_CLASSES_YOLO != detectionParams.numClassesConfigured)
{
    std::cerr << "WARNING: Num classes mismatch. Configured:"
              << detectionParams.numClassesConfigured
              << ", detected by network: " << NUM_CLASSES_YOLO << std::endl;
}

std::vector<NvDsInferParseObjectInfo> objects;

for (uint idx = 0; idx < masks.size(); ++idx) {
    const NvDsInferLayerInfo &layer = *sortedLayers[idx]; // 255 x Grid x Grid

    assert(layer.inferDims.numDims == 3);
    const uint gridSizeH = layer.inferDims.d[1];
    const uint gridSizeW = layer.inferDims.d[2];
    const uint stride = DIVUP(networkInfo.width, gridSizeW);
    assert(stride == DIVUP(networkInfo.height, gridSizeH));

    std::vector<NvDsInferParseObjectInfo> outObjs =
        decodeYoloV3Tensor((const float*)(layer.buffer), masks[idx], anchors, gridSizeW, gridSizeH, stride, kNUM_BBOXES,
                   NUM_CLASSES_YOLO, networkInfo.width, networkInfo.height);
    objects.insert(objects.end(), outObjs.begin(), outObjs.end());
}


objectList = objects;

return true;

}

/* C-linkage to prevent name-mangling */
extern “C” bool NvDsInferParseCustomYoloV3(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList)
{
static const std::vector kANCHORS = {
10.0, 13.0, 16.0, 30.0, 33.0, 23.0, 30.0, 61.0, 62.0,
45.0, 59.0, 119.0, 116.0, 90.0, 156.0, 198.0, 373.0, 326.0};
static const std::vector<std::vector> kMASKS = {
{6, 7, 8},
{3, 4, 5},
{0, 1, 2}};
return NvDsInferParseYoloV3 (
outputLayersInfo, networkInfo, detectionParams, objectList,
kANCHORS, kMASKS);
}

extern “C” bool NvDsInferParseCustomYoloV3Tiny(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList)
{
static const std::vector kANCHORS = {
10, 14, 23, 27, 37, 58, 81, 82, 135, 169, 344, 319};
static const std::vector<std::vector> kMASKS = {
{3, 4, 5},
//{0, 1, 2}}; // as per output result, select {1,2,3}
{1, 2, 3}};

return NvDsInferParseYoloV3 (
    outputLayersInfo, networkInfo, detectionParams, objectList,
    kANCHORS, kMASKS);

}

static bool NvDsInferParseYoloV2(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList)
{
// copy anchor data from yolov2.cfg file
std::vector anchors = {0.57273, 0.677385, 1.87446, 2.06253, 3.33843,
5.47434, 7.88282, 3.52778, 9.77052, 9.16828};
const uint kNUM_BBOXES = 5;

if (outputLayersInfo.empty()) {
    std::cerr << "Could not find output layer in bbox parsing" << std::endl;;
    return false;
}
const NvDsInferLayerInfo &layer = outputLayersInfo[0];

if (NUM_CLASSES_YOLO != detectionParams.numClassesConfigured)
{
    std::cerr << "WARNING: Num classes mismatch. Configured:"
              << detectionParams.numClassesConfigured
              << ", detected by network: " << NUM_CLASSES_YOLO << std::endl;
}

assert(layer.inferDims.numDims == 3);
const uint gridSizeH = layer.inferDims.d[1];
const uint gridSizeW = layer.inferDims.d[2];
const uint stride = DIVUP(networkInfo.width, gridSizeW);
assert(stride == DIVUP(networkInfo.height, gridSizeH));
for (auto& anchor : anchors) {
    anchor *= stride;
}
std::vector<NvDsInferParseObjectInfo> objects =
    decodeYoloV2Tensor((const float*)(layer.buffer), anchors, gridSizeW, gridSizeH, stride, kNUM_BBOXES,
               NUM_CLASSES_YOLO, networkInfo.width, networkInfo.height);

objectList = objects;

return true;

}

extern “C” bool NvDsInferParseCustomYoloV2(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList)
{
return NvDsInferParseYoloV2 (
outputLayersInfo, networkInfo, detectionParams, objectList);
}

extern “C” bool NvDsInferParseCustomYoloV2Tiny(
std::vector const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector& objectList)
{
return NvDsInferParseYoloV2 (
outputLayersInfo, networkInfo, detectionParams, objectList);
}

/* Check that the custom function has been defined correctly */
CHECK_CUSTOM_PARSE_FUNC_PROTOTYPE(NvDsInferParseCustomYoloV3);
CHECK_CUSTOM_PARSE_FUNC_PROTOTYPE(NvDsInferParseCustomYoloV3Tiny);
CHECK_CUSTOM_PARSE_FUNC_PROTOTYPE(NvDsInferParseCustomYoloV2);
CHECK_CUSTOM_PARSE_FUNC_PROTOTYPE(NvDsInferParseCustomYoloV2Tiny);

what it must be changed in this code for an ultra_light_320.onnx model and what i have to remove this code could tell me these things for me

nvdsparsebbox_Yolo.cpp is only sample to do postprocess for yolo models. you need to implement a parsing boxes funtion for the model ultra_light_32.onnx? what is the mdoel’s output? can you get the correct results by thirdpart tool?

ok successfully done

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.