Centernet半精度批处理详解-c++

.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 &gt_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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值