.hpp
#ifndef _H_OBJECT_DETECTION_H_
#define _H_OBJECT_DETECTION_H_
#include <torch/script.h>
#include <NumCpp.hpp>
#include <opencv2/opencv.hpp>
#include <common.hpp>
#include "base/deepnet/include/NeuralNet.hpp"
#include "base/deepnet/include/TorchWrapper.hpp"
#include "c10/cuda/CUDAException.h"
#include "c10/cuda/CUDAFunctions.h"
//#define SIMD_OPENCV_ENABLE
//#include "Simd/SimdLib.hpp"
#ifdef USE_CN_1XX
#include "../cn/include/cn.hpp"
#include "../cn/include/Task.hpp"
#elif USE_CN_2XX
#include "../cn2/include/cn.hpp"
#include "../cn2/include/Task.hpp"
#endif
#define OBJECT_NUM 150 //最大目标数量
#define OBJECT_THRESH 0.1 //目标检测阈值
#define OBJECT_CLASSES_NUM 7 //目标类别数
//#define USE_TORCHHALF_DETECT_CENTERNET //使用litorch1.0半精度
#define USE_TORCH_DETECT_CENTERNET //使用libtorch1.0全精度
//#define USE_TENSORRT_DETECT_CENTERNET //使用tensorRt
class VIRDataCollection;
class VIRTrafficElementExtraction;
struct Meta
{
int inputHeight = 0;
int inputWeight = 0;
nc::NdArray<float> c;
float s;
int out_height;
int out_width;
};
/*********************************************************************
类的功能: 目标(行人和车辆)检测
*********************************************************************/
class VIRObjetDetectionCenterNet
{
public:
VIRObjetDetectionCenterNet();
~VIRObjetDetectionCenterNet();
static VIRObjetDetectionCenterNet &ins();
int init(const std::string& configPath, const int& gpu_id);
void preprocess(const cv::Mat& image_input, cv::Mat& floatImg, Meta& meta);
void postprocess(cv::Mat& img, torch::Tensor& output_c, torch::Tensor& output_w,
torch::Tensor& output_h,torch::Tensor& output_maxpool, Meta& meta,
std::vector<sObjetDetectionOutput> &OutputObjectLoc);
int process(const cv::Mat& vImg, std::vector<sObjetDetectionOutput> &vvOutputObjectLoc);
int processBatch(const std::vector<cv::Mat>& imgs, const int batchNum, std::vector<std::vector<sObjetDetectionOutput>>& results);
int get_pedestrian( std::vector<std::vector<sObjetDetectionOutput> >& vvObject, std::vector<std::vector<cv::Rect>>& vvRect);
int uninit();
private:
VIRDataCollection *pVIRDataCollection;
VIRTrafficElementExtraction *pVIRTrafficElementExtraction;
#if defined(USE_CN_2XX)
const std::string m_modelFile = "/objdet_centernet/objdet_centernet.prototxt";
#else
const std::string m_modelFile = "/objdet_centernet/objdet_centernet.pth";
#endif
const std::string m_weightFile = "/objdet_centernet/objdet_centernet.caffemodel";
const std::string m_meanValue = "";
const std::string m_normalize_scalar = "";
std::map<std::string,std::string> m_configs;
std::shared_ptr<NeuralNet> m_net;
std::vector<torch::jit::IValue> inputs;
int w_ = 608;
int h_ = 608;
int outPutW = 0;
int outPutH = 0;
#if defined(USE_CN_2XX)
// std::shared_ptr<cn::Net> module;
#else
std::shared_ptr<torch::jit::script::Module> module;
#endif
const std::string modelFile = "/objdet_centernet/DLA_C++.pt";
std::shared_ptr<torch::jit::script::Module> net_;
};
#endif // _H_OBJECT_DETECTION_H_
.cpp
#include <common.hpp>
#include "./include/objectDetectionCenterNet.h"
//#define LIBTORCH_NEW_VERSION
#ifndef LIBTORCH_NEW_VERSION
extern "C" void THCCachingAllocator_emptyCache(void);
#endif
using namespace nc;
//using namespace c10;
VIRObjetDetectionCenterNet &VIRObjetDetectionCenterNet::ins()
{
static VIRObjetDetectionCenterNet obj;
return obj;
}
VIRObjetDetectionCenterNet::VIRObjetDetectionCenterNet()
{
}
VIRObjetDetectionCenterNet::~VIRObjetDetectionCenterNet()
{
}
//非极大值抑制
std::vector<nc::NdArray<float>> soft_nms(std::vector<nc::NdArray<float>> boxes_, float Nt=0.5)
{
nc::NdArray<float> boxes = nc::concatenate({boxes_[0], boxes_[1], boxes_[2], boxes_[3], boxes_[4], boxes_[5], boxes_[6]}, Axis::ROW);
int N = boxes.shape().rows;//行数
int pos = 0;
for (int i = 0; i < N; i++)
{
int tx1 = boxes(i, 0);//左上点X坐标
int ty1 = boxes(i, 1);//左上点Y坐标
int tx2 = boxes(i, 2);//右下点X坐标
int ty2 = boxes(i, 3);//右下点Y坐标
float ts = boxes(i, 4);//置信度
if (ts < 0.1)
{
boxes(i, 4) = 0 * boxes(i, 4);
continue;
}
//遍历后面的矩形框
pos = i + 1;
while (pos < N)
{
int x1 = boxes(pos, 0);
int y1 = boxes(pos, 1);
int x2 = boxes(pos, 2);
int y2 = boxes(pos, 3);
float s = boxes(pos, 4);
if (s < 0.1)
{
boxes(pos, 4) = 0 * boxes(pos, 4);
pos = pos + 1;
continue;
}
int area = (x2 - x1 + 1) * (y2 - y1 + 1);
int iw = (MIN(tx2, x2) - MAX(tx1, x1) + 1);
if (iw > 0)
{
int ih = (MIN(ty2, y2) - MAX(ty1, y1) + 1);
if (ih > 0)
{
float ua = float((tx2 - tx1 + 1) * (ty2 - ty1 + 1) + area - iw * ih);
float ov = iw * ih / ua; //IOU
if (ov > Nt)//IOU大于阈值则过滤;把置信度低的过滤
{
if (ts > s)
{
boxes(pos, 4) = 0 * boxes(pos, 4);
}
else
{
boxes(i, 4) = 0 * boxes(i, 4);
tx1 = boxes(pos, 0);
ty1 = boxes(pos, 1);
tx2 = boxes(pos, 2);
ty2 = boxes(pos, 3);
ts = boxes(pos, 4);
}
}
}
}
pos = pos + 1;
}
}
int a1 = boxes_[0].shape().rows;
int a2 = a1+boxes_[1].shape().rows;
int a3 = a2+boxes_[2].shape().rows;
int a4 = a3+boxes_[3].shape().rows;
int a5 = a4+boxes_[4].shape().rows;
int a6 = a5+boxes_[5].shape().rows;
int a7 = a6+boxes_[6].shape().rows;
boxes_[0] = boxes({0,a1},boxes.cSlice());
boxes_[1] = boxes({a1,a2},boxes.cSlice());
boxes_[2] = boxes({a2,a3},boxes.cSlice());
boxes_[3] = boxes({a3,a4},boxes.cSlice());
boxes_[4] = boxes({a4,a5},boxes.cSlice());
boxes_[5] = boxes({a5,a6},boxes.cSlice());
boxes_[6] = boxes({a6,a7},boxes.cSlice());
return boxes_;
}
void add_coco_bbox(nc::NdArray<float> bbox, int cat, cv::Mat image, float conf)
{
//char txt[256];
//sprintf(txt,"%s_%f",names[cat],conf);
//int font = cv::FONT_HERSHEY_SIMPLEX;
//int baseline;Scalar
//cv::Size text_size = cv::getTextSize(txt, font, 0.5, 2, &baseline);
if ( 0 == cat )
{
cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1), bbox(0,2)-bbox(0,0), bbox(0,3)-bbox(0,1)), cv::Scalar(0,0,255), 2);
}
else if ( 1 == cat )
{
cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1), bbox(0,2)-bbox(0,0), bbox(0,3)-bbox(0,1)), cv::Scalar(0,255,255), 2);
}
else if ( 2 == cat )
{
cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1), bbox(0,2)-bbox(0,0), bbox(0,3)-bbox(0,1)), cv::Scalar(255,0,255), 2);
}
else if ( 3 == cat )
{
cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1), bbox(0,2)-bbox(0,0), bbox(0,3)-bbox(0,1)), cv::Scalar(255,0,0), 2);
}
else if ( 4 == cat )
{
cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1), bbox(0,2)-bbox(0,0), bbox(0,3)-bbox(0,1)), cv::Scalar(0,255,0), 2);
}
else if ( 5 == cat )
{
cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1), bbox(0,2)-bbox(0,0), bbox(0,3)-bbox(0,1)), cv::Scalar(255,255,0), 2);
}
else
{
cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1), bbox(0,2)-bbox(0,0), bbox(0,3)-bbox(0,1)), cv::Scalar(0,128,255), 2);
}
//cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1)-text_size.height-2, bbox(0,0)+text_size.width, bbox(0,1)-2), (0,255,0), -1);
//cv::rectangle(image, cv::Rect(bbox(0,0), bbox(0,1), bbox(0,0), bbox(0,1)-2), (0,255,0), -1);
//cv::putText(image, txt, cv::Point(bbox(0,0), bbox(0,1)-2), 0, 0.5, (0, 0, 0), 1, cv::LINE_AA);
}
void show_results(cv::Mat image, std::vector<nc::NdArray<float>> results)
{
for (int i = 0; i < results.size(); i++)
{
for (int j = 0; j < results[i].shape().rows; j++)
{
if (results[i](j,4) > OBJECT_THRESH)//置信度阈值
{
add_coco_bbox(results[i](j,{0,4}), i, image, results[i](j,4));
}
}
}
cv::namedWindow("result", 0);
cv::imshow("result", image);
cv::waitKey();
//cv::destroyAllWindows();
}
void naive_arg_topK_3d(nc::NdArray<float> matrix, int K, int axis,nc::NdArray<float> &max_score,NdArray<uint32> &max_k)
{
NdArray<uint32> full_sort = nc::argsort(-matrix, Axis::COL); //"-"是降序排列,full_sort是索引,axis=0竖向,1行向
// NdArray<uint32> max_k = nc::copy(full_sort(full_sort.rSlice(),{0, K})); //取前K个数, 深拷贝:full_sort和max_k的整体是一个独立的对象。
// nc::NdArray<float> max_score = nc::zeros<float>(5, K);
max_k = nc::copy(full_sort(full_sort.rSlice(),{0, K})); //取前K个数, 深拷贝:full_sort和max_k的整体是一个独立的对象。
for (int i = 0; i < OBJECT_CLASSES_NUM; i++)
{
for (int j = 0; j < K; j++)
{
max_score(i,j) = matrix(i,max_k(i,j));
}
}
//return max_score,max_k
}
void naive_arg_topK_2d(nc::NdArray<float> matrix, int K, int axis, nc::NdArray<float> &max_score, NdArray<uint32> &max_k)
{
NdArray<uint32> full_sort = nc::argsort(-matrix, Axis::COL); //"-"是降序排列,full_sort是索引,axis=0竖向,1行向
max_k = nc::copy(full_sort(full_sort.rSlice(),{0, K})); //取前K个数,axis=0竖向,1行向# 深拷贝:full_sort和max_k的整体是一个独立的对象。
//nc::NdArray<float> max_score = nc::zeros<float>(5, K);
for (int j = 0; j < K; j++)
{
max_score(0,j) = matrix(0,max_k(0,j));
}
//return max_score,max_k
}
float sigmoid(float x)
{
return (1 / (1 + exp(-x)));
}
nc::NdArray<float> get_3rd_point(nc::NdArray<float> a, nc::NdArray<float> b)
{
nc::NdArray<float> direct = a - b;
return b + nc::NdArray<float>{-direct[1], direct[0]};
}
nc::NdArray<float> get_dir(nc::NdArray<float> src_point, float rot_rad)
{
float sn = nc::sin(rot_rad);
float cs = nc::cos(rot_rad);
nc::NdArray<float> src_result = {0, 0};
src_result[0] = src_point[0] * cs - src_point[1] * sn;
src_result[1] = src_point[0] * sn + src_point[1] * cs;
return src_result;
}
cv::Mat get_affine_transform(nc::NdArray<float> center, float scale, float rot, int output_size[2],nc::NdArray<float> shift = {0, 0},int inv=0)
{
nc::NdArray<float> scales = {scale, scale};//创建矩阵
nc::NdArray<float> scale_tmp = scales;
float src_w = scale_tmp[0];
int dst_w = output_size[0];
int dst_h = output_size[1];
float rot_rad = nc::constants::pi * rot / 180;
nc::NdArray<float> src_dir = get_dir(nc::NdArray<float>{0, float(src_w * -0.5)}, rot_rad);
nc::NdArray<float> dst_dir = {0, float(dst_w * -0.5)};
nc::NdArray<float> src = nc::zeros<float>(3, 2);
nc::NdArray<float> dst = nc::zeros<float>(3, 2);
nc::NdArray<float> temp;
temp = center + scale_tmp * shift;
src(0, 0) = temp(0,0);
src(0, 1) = temp(0,1);
temp = center + src_dir + scale_tmp * shift;
src(1, 0) = temp(0,0);
src(1, 1) = temp(0,1);
temp = dst_w * 0.5, dst_h * 0.5;
dst(0, 0) = temp(0,0);
dst(0, 1) = temp(0,1);
temp = nc::NdArray<float>{float(dst_w * 0.5), float(dst_h * 0.5)} + dst_dir;
dst(1, 0) = temp(0,0);
dst(1, 1) = temp(0,1);
temp = get_3rd_point(src(0, src.cSlice()), src(1, src.cSlice()));
src(2, 0) = temp(0,0);
src(2, 1) = temp(0,1);
temp = get_3rd_point(dst(0, dst.cSlice()), dst(1, dst.cSlice()));
dst(2, 0) = temp(0,0);
dst(2, 1) = temp(0,1);
cv::Mat trans;
cv::Point2f SRC[3];
cv::Point2f DST[3];
// Set your 3 points to calculate the Affine Transform
SRC[0] = cv::Point2f(src(0,0),src(0,1));//numcpp to opencv`s point2f
SRC[1] = cv::Point2f(src(1,0),src(1,1));
SRC[2] = cv::Point2f(src(2,0),src(2,1));
DST[0] = cv::Point2f(dst(0,0),dst(0,1));
DST[1] = cv::Point2f(dst(1,0),dst(1,1));
DST[2] = cv::Point2f(dst(2,0),dst(2,1));
if (1 == inv)
{
trans = cv::getAffineTransform(DST, SRC);
}
else
{
trans = cv::getAffineTransform(SRC, DST);
}
return trans;
}
nc::NdArray<uint32> _gather_feat(nc::NdArray<uint32> feat, nc::NdArray<uint32> ind)
{
nc::NdArray<uint32> result;
int dim = feat.shape().cols;//第二维
ind.reshape(ind.shape().cols, ind.shape().rows);//unsqueeze(2)
if (2 == dim)
{
ind = nc::concatenate({ind,ind},Axis::COL);//expand(ind.size(0), ind.size(1), dim)#expand扩展某个size为1的维度到dim维,[1,500,1]=>[1,500,dim]
result = nc::zeros<uint32>(OBJECT_NUM, 2);
for (int i = 0; i < OBJECT_NUM; i++)
{
for (int j = 0; j < 2; j++)
{
result(i,j) = feat(ind(i,j),j); //gather
}
}
}
else
{
result = nc::zeros<uint32>(OBJECT_NUM, 1);
for (int i = 0; i < OBJECT_NUM; i++)
{
result(i,0) = feat(ind(i,0),0); //gather
}
}
return result;
}
nc::NdArray<float> _gather_feat(nc::NdArray<float> feat, nc::NdArray<uint32> ind)
{
nc::NdArray<float> result;
int dim = feat.shape().cols;//第二维
ind.reshape(ind.shape().cols, ind.shape().rows);//unsqueeze(2)
if (2 == dim)
{
ind = nc::concatenate({ind,ind},Axis::COL);//expand(ind.size(0), ind.size(1), dim)#expand扩展某个size为1的维度到dim维,[1,500,1]=>[1,500,dim]
result = nc::zeros<float>(OBJECT_NUM, 2);
for (int i = 0; i < OBJECT_NUM; i++)
{
for (int j = 0; j < 2; j++)
{
result(i,j) = feat(ind(i,j),j); //gather
}
}
}
else
{
result = nc::zeros<float>(OBJECT_NUM, 1);
for (int i = 0; i < OBJECT_NUM; i++)
{
result(i,0) = feat(ind(i,0),0); //gather
}
}
return result;
}
void _tranpose_and_gather_feat(nc::NdArray<float> &feat, nc::NdArray<uint32> ind)//[1,2,128,128],[1,500]
{
nc::NdArray<float> feat_trans = feat.transpose();
feat = _gather_feat(feat_trans, ind);//[1,500,2]
}
void _topk(nc::NdArray<float> heat, int K, nc::NdArray<float> &topk_score, nc::NdArray<uint32> &topk_inds,
nc::NdArray<uint32> &topk_clses, nc::NdArray<uint32> &topk_ys, nc::NdArray<uint32> &topk_xs)
{
int cat = OBJECT_CLASSES_NUM;
// int height=128;
// int width = 128;
int height=152;
int width = 152;
nc::NdArray<float> topk_scores = nc::zeros<float>(OBJECT_CLASSES_NUM, OBJECT_NUM);
nc::NdArray<uint32> topk_inds_3d = nc::zeros<uint32>(OBJECT_CLASSES_NUM, OBJECT_NUM);
//naive_arg_topK_3d(heat.reshape(cat, 128*128), K, 1, topk_scores, topk_inds_3d);
naive_arg_topK_3d(heat.reshape(cat, 152*152), K, 1, topk_scores, topk_inds_3d);
for (int i = 0; i < OBJECT_CLASSES_NUM; i++)
{
for (int j = 0; j < OBJECT_NUM; j++)
{
topk_inds_3d(i, j) = topk_inds_3d(i, j)%(height * width);
topk_ys(i,j) = (topk_inds_3d(i, j) / width);
topk_xs(i,j) = (topk_inds_3d(i, j) % width);
}
}
nc::NdArray<uint32> topk_ind = nc::zeros<uint32>(1, OBJECT_NUM);
naive_arg_topK_2d(topk_scores.reshape(1, OBJECT_CLASSES_NUM*OBJECT_NUM), K, 1, topk_score, topk_ind);
for (int j = 0; j < OBJECT_NUM; j++)
{
topk_clses(0,j) = (topk_ind(0, j) / K);
}
nc::NdArray<uint32> topk_inds_ = _gather_feat(topk_inds_3d.reshape(OBJECT_CLASSES_NUM*OBJECT_NUM, 1), topk_ind);
nc::NdArray<uint32> topk_ys_ = _gather_feat(topk_ys.reshape(OBJECT_CLASSES_NUM*OBJECT_NUM, 1), topk_ind);
nc::NdArray<uint32> topk_xs_ = _gather_feat(topk_xs.reshape(OBJECT_CLASSES_NUM*OBJECT_NUM, 1), topk_ind);
topk_inds = nc::copy(topk_inds_.reshape(1,K));
topk_ys = nc::copy(topk_ys_.reshape(1,K));
topk_xs = nc::copy(topk_xs_.reshape(1,K));
//return topk_score, topk_inds, topk_clses, topk_ys, topk_xs;
}
nc::NdArray<float> ctdet_decode(nc::NdArray<float> heat, nc::NdArray<float> wh, nc::NdArray<float> reg, bool cat_spec_wh, int K)
{
//cat, size = heat.shape
//scores, inds, clses, ys, xs = _topk(heat, K=K)
nc::NdArray<float> scores = nc::zeros<float>(1, OBJECT_NUM);
nc::NdArray<uint32> inds = nc::zeros<uint32>(1, OBJECT_NUM);
nc::NdArray<uint32> clses = nc::zeros<uint32>(1, OBJECT_NUM);
nc::NdArray<uint32> ys = nc::zeros<uint32>(OBJECT_CLASSES_NUM, OBJECT_NUM);
nc::NdArray<uint32> xs = nc::zeros<uint32>(OBJECT_CLASSES_NUM, OBJECT_NUM);
_topk(heat, K, scores, inds, clses, ys, xs);
nc::NdArray<float> XS;
nc::NdArray<float> YS;
if (reg.size())//非空
{
_tranpose_and_gather_feat(reg, inds);
reg.reshape(K, 2);
nc::NdArray<float> xs_float = xs.reshape(K, 1).astype<float>();
XS = xs_float + reg(reg.rSlice(),{0, 1});
nc::NdArray<float> ys_float = ys.reshape(K, 1).astype<float>();
YS = ys_float + reg(reg.rSlice(),{1, 2});
}
else
{
nc::NdArray<float> xs_float = xs.reshape(K, 1).astype<float>();
XS = xs_float + 0.5;
nc::NdArray<float> ys_float = ys.reshape(K, 1).astype<float>();
YS = ys_float + 0.5;
}
_tranpose_and_gather_feat(wh, inds);
if (cat_spec_wh)
{
}
else
{
wh.reshape(K, 2);
}
nc::NdArray<float> clses_float = clses.reshape(K, 1).astype<float>();
scores.reshape(K, 1);
nc::NdArray<float> bboxes = nc::concatenate({XS - wh(wh.rSlice(),{0, 1}) / 2,
YS - wh(wh.rSlice(),{1, 2}) / 2,
XS + wh(wh.rSlice(),{0, 1}) / 2,
YS + wh(wh.rSlice(),{1, 2}) / 2}, Axis::COL);
nc::NdArray<float> detections = nc::concatenate({bboxes, scores, clses_float}, Axis::COL);
return detections;
}
nc::NdArray<float> affine_transform(nc::NdArray<float> pt, nc::NdArray<float> t)
{
nc::NdArray<float> new_pt = {pt(0,0), pt(0,1),1.0};
new_pt = new_pt.transpose();
nc::NdArray<float> new_pt_dot = nc::dot(t, new_pt);
return new_pt_dot({0,2},0);
}
nc::NdArray<float> transform_preds(nc::NdArray<float> coords, nc::NdArray<float> center, float scale, int output_size[2])
{
nc::NdArray<float> target_coords = nc::zeros<float>(coords.shape());
nc::NdArray<float> target_coords_temp;
cv::Mat trans = get_affine_transform(center, scale, 0, output_size, {0, 0}, 1);
nc::NdArray<float> trans_NdArray = nc::zeros<float>(trans.rows, trans.cols);
double* ptr_data = (double*)trans.data;
for (int i = 0; i < trans.rows; i++)
{
for (int j = 0; j < trans.cols; j++)
{
trans_NdArray(i,j) = (float)ptr_data[i*trans.cols+j];
//printf("====%d====\n",ptr_data[3*i*trans.cols+3*0+0]);
}
}
//trans_NdArray.astype<float>();
for (int p = 0; p < coords.shape().rows; p++)
{
target_coords_temp = nc::copy(affine_transform(coords(p, {0,2}), trans_NdArray));
for (int q = 0; q < 2; q++)
{
target_coords(p, q) = target_coords_temp(q,0);
}
}
return target_coords;
}
std::vector<nc::NdArray<float>> ctdet_post_process(nc::NdArray<float> dets, nc::NdArray<float> c, float s, int h, int w, int num_classes)
{
//top_preds = {}
int w_h[2]={w,h};
nc::NdArray<float> dets_01 = transform_preds(dets(dets.rSlice(), {0, 2}), c, s, w_h);
nc::NdArray<float> dets_23 = transform_preds(dets(dets.rSlice(), {2, 4}), c, s, w_h);
nc::NdArray<float> classes = dets(dets.rSlice(), {5, 6});
std::vector<nc::NdArray<float>> ret;
nc::NdArray<float> dets_cat = nc::concatenate({dets_01, dets_23, dets(dets.rSlice(), {4, 5})}, Axis::COL);
for (int i = 0; i < OBJECT_CLASSES_NUM; i++)
{
int sum_same = 0;
nc::NdArray<float> inds = nc::zeros<float>(OBJECT_NUM,1);//标置位
for (int j = 0; j < OBJECT_NUM; j++)
{
if (abs(classes(j, 0)-i) < 0.000001)//相等则置1,否则为0
{
inds(j,0) = 1;
sum_same++;
}
}
nc::NdArray<float> dets_post = nc::zeros<float>(OBJECT_NUM, 5);//标置位
for (int j = 0; j < OBJECT_NUM; j++)
{
for (int k = 0; k < 5; k++)//(boxes=4)+1+1
{
dets_post(j,k) = dets_cat(j,k)*inds(j,0);
}
}
//nc::append(ret,dets_post,Axis::COL);
ret.push_back(dets_post);
}
return ret;
}
std::vector<nc::NdArray<float>> post_process(nc::NdArray<float> dets, Meta meta)
{
//dets = dets.reshape(-1, dets.shape[1]);
nc::NdArray<float> c = meta.c;
float s = meta.s;
int out_height = meta.out_height;
int out_width = meta.out_width;
std::vector<nc::NdArray<float>> dets_result;
dets_result = ctdet_post_process(dets, c, s, out_height, out_width, OBJECT_CLASSES_NUM);
return dets_result;
}
int VIRObjetDetectionCenterNet::init(const std::string& configPath, const int& gpu_id)
{
#ifdef USE_TORCHHALF_DETECT_CENTERNET
torch::Device device(torch::kCUDA, gpu_id);
//c10::cuda::set_device(DeviceID);
module = torch::jit::load(configPath+modelFile);
//module->to(at::kCUDA); // put model to gpu
module->to(torch::kHalf);//半精度
module->to(device);
#elif defined(USE_TORCH_DETECT_CENTERNET)
int ret = setenv("CUDA_VISIBLE_DEVICES", std::to_string(gpu_id).c_str(), 1);
if(ret !=0)
{
throw std::runtime_error("set CUDA_VISIBLE_DEVICES failed");
}
c10::cuda::set_device(gpu_id);
//加载模型
std::string modelPath=configPath+modelFile;
if(access(modelPath.c_str(),F_OK)==-1)
{
return PROCESS_FAIL;
}
module= torch::jit::load(modelPath,torch::kCUDA); ///可以选择在cpu中加载模型也可以选择在GPU中加载模型,但是最后都要将加载的模型再放到GPU中
module->to(at::kCUDA); //torch1.0使用
#else
setModelFile(m_configs, configPath+m_modelFile);
setWeightFile(m_configs,configPath+m_weightFile);
setMeanValue(m_configs, m_meanValue);
setNormalizeScalar(m_configs, m_normalize_scalar);
setGPUID(m_configs, std::to_string(gpu_id));
m_net.reset(new TorchWrapper(m_configs));
#endif
return PROCESS_SUCCESS;
//#if defined(USE_CN_2XX)
// module.reset(new cn::Net(modelPath + "/objdet_centernet/objdet_centernet.cambricon"));
//#else
// module = torch::jit::load(modelPath + "/yolo/DLA_C++.pt");
// module->to(at::kCUDA); // put model to gpu
//#endif
// return PROCESS_SUCCESS;
}
inline void Preprocess_centernet(cv::Mat &img, cv::Mat &resimg)
{
cv::Mat image=((img/255.0)-cv::Scalar(0.408, 0.447, 0.470));
// cv::namedWindow("test_image",0);
// cv::imshow("test_image",image);
// cv::waitKey(0);
std::vector<cv::Mat> channels;
cv::split(image,channels);
cv::Mat B = channels.at(0);//从vector中读数据用vector::at()
cv::Mat G = channels.at(1);
cv::Mat R = channels.at(2);
B = B / 0.289;
G = G / 0.274;
R = R / 0.278;
std::vector<cv::Mat> src;
src.push_back(B);//往vector里存数据要用vector::push_back()
src.push_back(G);
src.push_back(R);
cv::merge(src,resimg);
// cv::namedWindow("test_image",0);
// cv::imshow("test_image",resimg);
// cv::waitKey(0);
}
void VIRObjetDetectionCenterNet::preprocess(const cv::Mat& image_input, cv::Mat& floatImg, Meta& meta)
{
meta.inputWeight = image_input.cols;
meta.inputHeight = image_input.rows;
cv::Mat imgin;
cv::copyMakeBorder(image_input,imgin, 0, 30, 0, 30, cv::BORDER_CONSTANT, 0);
int width = imgin.cols;//宽
int height = imgin.rows;//高
nc::NdArray<float> c = {float(width/2), float(height/2)};
float s = MAX(height, width) * 1.0;
// s = s+(s/608.0)*5*2;
meta.c = c;
meta.s = s;
meta.out_width = w_/4;
meta.out_height = h_/4;
//int size_input[2] = {512,512};
int size_input[2] = {608,608};
cv::Mat trans_output;
trans_output = get_affine_transform(c, s, 0, size_input);
cv::Mat x=imgin.clone();
cv::Mat warp_dst;
cv::resize(x, x, cv::Size(width, height));
// Apply the Affine Transform just found to the src image
cv::warpAffine( x, warp_dst, trans_output, cv::Size(w_, h_));
warp_dst.convertTo(floatImg, CV_32FC3);
}
void VIRObjetDetectionCenterNet::postprocess(cv::Mat& img, torch::Tensor& output_c, torch::Tensor& output_w,
torch::Tensor& output_h,torch::Tensor& output_maxpool, Meta& meta,
std::vector<sObjetDetectionOutput> &OutputObjectLoc) {
// 直接用指针从tensor中取数据的方式
float* ptr_output_c = (float*)output_c.data_ptr();
float* ptr_output_w = (float*)output_w.data_ptr();
float* ptr_output_h = (float*)output_h.data_ptr();
float* ptr_output_maxpool = (float*)output_maxpool.data_ptr();
const float *data_blob53 = ptr_output_c;
const float *data_pool53 = ptr_output_maxpool;
const float *data_blob55 = ptr_output_w;
const float *data_blob57 = ptr_output_h;
int size_feature = 152*152;
nc::NdArray<float> hm = nc::zeros<float>(OBJECT_CLASSES_NUM, size_feature);//heatmap
nc::NdArray<float> pool53 = nc::zeros<float>(OBJECT_CLASSES_NUM, size_feature);//heatmap=>maxpooling
nc::NdArray<float> keep = nc::zeros<float>(OBJECT_CLASSES_NUM, size_feature);//标置位
nc::NdArray<float> heat = nc::zeros<float>(OBJECT_CLASSES_NUM, size_feature);//处理过的heatmap
nc::NdArray<float> wh = nc::zeros<float>(2, size_feature);//width,height
nc::NdArray<float> reg = nc::zeros<float>(2, size_feature);//回归的位置,偏移?
for (int i = 0; i < OBJECT_CLASSES_NUM; i++)
{
for (int j = 0; j < size_feature; j++)
{
hm(i, j) = sigmoid(data_blob53[i*size_feature+j]);
pool53(i, j) = sigmoid(data_pool53[i*size_feature+j]);
if (abs(pool53(i, j)-hm(i, j)) < 0.000001)//相等则置1,否则为0
{
keep(i,j) = 1;
}
heat(i, j) = hm(i, j) * keep(i,j);
}
}
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < size_feature; j++)
{
wh(i, j) = data_blob55[i*size_feature+j];
reg(i, j) = data_blob57[i*size_feature+j];
}
}
nc::NdArray<float> dets = ctdet_decode(heat, wh, reg, false, OBJECT_NUM);
std::vector<nc::NdArray<float>> result_dets = post_process(dets, meta);
std::vector<nc::NdArray<float>>result_dets_nms = soft_nms(result_dets, 0.5);
// show_results(imgin, result_dets_nms);
//=================================//把检测结果传出output//=================================//
std::vector<sObjetDetectionOutput> result;
result.clear();
for (int i = 0; i < result_dets_nms.size(); i++)
{
for (int j = 0; j < result_dets_nms[i].shape().rows; j++)
{
if (result_dets_nms[i](j,4) > OBJECT_THRESH)//置信度阈值
{
sObjetDetectionOutput object;
object.objectLocation.x = std::max(0, (int)result_dets_nms[i](j,0));
object.objectLocation.y = std::max(0, (int)result_dets_nms[i](j,1));
object.objectLocation.width = std::min((int)result_dets_nms[i](j,2), meta.inputWeight) - object.objectLocation.x;
object.objectLocation.height = std::min((int)result_dets_nms[i](j,3), meta.inputHeight) - object.objectLocation.y;
//object.objectness = 0.0;
object.objectConfidence = result_dets_nms[i](j,4);
if ((object.objectLocation.width <= 0) || (object.objectLocation.height <= 0))//过滤宽高非正数
{
continue;
}
//标签转换
if ((0 == i) || (5 == i) || (6 == i))
{
object.objectLabel = (eObjetDetectionLabel)i;
}
else if (4 == i)
{
object.objectLabel = (eObjetDetectionLabel)1;
}
else
{
object.objectLabel = (eObjetDetectionLabel)(i+1);
}
result.push_back(object);
}
}
}
OutputObjectLoc = result;
}
int VIRObjetDetectionCenterNet::processBatch(const std::vector<cv::Mat>& imgs,
const int batchNum,
std::vector<std::vector<sObjetDetectionOutput>>& results) {
std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
#ifdef USE_TORCHHALF
AaronTimer aaronTimer;
std::vector<Meta> metas;
std::vector<torch::Tensor> tensor_vec;
for (int i = 0; i < batchNum; ++i) {
cv::Mat floatImg,floatImg1;
Meta meta;
preprocess(imgs[i], floatImg1, meta);
Preprocess_centernet(floatImg1, floatImg);
metas.push_back(meta);
auto img_tensor = torch::CPU(torch::kFloat32).tensorFromBlob(floatImg.data,{1, h_, w_, 3}); //将cv::Mat转成tensor,大小为1,OBJECT_WIDTH_HEIGHT,OBJECT_WIDTH_HEIGHT,3
img_tensor = img_tensor.permute({0, 3, 1, 2}); //调换顺序变为torch输入的格式 1,3,OBJECT_WIDTH_HEIGHT,OBJECT_WIDTH_HEIGHT
auto img_var = torch::autograd::make_variable(img_tensor, false); //不需要梯度
tensor_vec.push_back(img_var.to(torch::kHalf).to(at::kCUDA)); //转半精度
}
aaronTimer.stop();
vLOG(vINFO) << "VIRObjetDetectionCenterNet--processBatch preprocess time = " << aaronTimer.m_timeMs << "ms.";
aaronTimer.start();
torch::TensorList tensor_list{tensor_vec};
torch::Tensor batch_of_tensors =torch::cat(tensor_list);
auto output = module->forward({batch_of_tensors}).toTuple();
cudaDeviceSynchronize(); //必须加入此句话,不然测试的耗时不准
torch::Tensor output_c = output->elements()[0].toTensor(); //元组转tensor
torch::Tensor output_w = output->elements()[1].toTensor();
torch::Tensor output_h = output->elements()[2].toTensor();
torch::Tensor output_maxpool=torch::max_pool2d(output_c, {3,3}, {1,1}, {1,1});
output_c = output_c.to(torch::kFloat32).to(torch::kCPU);
output_w = output_w.to(torch::kFloat32).to(torch::kCPU);
output_h = output_h.to(torch::kFloat32).to(torch::kCPU);
output_maxpool = output_maxpool.to(torch::kFloat32).to(torch::kCPU);
for (int k = 0; k < batchNum; ++k)
{
torch::Tensor output_c_ = output_c[k];
torch::Tensor output_w_ = output_w[k];
torch::Tensor output_h_ = output_h[k];
torch::Tensor output_maxpool_ = output_maxpool[k];
std::vector<sObjetDetectionOutput> result;
cv::Mat frame_ = imgs[k];
postprocess(frame_, output_c_, output_w_, output_h_,output_maxpool_, metas[k], result);
results.push_back(result);
}
aaronTimer.stop();
vLOG(vINFO) << "VIRObjetDetectionCenterNet--processBatch postprocess time = " << aaronTimer.m_timeMs << "ms.";
#elif defined(USE_TORCH)
AaronTimer aaronTimer;
std::vector<Meta> metas;
std::vector<torch::Tensor> tensor_vec;
for (int i = 0; i < batchNum; ++i) {
cv::Mat floatImg,floatImg1;
Meta meta;
preprocess(imgs[i], floatImg1, meta);
Preprocess_centernet(floatImg1, floatImg);
metas.push_back(meta);
auto img_tensor = torch::CPU(torch::kFloat32).tensorFromBlob(floatImg.data,{1, h_, w_, 3}); //将cv::Mat转成tensor,大小为1,OBJECT_WIDTH_HEIGHT,OBJECT_WIDTH_HEIGHT,3
img_tensor = img_tensor.permute({0, 3, 1, 2}); //调换顺序变为torch输入的格式 1,3,OBJECT_WIDTH_HEIGHT,OBJECT_WIDTH_HEIGHT
auto img_var = torch::autograd::make_variable(img_tensor, false); //不需要梯度
tensor_vec.push_back(img_var.to(at::kCUDA));
}
aaronTimer.stop();
vLOG(vINFO) << "VIRObjetDetectionCenterNet--processBatch preprocess time = " << aaronTimer.m_timeMs << "ms.";
aaronTimer.start();
torch::TensorList tensor_list{tensor_vec};
torch::Tensor batch_of_tensors =torch::cat(tensor_list);
auto output = module->forward({batch_of_tensors}).toTuple();
cudaDeviceSynchronize(); //必须加入此句话,不然测试的耗时不准
torch::Tensor output_c = output->elements()[0].toTensor(); //元组转tensor
torch::Tensor output_w = output->elements()[1].toTensor();
torch::Tensor output_h = output->elements()[2].toTensor();
torch::Tensor output_maxpool=torch::max_pool2d(output_c, {3,3}, {1,1}, {1,1});
output_c = output_c.to(torch::kCPU);
output_w = output_w.to(torch::kCPU);
output_h = output_h.to(torch::kCPU);
output_maxpool = output_maxpool.to(torch::kCPU);
for (int i = 0; i < batchNum; ++i)
{
torch::Tensor output_c_ = output_c[i];
torch::Tensor output_w_ = output_w[i];
torch::Tensor output_h_ = output_h[i];
torch::Tensor output_maxpool_ = output_maxpool[i];
std::vector<sObjetDetectionOutput> result;
cv::Mat frame_ = imgs[i];
postprocess(frame_, output_c_, output_w_, output_h_,output_maxpool_, metas[i], result);
results.push_back(result);
}
aaronTimer.stop();
vLOG(vINFO) << "VIRObjetDetectionCenterNet--processBatch postprocess time = " << aaronTimer.m_timeMs << "ms.";
#else
AaronTimer aaronTimer;
std::vector<Meta> metas;
std::vector<cv::Mat> floatImgs;
for (int i = 0; i < batchNum; ++i) {
cv::Mat floatImg;
Meta meta;
preprocess(imgs[i], floatImg, meta);
floatImgs.push_back(floatImg);
metas.push_back(meta);
}
aaronTimer.stop();
vLOG(vINFO) << "VIRObjetDetectionCenterNet--processBatch preprocess time = " << aaronTimer.m_timeMs << "ms.";
aaronTimer.start();
std::vector<float*> modelResults;
// void general_process(const std::vector<cv::Mat>& imgs, const int batch_num, std::vector<float*>& results);
m_net->general_process(floatImgs, batchNum, modelResults);
aaronTimer.stop();
vLOG(vINFO) << "VIRObjetDetectionCenterNet--processBatch general_process time = " << aaronTimer.m_timeMs << "ms.";
aaronTimer.start();
std::vector<int> chammel1Shape;
std::vector<int> chammel2Shape;
std::vector<int> chammel3Shape;
m_net->getOutputShape(chammel1Shape, 0); // NCHW
m_net->getOutputShape(chammel2Shape, 1);
m_net->getOutputShape(chammel3Shape, 2);
for (int i = 0; i < batchNum; ++i)
{
torch::Tensor output_c = torch::from_blob((float *)modelResults[0]+(i*chammel1Shape[1]*chammel1Shape[2]*chammel1Shape[3]), {chammel1Shape[1], chammel1Shape[2], chammel1Shape[3]}, at::dtype(torch::kFloat));
torch::Tensor output_w = torch::from_blob((float *)modelResults[1]+(i*chammel2Shape[1]*chammel2Shape[2]*chammel2Shape[3]), {chammel2Shape[1], chammel2Shape[2], chammel2Shape[3]}, at::dtype(torch::kFloat));
torch::Tensor output_h = torch::from_blob((float *)modelResults[2]+(i*chammel3Shape[1]*chammel3Shape[2]*chammel3Shape[3]), {chammel3Shape[1], chammel3Shape[2], chammel3Shape[3]}, at::dtype(torch::kFloat));
torch::Tensor output_maxpool = torch::max_pool2d(output_c, {3,3}, {1,1}, {1,1});
output_c = output_c.to(torch::kCPU);
output_w = output_w.to(torch::kCPU);
output_h = output_h.to(torch::kCPU);
output_maxpool = output_maxpool.to(torch::kCPU);
std::vector<sObjetDetectionOutput> result;
cv::Mat frame_ = imgs[i];
postprocess(frame_, output_c, output_w, output_h,output_maxpool, metas[i], result);
results.push_back(result);
}
aaronTimer.stop();
vLOG(vINFO) << "VIRObjetDetectionCenterNet--processBatch postprocess time = " << aaronTimer.m_timeMs << "ms.";
#endif
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
std::chrono::duration<double > time_used = std::chrono::duration_cast<std::chrono::duration<double >>(t1-t0);
std::cout<<"image forward use time: "<<std::to_string(time_used.count())<<" seconds"<<std::endl;
vLOG(vINFO) << "carSpecilTypeRec--process time = " << std::to_string(time_used.count()) << "second";
}
int VIRObjetDetectionCenterNet::process(const cv::Mat& image_input, std::vector<sObjetDetectionOutput> &OutputObjectLoc)
{
#ifdef USE_TORCHHALF_DETECT_CENTERNET
cv::Mat ori=image_input;
cv::Mat imgin,floatImg;
Meta meta;
preprocess(image_input, imgin, meta);
Preprocess_centernet(imgin,floatImg);
auto img_tensor = torch::CPU(torch::kFloat32).tensorFromBlob(floatImg.data, {1, 608, 608,3});//将cv::Mat转成tensor,大小为1,608,608,3
img_tensor = img_tensor.permute({0, 3, 1, 2}); //调换顺序变为torch输入的格式 1,3,608,608
auto img_var = torch::autograd::make_variable(img_tensor, false).to(torch::kHalf).to(torch::kCUDA); //不需要梯度
auto output = module->forward({img_var}).toTuple();
torch::Tensor output_c = output->elements()[0].toTensor();
torch::Tensor output_w = output->elements()[1].toTensor();
torch::Tensor output_h = output->elements()[2].toTensor();
torch::Tensor output_maxpool = torch::max_pool2d(output_c, {3,3}, {1,1}, {1,1});
output_c = output_c.to(torch::kFloat32).to(torch::kCPU);
output_w = output_w.to(torch::kFloat32).to(torch::kCPU);
output_h = output_h.to(torch::kFloat32).to(torch::kCPU);
output_maxpool = output_maxpool.to(torch::kFloat32).to(torch::kCPU);
postprocess(ori, output_c, output_w, output_h,output_maxpool, meta, OutputObjectLoc);
#elif defined(USE_TORCH_DETECT_CENTERNET)
cv::Mat ori=image_input;
cv::Mat imgin,floatImg;
Meta meta;
preprocess(image_input, imgin, meta);
Preprocess_centernet(imgin,floatImg);
auto img_tensor = torch::CPU(torch::kFloat32).tensorFromBlob(floatImg.data, {1, 608, 608,3});//将cv::Mat转成tensor,大小为1,608,608,3
img_tensor = img_tensor.permute({0, 3, 1, 2}); //调换顺序变为torch输入的格式 1,3,608,608
auto img_var = torch::autograd::make_variable(img_tensor, false).to(torch::kCUDA); //不需要梯度
c10::intrusive_ptr<c10::ivalue::Tuple> output = module->forward({img_var}).toTuple();
torch::Tensor output_c = output->elements()[0].toTensor();
torch::Tensor output_w = output->elements()[1].toTensor();
torch::Tensor output_h = output->elements()[2].toTensor();
torch::Tensor output_maxpool = torch::max_pool2d(output_c, {3,3}, {1,1}, {1,1});
output_c = output_c.to(torch::kCPU);
output_w = output_w.to(torch::kCPU);
output_h = output_h.to(torch::kCPU);
output_maxpool = output_maxpool.to(torch::kCPU);
postprocess(ori, output_c, output_w, output_h,output_maxpool, meta, OutputObjectLoc);
#else
#endif
return PROCESS_SUCCESS;
}
int VIRObjetDetectionCenterNet::get_pedestrian( std::vector<std::vector<sObjetDetectionOutput> >& vvObject, std::vector<std::vector<cv::Rect>>& vvRect)
{
vvRect.clear();
for( int i = 0; i < vvObject.size(); i++ )
{
std::vector<cv::Rect> vRect;
vRect.clear();
for( int j = 0; j < vvObject[i].size(); j++ )
{
if(vvObject[i][j].objectLabel == ODLPerson )
{
vRect.push_back(vvObject[i][j].objectLocation);
}
}
vvRect.push_back(vRect);
}
return PROCESS_SUCCESS;
}
int VIRObjetDetectionCenterNet::uninit( )
{
#ifndef LIBTORCH_NEW_VERSION
THCCachingAllocator_emptyCache();
#else
// for the future version, not supported in v1.0.0 & v1.0.1
c10::cuda::CUDACachingAllocator::emptyCache();
#endif
return PROCESS_SUCCESS;
}
test.cpp
//
// Created by em on 20-8-27.
//
#include <dirent.h>
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <string>
#include <time.h>
#include <stdio.h>
#include<stdio.h>
#include<unistd.h>
#include "../../source/base/objDetectionCenterNet/include/objectDetectionCenterNet.h"
#include "../../include/common.hpp"
#include <boost/algorithm/string.hpp>
//#define map_test;
//#define common_test;
struct resultWithScore {
int fp;
int tp;
float score;
};
void debug_objdetect_showimg(std::vector<cv::Mat> img, std::vector<std::vector<sObjetDetectionOutput>> rect) {
//cv::destroyAllWindows();
for(int i = 0; i < img.size(); i++)
{
cv::Mat tMat=img[i].clone();
std::string winname = "obj " + std::to_string (i);
cv::namedWindow(winname,cv::WINDOW_NORMAL);
if(rect.size() > 0)
{
for(int j = 0; j < rect[i].size(); j++ )
{
#if 01
if (rect[i][j].objectLabel == 0)
{
//id = "xiaoche";
cv::rectangle(tMat,rect[i][j].objectLocation, cv::Scalar(0, 0, 255), 3, 8, 0);
}
else if (rect[i][j].objectLabel == 1)
{
//id = "dache";
cv::rectangle(tMat,rect[i][j].objectLocation, cv::Scalar(255, 128, 128), 3, 8, 0);
}
else if (rect[i][j].objectLabel == 2)
{
//id = "xingren";
cv::rectangle(tMat,rect[i][j].objectLocation, cv::Scalar(0, 255, 0), 3, 8, 0);
}
else if (rect[i][j].objectLabel == 3)
{
//id = "xingren-qiche";
cv::rectangle(tMat,rect[i][j].objectLocation, cv::Scalar(0, 255, 0), 3, 8, 0);
}
else if (rect[i][j].objectLabel == 4)
{
//id = "feijidongche";
cv::rectangle(tMat,rect[i][j].objectLocation, cv::Scalar(255, 0, 0), 3, 8, 0);
}
else if (rect[i][j].objectLabel == 5)
{
//id = "road_cone";
cv::rectangle(tMat,rect[i][j].objectLocation, cv::Scalar(255, 255, 0), 3, 8, 0);
}
else if (rect[i][j].objectLabel == 6)
{
//id = "parking_corner";
cv::rectangle(tMat,rect[i][j].objectLocation, cv::Scalar(0, 255, 255), 3, 8, 0);
}
#else
if ((rect[i][j].objectLocation.width < 80) || (rect[i][j].objectLocation.height < 80))//开灯开门
{
//continue;
}
if ((rect[i][j].objectLocation.width < 80) || (rect[i][j].objectLocation.height < 80))//路锥(施工)
{
//continue;
}
//if ((ODLSmallCar == rect[i][j].objectLabel) || (ODLBigCar == rect[i][j].objectLabel))//只保存大车和小车
//if ((ODLSmallCar == rect[i][j].objectLabel) || (ODLBigCar == rect[i][j].objectLabel)|| (ODLNonMotorVehicle == rect[i][j].objectLabel))//只保存大车,小车,非机动车
//if ((ODLRoadCone == rect[i][j].objectLabel) || (ODLBigCar == rect[i][j].objectLabel))//只保存大车和路锥
{
cv::Mat m_roi = tMat(rect[i][j].objectLocation);
std::string saveDir = "";
if (ODLRoadCone == rect[i][j].objectLabel)//路锥(施工)
{
saveDir ="/data_1/交接/data/路锥识别/未清洗样本/sample_data_20200224/1/";
}
else
{
saveDir ="/data_1/交接/data/路锥识别/未清洗样本/sample_data_20200224/2/";
}
char a[256];
sprintf(a,"%d",test_num_2);
std::string dst_path = saveDir+a+".jpg";
//std::cout << dst_path<< std::endl;
// cv::namedWindow("img1_resize_1",1);
// cv::imshow("img1_resize_1", img1_resize_1);
// cv::waitKey(0);
cv::imwrite(dst_path, m_roi);
test_num_2++;
}
#endif
}
}
cv::imshow(winname,tMat);
}
cv::waitKey(0);
}
float voc_ap(std::vector<float> &rec, std::vector<float> &prec) {
rec.insert(rec.begin(), 0.0);
rec.push_back(1.0);
prec.insert(prec.begin(), 0.0);
prec.push_back(0.0);
for (int i = prec.size() - 2; i > -1; i--) {
prec[i] = std::max(prec[i], prec[i + 1]);
}
std::vector<int> i_list;
for (int i = 1; i < rec.size(); i++) {
if (rec[i] != rec[i - 1]) {
i_list.push_back(i);
}
}
float ap = 0.0;
for (int i = 0; i < i_list.size(); i++) {
ap += ((rec[i_list[i]] - rec[i_list[i] - 1]) * prec[i_list[i]]);
}
return ap;
}
double IoU(cv::Rect2f src, cv::Rect2f dst) {
float w = std::min(src.x + src.width, dst.x + dst.width) - std::max(src.x, dst.x) + 1;
float h = std::min(src.y + src.height, dst.y + dst.height) - std::max(src.y, dst.y) + 1;
if (w <= 0 || h <= 0)
return 0;
float area = w * h;
return (area) * 1.0 / ((src.width + 1) * (src.height + 1) + (dst.width + 1) * (dst.height + 1) - area);
}
bool cmpare_pair(const resultWithScore a, resultWithScore b) {
return a.score > b.score;//自定义的比较函数
}
int getMAP(std::vector<std::string> &class_names, std::string >_path, std::string &pre_path, std::string output_result, double &MINOVERLAP) {
// if (boost::filesystem::is_empty(gt_path) || boost::filesystem::is_empty(pre_path)) {
// std::cout << "Error: No ground-truth files found!" << std::endl;
// return 0;
// }
// map with counter per class
float error_=0;
std::vector<std::pair<std::string, int>> gt_counter_per_class;
for (int i = 0; i < class_names.size(); i++) {
std::pair<std::string, int> gt_counter;
std::vector<std::string> gt_files;
GetFileNames(gt_path, gt_files);
// 获取每个类别的gt数量。
int gt_num = 0;
for (auto gt_file : gt_files) {
std::ifstream gt(gt_file);
std::string gt_line;
while (std::getline(gt, gt_line)) {
std::vector<std::string> gt_list;
boost::split(gt_list, gt_line, boost::is_any_of(" "), boost::token_compress_on);
if (gt_list[0] == class_names[i]) {
gt_num++;
}
}
}
if (gt_num==0){
error_++;
std::cout<<"gt=0"<<std::endl;
}
gt_counter.first = class_names[i];
gt_counter.second = gt_num;
gt_counter_per_class.push_back(gt_counter);
}
std::ofstream in;
in.open(output_result, std::ios::app);
float sum_AP = 0;
for (int i = 0; i < gt_counter_per_class.size(); i++) {
std::vector<resultWithScore> vResultWithScore;
std::vector<std::string> pre_files;
GetFileNames(pre_path, pre_files);
for (auto pre_file : pre_files) {
// get the predicted of the file.
std::ifstream pre(pre_file);
std::string pre_line;
std::vector<int> used;
while (std::getline(pre, pre_line)) {
resultWithScore result;
std::vector<std::string> pre_list;
boost::split(pre_list, pre_line, boost::is_any_of(" "), boost::token_compress_on);
if (pre_list[0] != gt_counter_per_class[i].first) { // get the box of the gt_counter_per_class[i] class
continue;
}
float pre_x = atof(pre_list[2].c_str());
float pre_y = atof(pre_list[3].c_str());
float pre_w = atof(pre_list[4].c_str()) - atof(pre_list[2].c_str());
float pre_h = atof(pre_list[5].c_str()) - atof(pre_list[3].c_str());
float score = atof(pre_list[1].c_str());
result.score = score;
cv::Rect2f rect = cv::Rect2f(pre_x, pre_y, pre_w, pre_h);
// get the gt
std::vector<std::string> file_name_split;
boost::split(file_name_split, pre_file, boost::is_any_of("/"), boost::token_compress_on);
std::string file_name = file_name_split[file_name_split.size() - 1];
std::ifstream gt(gt_path + "/" + file_name);
std::string line;
double iou_max = -1;
int line_index = -1;
int max_iou_index = -1;
while (std::getline(gt, line)) {
line_index += 1;
std::vector<std::string> gt_list;
boost::split(gt_list, line, boost::is_any_of(" "), boost::token_compress_on);
if (gt_list[0] != gt_counter_per_class[i].first) {
continue;
}
float gt_x = atof(gt_list[1].c_str());
float gt_y = atof(gt_list[2].c_str());
float gt_w = atof(gt_list[3].c_str()) - atof(gt_list[1].c_str());
float gt_h = atof(gt_list[4].c_str()) - atof(gt_list[2].c_str());
cv::Rect2f gt_rect = cv::Rect2f(gt_x, gt_y, gt_w, gt_h);
double iou = IoU(gt_rect, rect);
if (iou > iou_max) {
iou_max = iou;
max_iou_index = line_index;
}
}
// std::cout << "max iou is: " << iou_max << std::endl;
bool used_flag = false;
if (iou_max >= MINOVERLAP) {
for (int u = 0; u < used.size(); u++) {
if (max_iou_index == used[u]) { //the gt is used;
used_flag = true;
}
}
if (!used_flag) {
result.tp = 1;
result.fp = 0;
used.push_back(max_iou_index);
} else {
result.tp = 0;
result.fp = 1;
}
} else {
result.tp = 0;
result.fp = 1;
}
vResultWithScore.push_back(result);
}
}
// 按检测score从大到小排序
std::sort(vResultWithScore.begin(), vResultWithScore.end(), cmpare_pair);
int cumsum = 0;
int val;
std::vector<float> rec, prec;
for (int j = 0; j < vResultWithScore.size(); j++) {
val = vResultWithScore[j].fp;
vResultWithScore[j].fp += cumsum;
cumsum += val;
}
cumsum = 0;
for (int j = 0; j < vResultWithScore.size(); j++) {
val = vResultWithScore[j].tp;
vResultWithScore[j].tp += cumsum;
cumsum += val;
if (!gt_counter_per_class.empty()) {
float rec_j = (float) (vResultWithScore[j].tp * 1.0 / gt_counter_per_class[i].second);
rec.push_back(rec_j);
float prec_j = (float) (vResultWithScore[j].tp * 1.0 /
(vResultWithScore[j].fp + vResultWithScore[j].tp));
prec.push_back(prec_j);
} else {
std::cout << "There is no gt." << std::endl;
}
}
float ap = voc_ap(rec, prec);
sum_AP += ap;
std::cout << "AP of " << gt_counter_per_class[i].first << " is: " << std::to_string(ap) << std::endl;
in << "AP of " << gt_counter_per_class[i].first << " is: " << std::to_string(ap) << "\n";
}
float mAP = sum_AP / (gt_counter_per_class.size()-error_);
std::cout << "mAP is: " << mAP << std::endl;
in << "mAP is: " << mAP << "\n";
in << "=================" << "\n";
in.close();
}
void draw(std::string& name,
std::string& pre_path,
std::string& gt_path,
std::string& res_path,
std::vector<sObjetDetectionOutput>& res) {
int npos = name.find_last_of('.');
std::string out_txt = name.substr(0, npos);
int mpos = name.find_last_of('/');
out_txt = out_txt.substr(mpos + 1);
cv::Mat img = cv::imread(name, 1);
cv::Mat new_img = img.clone();
std::string txt_name_new = out_txt + ".txt";
std::string txt_path = pre_path + txt_name_new;
std::string img_name_new = out_txt + ".jpg";
std::string txtName = gt_path + out_txt + ".txt";
if(access (name.c_str() , 0) || access ( txtName.c_str() , 0 ))
return;
FILE *fp = NULL;
fp = fopen(txt_path.data(), "w");
sObjetDetectionOutput sObjetDetectionOutput_;
sObjetDetectionOutput_.objectConfidence = 0.8;
sObjetDetectionOutput_.objectLocation = cv::Rect(100, 100, 1000, 1000);
sObjetDetectionOutput_.objectLabel = ODLSmallCar;
// res.push_back(sObjetDetectionOutput_);
for (int i = 0; i < res.size(); ++i) {
if (res[i].objectLabel == 0) {
cv::Mat rectImg = new_img(res[i].objectLocation);
cv::rectangle(new_img, res[i].objectLocation, cv::Scalar(255, 204, 0), 3, 8, 0);
cv::putText(new_img, "SmallCar",
cv::Point(res[i].objectLocation.x, res[i].objectLocation.y), 3,
1.2, cv::Scalar(255, 0, 255), 2);
fprintf(fp, "%s %f %d %d %d %d\n", "0", res[i].objectConfidence, res[i].objectLocation.x,
res[i].objectLocation.y,
res[i].objectLocation.x + res[i].objectLocation.width,
res[i].objectLocation.y + res[i].objectLocation.height);
}
if (res[i].objectLabel == 1) {
cv::rectangle(new_img, res[i].objectLocation, cv::Scalar(255, 204, 0), 3, 8, 0);
cv::putText(new_img, "BigCar",
cv::Point(res[i].objectLocation.x, res[i].objectLocation.y), 3,
1.2, cv::Scalar(255, 0, 255), 2);
fprintf(fp, "%s %f %d %d %d %d\n", "1", res[i].objectConfidence, res[i].objectLocation.x,
res[i].objectLocation.y,
res[i].objectLocation.x + res[i].objectLocation.width,
res[i].objectLocation.y + res[i].objectLocation.height);
}
if (res[i].objectLabel == 2) {
cv::rectangle(new_img, res[i].objectLocation, cv::Scalar(255, 204, 0), 3, 8, 0);
cv::putText(new_img, "Person",
cv::Point(res[i].objectLocation.x, res[i].objectLocation.y), 3,
1.2, cv::Scalar(255, 0, 255), 2);
fprintf(fp, "%s %f %d %d %d %d\n", "2", res[i].objectConfidence, res[i].objectLocation.x,
res[i].objectLocation.y,
res[i].objectLocation.x + res[i].objectLocation.width,
res[i].objectLocation.y + res[i].objectLocation.height);
}
if (res[i].objectLabel == 3) {
cv::rectangle(new_img, res[i].objectLocation, cv::Scalar(255, 204, 0), 3, 8, 0);
cv::putText(new_img, "Cyclist",
cv::Point(res[i].objectLocation.x, res[i].objectLocation.y), 3,
1.2, cv::Scalar(255, 0, 255), 2);
fprintf(fp, "%s %f %d %d %d %d\n", "3", res[i].objectConfidence, res[i].objectLocation.x,
res[i].objectLocation.y,
res[i].objectLocation.x + res[i].objectLocation.width,
res[i].objectLocation.y + res[i].objectLocation.height);
}
if (res[i].objectLabel == 4) {
cv::rectangle(new_img, res[i].objectLocation, cv::Scalar(255, 204, 0), 3, 8, 0);
cv::putText(new_img, "NonMotorVehicle",
cv::Point(res[i].objectLocation.x, res[i].objectLocation.y), 3,
1.2, cv::Scalar(255, 0, 255), 2);
fprintf(fp, "%s %f %d %d %d %d\n", "4", res[i].objectConfidence, res[i].objectLocation.x,
res[i].objectLocation.y,
res[i].objectLocation.x + res[i].objectLocation.width,
res[i].objectLocation.y + res[i].objectLocation.height);
}
if (res[i].objectLabel == 5) {
cv::rectangle(new_img, res[i].objectLocation, cv::Scalar(255, 204, 0), 3, 8, 0);
cv::putText(new_img, "RoadCone",
cv::Point(res[i].objectLocation.x, res[i].objectLocation.y), 3,
1.2, cv::Scalar(255, 0, 255), 2);
fprintf(fp, "%s %f %d %d %d %d\n", "4", res[i].objectConfidence, res[i].objectLocation.x,
res[i].objectLocation.y,
res[i].objectLocation.x + res[i].objectLocation.width,
res[i].objectLocation.y + res[i].objectLocation.height);
}
if (res[i].objectLabel == 6) {
cv::rectangle(new_img, res[i].objectLocation, cv::Scalar(255, 204, 0), 3, 8, 0);
cv::putText(new_img, "BParkingCorner",
cv::Point(res[i].objectLocation.x, res[i].objectLocation.y), 3,
1.2, cv::Scalar(255, 0, 255), 2);
fprintf(fp, "%s %f %d %d %d %d\n", "4", res[i].objectConfidence, res[i].objectLocation.x,
res[i].objectLocation.y,
res[i].objectLocation.x + res[i].objectLocation.width,
res[i].objectLocation.y + res[i].objectLocation.height);
}
}
fclose(fp);
// cv::imshow("www",new_img);
// cv::waitKey(0);
cv::imwrite(res_path + img_name_new, new_img);
}
#ifdef common_test
int main() {
const std::string model_file = "/data_2/project/weizhang_code/VIR_Vedio/VideoModelLib/model//";
std::string data_file = "/data_2/data/20201014/寒武纪给的数据/目标检测/img";
int flag = VIRObjetDetection::ins().init(model_file, 0);
std::vector<std::string> img_names;
GetFileNames(data_file, img_names);
for (auto name : img_names) {
cv::Mat img = cv::imread(name, 1);
std::vector<sObjetDetectionOutput> OutputObjectLoc;
VIRObjetDetection::ins().process(img, OutputObjectLoc);
for (int j = 0; j < OutputObjectLoc.size(); j++) {
cv::rectangle(img, OutputObjectLoc[j].objectLocation, cv::Scalar(0, 255, 0), 2);
}
cv::namedWindow("show", CV_WINDOW_NORMAL);
cv::imshow("show", img);
cv::waitKey();
}
}
#endif
int map_test_batch() {
const std::string model_file = "/data1/Working/project/weifa-all-project/video-3.0/VideoModelLib/model_gpu";
std::string data_file = "/data1/Working/project/weifa-all-project/video-3.0/use-tensorRT/data/detect_centernet/old/images/";
std::string save_path = "/data1/Working/project/weifa-all-project/video-3.0/use-tensorRT/data/detect_centernet/objdet_centernet/";
std::string output_file = save_path + "/objdet_centernet_result.txt";
std::string gt_path = "/data1/Working/project/weifa-all-project/video-3.0/use-tensorRT/data/detect_centernet/old/ground-truth/";
if (access(save_path.data(), 0) == -1) {
mkdir(save_path.data(), 0777);
}
std::string pre_path = save_path + "/txt/";
if (access(pre_path.data(), 0) == -1) {
mkdir(pre_path.data(), 0777);
}
std::string res_path = save_path + "/" + "01" + "/";
if (access(res_path.data(), 0) == -1) {
mkdir(res_path.data(), 0777);
}
std::vector<std::string> class_names;
for (int i = 0; i < 7; i++) {
class_names.push_back(std::to_string(i));
}
eVIRPlaceNum a = eVIRPlaceNum::PlaceBaoding;
int flag = VIRObjetDetectionCenterNet::ins().init(model_file, 0);
std::vector<std::string> img_names;
GetFileNames(data_file, img_names);
std::ofstream in;
in.open(output_file, std::ios::app);
// for multi-batch
int img_num = img_names.size();
const int batch_num = 4;
std::vector<cv::Mat> imgs(batch_num);
int batch_group = img_num / batch_num;
int res_num = img_num % batch_num;
double total_time_use=0.0;
for (int n = 0; n < batch_group; n++)
{
std::vector<std::string> names;
for (int j = 0; j < batch_num; j++)
{
int img_idx = n * batch_num + j;
std::string img_name = img_names[img_idx];
names.push_back(img_name);
imgs[j] = cv::imread(img_name);
}
std::vector<std::vector<sObjetDetectionOutput>> results;
std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
VIRObjetDetectionCenterNet::ins().processBatch(imgs, batch_num, results);
//debug show
// debug_objdetect_showimg(imgs,results);//暂时不使用,保存结果
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
std::chrono::duration<double > time_used = std::chrono::duration_cast<std::chrono::duration<double >>(t1-t0);
if(n!=0)
{
total_time_use+=time_used.count();
}
std::cout << "one batch processed" << std::endl;
for(int i = 0; i < batch_num; ++i){
std::vector<sObjetDetectionOutput>& res = results[i];
draw(names[i], pre_path, gt_path, res_path, res);
}
}
if (res_num != 0)
{
for (int n = 0; n < res_num; n++)
{
int img_idx = batch_group * batch_num + n;
std::string img_name = img_names[img_idx];
imgs[n] = cv::imread(img_name);
}
// surplus images
for (int n = res_num; n < batch_num; n++)
{
imgs[n] = imgs[0];
}
std::vector<std::vector<sObjetDetectionOutput>> results;
std::chrono::steady_clock::time_point t00 = std::chrono::steady_clock::now();
VIRObjetDetectionCenterNet::ins().processBatch(imgs, batch_num, results);
std::chrono::steady_clock::time_point t11 = std::chrono::steady_clock::now();
std::chrono::duration<double > time_used_ = std::chrono::duration_cast<std::chrono::duration<double >>(t11-t00);
total_time_use+=time_used_.count();
std::cout << "one batch processed" << std::endl;
}
size_t total_num = img_names.size();
double meanTime = total_time_use / (total_num-batch_num);
std::cout << "totalNum: " << total_num << std::endl;
std::cout << "totalTime: " << total_time_use << std::endl;
std::cout << "meanTime: " << meanTime << std::endl;
std::cout <<"================="<< std::endl;
in << "totalNum: " << total_num << std::endl;
in << "totalTime: " << total_time_use << std::endl;
in << "meanTime: " << meanTime << "\n";
in << "=================" << "\n";
in.close();
/// map
double iou = 0.2;
getMAP(class_names, gt_path, pre_path, output_file, iou);
}
int map_test_single() {
const std::string model_file = "/data1/Working/project/weifa-all-project/video-3.0/VideoModelLib/model_gpu";
std::string data_file = "/data1/Working/project/weifa-all-project/video-3.0/use-tensorRT/data/detect_centernet/old/images/";
std::string save_path = "/data1/Working/project/weifa-all-project/video-3.0/use-tensorRT/data/detect_centernet/objdet_centernet/";
std::string output_file = save_path + "/objdet_centernet_result.txt";
std::string gt_path = "/data1/Working/project/weifa-all-project/video-3.0/use-tensorRT/data/detect_centernet/old/ground-truth/";
if (access(save_path.data(), 0) == -1) {
mkdir(save_path.data(), 0777);
}
std::string pre_path = save_path + "/txt/";
if (access(pre_path.data(), 0) == -1) {
mkdir(pre_path.data(), 0777);
}
std::string res_path = save_path + "/" + "01" + "/";
if (access(res_path.data(), 0) == -1) {
mkdir(res_path.data(), 0777);
}
std::vector<std::string> class_names;
for (int i = 0; i < 7; i++) {
class_names.push_back(std::to_string(i));
}
eVIRPlaceNum a = eVIRPlaceNum::PlaceBaoding;
std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
int flag = VIRObjetDetectionCenterNet::ins().init(model_file, 0);
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
std::chrono::duration<double > time_used = std::chrono::duration_cast<std::chrono::duration<double >>(t1-t0);
std::cout<<"use time init: "<<time_used.count()<<std::endl;
std::vector<std::string> img_names;
GetFileNames(data_file, img_names);
std::ofstream in;
in.open(output_file, std::ios::app);
int img_num = img_names.size();
double total_time_use=0.0;
for(int i=0;i<img_num;i++)
{
std::string img_name = img_names[i];
cv::Mat srcimage = cv::imread(img_name);
std::vector<sObjetDetectionOutput> results;
std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
VIRObjetDetectionCenterNet::ins().process(srcimage,results);
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
std::chrono::duration<double > time_used = std::chrono::duration_cast<std::chrono::duration<double >>(t1-t0);
if(i!=0)
{
total_time_use+=time_used.count();
}
draw(img_name, pre_path, gt_path, res_path, results);
}
size_t total_num = img_names.size();
double meanTime = total_time_use / (total_num-1);
std::cout << "totalNum: " << total_num << std::endl;
std::cout << "totalTime: " << total_time_use << std::endl;
std::cout << "meanTime: " << meanTime << std::endl;
std::cout <<"================="<< std::endl;
in << "totalNum: " << total_num << std::endl;
in << "totalTime: " << total_time_use << std::endl;
in << "meanTime: " << meanTime << "\n";
in << "=================" << "\n";
in.close();
/// map
double iou = 0.2;
getMAP(class_names, gt_path, pre_path, output_file, iou);
}
int main()
{
std::cout<<"begin"<<std::endl;
// map_test_batch();
map_test_single();
return 0;
}