Custom Model - Sample Custom Parser - FasterRCNN¶
For the source code of FasterRCNN, see TensorRT sample - FasterRCNN
Custom parser implementation¶
the parser file nvdsparsebbox_fasterRCNN.cpp is in /opt/nvidia/deepstream/deepstream-5.1/sources/objectDetector_FasterRCNN/nvdsinfer_custom_impl_fasterRCNN.
#include <cmath>
#include <cstring>
#include <iostream>
#include "nvdsinfer_custom_impl.h"
#include "nvdssample_fasterRCNN_common.h"
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define CLIP(a,min,max) (MAX(MIN(a, max), min))
/* This is a sample bounding box parsing function for the sample FasterRCNN
* detector model provided with the TensorRT samples. */
extern "C"
bool NvDsInferParseCustomFasterRCNN (std::vector<NvDsInferLayerInfo> const &outputLayersInfo,
NvDsInferNetworkInfo const &networkInfo,
NvDsInferParseDetectionParams const &detectionParams,
std::vector<NvDsInferObjectDetectionInfo> &objectList);
/* C-linkage to prevent name-mangling */
extern "C"
bool NvDsInferParseCustomFasterRCNN (std::vector<NvDsInferLayerInfo> const &outputLayersInfo,
NvDsInferNetworkInfo const &networkInfo,
NvDsInferParseDetectionParams const &detectionParams,
std::vector<NvDsInferObjectDetectionInfo> &objectList)
{
static int bboxPredLayerIndex = -1;
static int clsProbLayerIndex = -1;
static int roisLayerIndex = -1;
static const int NUM_CLASSES_FASTER_RCNN = 21;
static bool classMismatchWarn = false;
int numClassesToParse;
if (bboxPredLayerIndex == -1) {
for (unsigned int i = 0; i < outputLayersInfo.size(); i++) {
if (strcmp(outputLayersInfo[i].layerName, "bbox_pred") == 0) {
bboxPredLayerIndex = i;
break;
}
}
if (bboxPredLayerIndex == -1) {
std::cerr << "Could not find bbox_pred layer buffer while parsing" << std::endl;
return false;
}
}
if (clsProbLayerIndex == -1) {
for (unsigned int i = 0; i < outputLayersInfo.size(); i++) {
if (strcmp(outputLayersInfo[i].layerName, "cls_prob") == 0) {
clsProbLayerIndex = i;
break;
}
}
if (clsProbLayerIndex == -1) {
std::cerr << "Could not find cls_prob layer buffer while parsing" << std::endl;
return false;
}
}
if (roisLayerIndex == -1) {
for (unsigned int i = 0; i < outputLayersInfo.size(); i++) {
if (strcmp(outputLayersInfo[i].layerName, "rois") == 0) {
roisLayerIndex = i;
break;
}
}
if (roisLayerIndex == -1) {
std::cerr << "Could not find rois layer buffer while parsing" << std::endl;
return false;
}
}
if (!classMismatchWarn) {
if (NUM_CLASSES_FASTER_RCNN !=
detectionParams.numClassesConfigured) {
std::cerr << "WARNING: Num classes mismatch. Configured:" <<
detectionParams.numClassesConfigured << ", detected by network: " <<
NUM_CLASSES_FASTER_RCNN << std::endl;
}
classMismatchWarn = true;
}
numClassesToParse = MIN (NUM_CLASSES_FASTER_RCNN,
detectionParams.numClassesConfigured);
float *rois = (float *) outputLayersInfo[roisLayerIndex].buffer;
float *deltas = (float *) outputLayersInfo[bboxPredLayerIndex].buffer;
float *scores = (float *) outputLayersInfo[clsProbLayerIndex].buffer;
for (int i = 0; i < nmsMaxOut; ++i)
{
float width = rois[i * 4 + 2] - rois[i * 4] + 1;
float height = rois[i * 4 + 3] - rois[i * 4 + 1] + 1;
float ctr_x = rois[i * 4] + 0.5f * width;
float ctr_y = rois[i * 4 + 1] + 0.5f * height;
float *deltas_offset = deltas + i * NUM_CLASSES_FASTER_RCNN * 4;
for (int j = 0; j < numClassesToParse; ++j)
{
float confidence = scores[i * NUM_CLASSES_FASTER_RCNN + j];
if (confidence < detectionParams.perClassPreclusterThreshold[j])
continue;
NvDsInferObjectDetectionInfo object;
float dx = deltas_offset[j * 4];
float dy = deltas_offset[j * 4 + 1];
float dw = deltas_offset[j * 4 + 2];
float dh = deltas_offset[j * 4 + 3];
float pred_ctr_x = dx * width + ctr_x;
float pred_ctr_y = dy * height + ctr_y;
float pred_w = exp(dw) * width;
float pred_h = exp(dh) * height;
float rectx1 = MIN (pred_ctr_x - 0.5f * pred_w, networkInfo.width - 1.f);
float recty1 = MIN (pred_ctr_y - 0.5f * pred_h, networkInfo.height - 1.f);
float rectx2 = MIN (pred_ctr_x + 0.5f * pred_w, networkInfo.width - 1.f);
float recty2 = MIN (pred_ctr_y + 0.5f * pred_h, networkInfo.height - 1.f);
object.classId = j;
object.detectionConfidence = confidence;
/* Clip object box co-ordinates to network resolution */
object.left = CLIP(rectx1, 0, networkInfo.width - 1);
object.top = CLIP(recty1, 0, networkInfo.height - 1);
object.width = CLIP(rectx2, 0, networkInfo.width - 1) - object.left + 1;
object.height = CLIP(recty2, 0, networkInfo.height - 1) - object.top + 1;
objectList.push_back(object);
}
}
return true;
}
/* Check that the custom function has been defined correctly */
CHECK_CUSTOM_PARSE_FUNC_PROTOTYPE(NvDsInferParseCustomFasterRCNN);
In the same directory with the parser file, we can find nvdssample_fasterRCNN_common.h
#ifndef __NVDS_SAMPLE_FASTERRCNN_COMMON_H__
#define __NVDS_SAMPLE_FASTERRCNN_COMMON_H__
const int nmsMaxOut = 300;
const int poolingH = 7;
const int poolingW = 7;
const int featureStride = 16;
const int preNmsTop = 6000;
const int anchorsRatioCount = 3;
const int anchorsScaleCount = 3;
const float iouThreshold = 0.7f;
const float minBoxSize = 16;
const float spatialScale = 0.0625f;
const float anchorsRatios[anchorsRatioCount] = {0.5f, 1.0f, 2.0f};
const float anchorsScales[anchorsScaleCount] = {8.0f, 16.0f, 32.0f};
#endif