first commit

This commit is contained in:
nqthai199@gmail.com
2022-09-15 14:33:44 +07:00
commit 24cca83c2e
13 changed files with 563 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
[property]
gpu-id=0
net-scale-factor=1
# 0:RGB 1:BGR
model-color-format=1
model-engine-file=license-plate-detection.trt
labelfile-path=labels-custom.txt
num-detected-classes=1
batch-size=1
interval=0
gie-unique-id=1
# primary
process-mode=1
# Detector
network-type=0
# FP16
network-mode=2
# 0Group Rectange 1DBSCAN 2NMS 3:DBSCAN+NMS 4:None
cluster-mode=2
maintain-aspect-ratio=1
scaling-filter=1
scaling-compute-hw=0
parse-bbox-func-name=NvDsInferParseCustomYolox
custom-lib-path=nvdsinfer_custom_impl_yolox/libnvdsinfer_custom_impl_yolox.so
[class-attrs-all]
pre-cluster-threshold=0.6
nms-iou-threshold=0.4

View File

@@ -0,0 +1 @@
license plate

Binary file not shown.

View File

@@ -0,0 +1,54 @@
#
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#CUDA_VER?=
CUDA_VER=11.2
ifeq ($(CUDA_VER),)
$(error "CUDA_VER is not set")
endif
CC:= g++
NVCC:=/usr/local/cuda-$(CUDA_VER)/bin/nvcc
CFLAGS:= -Wall -std=c++11 -shared -fPIC -Wno-error=deprecated-declarations
CFLAGS+= -I../../../includes -I/usr/local/cuda-$(CUDA_VER)/include
# CXXFLAGS:= -fopenmp
CXXFLAGS = -std=c++11
LIBS:= -lnvinfer_plugin -lnvinfer -lnvparsers -L/usr/local/cuda-$(CUDA_VER)/lib64 -lcudart -lcublas -lstdc++fs
LFLAGS:= -shared -Wl,--start-group $(LIBS) -Wl,--end-group
INCS:= $(wildcard *.h)
SRCFILES:= nvdsparsebbox_yolox.cpp
TARGET_LIB:= libnvdsinfer_custom_impl_yolox.so
TARGET_OBJS:= $(SRCFILES:.cpp=.o)
TARGET_OBJS:= $(TARGET_OBJS:.cu=.o)
all: $(TARGET_LIB)
%.o: %.cpp $(INCS) Makefile
$(CC) -c -o $@ $(CFLAGS) $(CXXFLAGS) $<
%.o: %.cu $(INCS) Makefile
$(NVCC) -c -o $@ --compiler-options '-fPIC' $<
$(TARGET_LIB) : $(TARGET_OBJS)
$(CC) -o $@ $(TARGET_OBJS) $(LFLAGS)
clean:
rm -rf $(TARGET_LIB)
rm -rf $(TARGET_OBJS)

View File

@@ -0,0 +1,240 @@
/*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include <fstream>
#include <vector>
#include <map>
#include <iostream>
// #include <omp.h>
// #include <opencv2/opencv.hpp>
#include "nvdsinfer_custom_impl.h"
#define NMS_THRESH 0.1
#define BBOX_CONF_THRESH 0.1
static const int NUM_CLASSES = 1;
static const int INPUT_W = 416;
static const int INPUT_H = 416;
static const int IMAGE_W = 1920;
static const int IMAGE_H = 1080;
const char* INPUT_BLOB_NAME = "images";
const char* OUTPUT_BLOB_NAME = "output";
static constexpr int LOCATIONS = 4;
struct alignas(float) Detection{
//center_x center_y w h
float bbox[LOCATIONS];
float conf; // bbox_conf * cls_conf
float class_id;
};
struct GridAndStride
{
int grid0;
int grid1;
int stride;
};
static void generate_grids_and_stride(std::vector<int>& strides, std::vector<GridAndStride>& grid_strides)
{
for (auto stride : strides)
{
int num_grid_y = INPUT_H / stride;
int num_grid_x = INPUT_W / stride;
for (int g1 = 0; g1 < num_grid_y; g1++)
{
for (int g0 = 0; g0 < num_grid_x; g0++)
{
/* 用于预测每层特征图上anchor的位置信息*/
grid_strides.push_back((GridAndStride){g0, g1, stride});
}
}
}
}
static void generate_yolox_proposals(std::vector<GridAndStride> grid_strides, float* feat_blob, float prob_threshold, std::vector<Detection>& objects)
{
const int num_anchors = grid_strides.size(); // 8400
for (int anchor_idx = 0; anchor_idx < num_anchors; anchor_idx++)
{
const int grid0 = grid_strides[anchor_idx].grid0;
const int grid1 = grid_strides[anchor_idx].grid1;
const int stride = grid_strides[anchor_idx].stride;
const int basic_pos = anchor_idx * (NUM_CLASSES + 5);
// yolox/models/yolo_head.py decode logic
// decode之后的bbox信息
float x_center = (feat_blob[basic_pos+0] + grid0) * stride;
float y_center = (feat_blob[basic_pos+1] + grid1) * stride;
float w = exp(feat_blob[basic_pos+2]) * stride;
float h = exp(feat_blob[basic_pos+3]) * stride;
float box_objectness = feat_blob[basic_pos+4];
for (int class_idx = 0; class_idx < NUM_CLASSES; class_idx++)
{
float box_cls_score = feat_blob[basic_pos + 5 + class_idx];
float box_prob = box_objectness * box_cls_score;
if (box_prob > prob_threshold)
{
Detection obj;
obj.bbox[0] = x_center;
obj.bbox[1] = y_center;
obj.bbox[2] = w;
obj.bbox[3] = h;
obj.class_id = class_idx;
obj.conf = box_prob;
objects.push_back(obj);
}
} // class loop
} // point anchor loop
}
bool cmp(Detection& a, Detection& b)
{
return a.conf > b.conf;
}
float iou(float lbox[4], float rbox[4])
{
float interBox[] =
{
std::max(lbox[0] - lbox[2]/2.f , rbox[0] - rbox[2]/2.f), //left
std::min(lbox[0] + lbox[2]/2.f , rbox[0] + rbox[2]/2.f), //right
std::max(lbox[1] - lbox[3]/2.f , rbox[1] - rbox[3]/2.f), //top
std::min(lbox[1] + lbox[3]/2.f , rbox[1] + rbox[3]/2.f), //bottom
};
if(interBox[2] > interBox[3] || interBox[0] > interBox[1])
return 0.0f;
float interBoxS =(interBox[1]-interBox[0])*(interBox[3]-interBox[2]);
return interBoxS/(lbox[2]*lbox[3] + rbox[2]*rbox[3] -interBoxS);
}
void nms_bboxes(std::vector<Detection>& proposals, std::vector<Detection>& res,float nms_thresh)
{
// int det_size = sizeof(Detection) / sizeof(float);
std::map<float, std::vector<Detection>> m;
for (unsigned int i = 0; i < proposals.size(); i++)
{
Detection det = proposals[i];
if (m.count(det.class_id) == 0) m.emplace(det.class_id, std::vector<Detection>());
m[det.class_id].push_back(det);
}
for (auto it = m.begin(); it != m.end(); it++)
{
auto& dets = it->second;
std::sort(dets.begin(), dets.end(), cmp);
for (size_t m = 0; m < dets.size(); ++m)
{
auto& item = dets[m];
res.push_back(item);
for (size_t n = m + 1; n < dets.size(); ++n)
{
if (iou(item.bbox, dets[n].bbox) > nms_thresh)
{
dets.erase(dets.begin()+n);
--n;
}
}
}
}
}
static void decode_outputs(float* prob, std::vector<Detection>& objects, float scale, const int img_w, const int img_h) {
std::vector<Detection> proposals;
std::vector<int> strides = {8, 16, 32};
std::vector<GridAndStride> grid_strides;
generate_grids_and_stride(strides, grid_strides);
generate_yolox_proposals(grid_strides, prob, BBOX_CONF_THRESH, proposals);
// NMS
nms_bboxes(proposals, objects, NMS_THRESH);
}
/* This is a sample bounding box parsing function for the sample YoloV5 detector model */
static bool NvDsInferParseYolox(
std::vector<NvDsInferLayerInfo> const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector<NvDsInferParseObjectInfo>& objectList)
{
float* prob = (float*)outputLayersInfo[0].buffer;
std::vector<Detection> objects;
float scale = std::min(INPUT_W / (IMAGE_W*1.0), INPUT_H / (IMAGE_H*1.0));
decode_outputs(prob, objects, scale, IMAGE_W, IMAGE_H);
float scale_bbox_width = 0.25f;
float scale_bbox_height = 0.4f;
for(auto& r : objects) {
NvDsInferParseObjectInfo oinfo;
oinfo.classId = r.class_id;
oinfo.left = static_cast<unsigned int>(r.bbox[0]-r.bbox[2]*0.5f);
oinfo.top = static_cast<unsigned int>(r.bbox[1]-r.bbox[3]*0.5f);
oinfo.width = static_cast<unsigned int>(r.bbox[2]);
oinfo.height = static_cast<unsigned int>(r.bbox[3]);
oinfo.detectionConfidence = r.conf;
float x1 = oinfo.left / scale;
float y1 = oinfo.top / scale;
float width = oinfo.width / scale;
float height = oinfo.height / scale;
float x2 = x1 + width;
float y2 = y1 + height;
x1 = ((x1 - scale_bbox_width * width) >= 0) ? (x1 - scale_bbox_width * width) : 0;
y1 = ((y1 - scale_bbox_height * height) >= 0) ? (y1 - scale_bbox_height * height) : 0;
x2 = ((x2 + scale_bbox_width * width) <= IMAGE_W) ? (x2 + scale_bbox_width * width) : IMAGE_W;
y2 = ((y2 + scale_bbox_height * height) <= IMAGE_H) ? (y2 + scale_bbox_height * height) : IMAGE_H;
oinfo.left = (float) x1 * scale;
oinfo.top = (float) y1 * scale;
oinfo.width = (float) (x2 - x1) * scale;
oinfo.height = (float) (y2 - y1) * scale;
objectList.push_back(oinfo);
}
return true;
}
extern "C" bool NvDsInferParseCustomYolox(
std::vector<NvDsInferLayerInfo> const &outputLayersInfo,
NvDsInferNetworkInfo const &networkInfo,
NvDsInferParseDetectionParams const &detectionParams,
std::vector<NvDsInferParseObjectInfo> &objectList)
{
return NvDsInferParseYolox(
outputLayersInfo, networkInfo, detectionParams, objectList);
}
/* Check that the custom function has been defined correctly */
CHECK_CUSTOM_PARSE_FUNC_PROTOTYPE(NvDsInferParseCustomYolox);