Opencv C++部署YOLOv3v4

一.推理C++源码

0.源码链接

https://learnopencv.com/deep-learning-based-object-detection-using-yolov3-with-opencv-python-c/

1.初始化参数

//初始化参数
float confThreshold = 0.5; // 置信度阈值
float nmsThreshold = 0.4;  // 非极大值抑制阈值
int inpWidth = 416;        //网络输入尺寸宽度
int inpHeight = 416;       //网络输入尺寸高度

2.加载模型与类别标签

//加载类别名称
string classesFile = "coco.names";
ifstream ifs(classesFile.c_str());
string line;
while (getline(ifs, line)) classes.push_back(line);

//给模型喂养配置文件与权重文件
String modelConfiguration = "yolov3.cfg";
String modelWeights = "yolov3.weights";

//加载网络模型
Net net = readNetFromDarknet(modelConfiguration, modelWeights);
net.setPreferableBackend(DNN_BACKEND_OPENCV);
net.setPreferableTarget(DNN_TARGET_CPU);

3.读取输入图片

outputFile = "yolo_out_cpp.avi";
if (parser.has("image"))
    {
        //打开图片文件
        str = parser.get<String>("image");
        ifstream ifile(str);
        if (!ifile) throw("error");
        cap.open(str);
        str.replace(str.end()-4, str.end(), "_yolo_out_cpp.jpg");
        outputFile = str;
    }
    else if (parser.has("video"))
    {
        //打开视频文件
        str = parser.get<String>("video");
        ifstream ifile(str);
        if (!ifile) throw("error");
        cap.open(str);
        str.replace(str.end()-4, str.end(), "_yolo_out_cpp.avi");
        outputFile = str;
    }
    //打开网络摄像机
    else cap.open(parser.get<int>("device"));

    catch(...) {
        cout << "Could not open the input image/video stream" << endl;
        return 0;
    }
    
    //初始化视频存储器,存储输出视频
    if (!parser.has("image")) {
        video.open(outputFile, VideoWriter::fourcc('M','J','P','G'), 28, Size(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT)));
    }

4.处理每一帧

//处理每一帧
while (waitKey(1) < 0)
{
    //从视频获取图像
    cap >> frame;

    // Stop the program if reached end of video
    if (frame.empty()) {
        cout << "Done processing !!!" << endl;
        cout << "Output file is stored as " << outputFile << endl;
        waitKey(3000);
        break;
    }
    //从原图像创建一个4D的blob
    blobFromImage(frame, blob, 1/255.0, cv::Size(inpWidth, inpHeight), Scalar(0,0,0), true, false);
        
    //为网络设置输入
    net.setInput(blob);
    
    //运行前向推理的过程,得到输出层的输出
    vector<Mat> outs;
    net.forward(outs, getOutputsNames(net));
        
    //移除低置信度的输出框
    postprocess(frame, outs);
        
    //展示效率信息。函数getPerfProfile返回每一层的推理时间
    vector<double> layersTimes;
    double freq = getTickFrequency() / 1000;
    double t = net.getPerfProfile(layersTimes) / freq;
    string label = format("Inference time for a frame : %.2f ms", t);
    putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255));
        
    //保存带有检测框的一帧图像
    Mat detectedFrame;
    frame.convertTo(detectedFrame, CV_8U);
    if (parser.has("image")) imwrite(outputFile, detectedFrame);
    else video.write(detectedFrame);
        
    imshow(kWinName, frame);        
}

二.forward函数

//运行前向推理的过程,得到输出层的输出
vector<Mat> outs;
net.forward(outs, getOutputsNames(net));

函数getOutputsNames()的输出为网络中的三个不同尺度的输出层名称(分别预测大、中、小物体)。

net.forward()函数根据输出层名称得到输出结果,输出内容outs为一个Mat数组,每个Mat为5+nc维度向量组(n行5+nc列矩阵,nc为类别的数量)。outs数组的每一个元素都是一个5+nc维向量(总共有三个元素,均为Mat),该5+nc维向量是每一个输出层的输出,形式为blob二进制对象。

YOLOv4网络的输出为矩形框,每个矩形框由一个向量表示,所有矩形框组成一个向量组。每个向量的长度为类别数 + 5个参数,这五个参数的前四个分别是矩形框在图像上的位置center_x, center_y, width, height(均为比例,范围在0-1之间),第五个参数是该矩形框可能包含物体的置信度。从向量的第六个参数开始,分别表示矩形框中物体对应每个类别的置信度

参考链接:https://www.freesion.com/article/72531365556/

三.net.setPreferableBackend与net.setPreferableTarget

1.setPreferableBackend()函数形参

DNN_BACKEND_INFERENCE_ENGINE;
DNN_BACKEND_OPENCV;
DNN_BACKEND_HALIDE;
DNN_BACKEND_CUDA;
DNN_BACKEND_DEFAULT;

其中,如果OpenCV是用英特尔的Inference Engine library编译的话,那么DNN_BACKEND_DEFAULT为DNN_BACKEND_INFERENCE_ENGINE,否则为DNN_BACKEND_OPENCV。

2.setPreferableTarget()函数形参

List of supported combinations backend / target:
|                        | DNN_BACKEND_OPENCV | DNN_BACKEND_INFERENCE_ENGINE | DNN_BACKEND_HALIDE |  DNN_BACKEND_CUDA |
|------------------------|--------------------|------------------------------|--------------------|-------------------|
| DNN_TARGET_CPU         |                  + |                            + |                  + |                   |
| DNN_TARGET_OPENCL      |                  + |                            + |                  + |                   |
| DNN_TARGET_OPENCL_FP16 |                  + |                            + |                    |                   |
| DNN_TARGET_MYRIAD      |                    |                            + |                    |                   |
| DNN_TARGET_FPGA        |                    |                            + |                    |                   |
| DNN_TARGET_CUDA        |                    |                              |                    |                 + |
| DNN_TARGET_CUDA_FP16   |                    |                              |                    |                 + |

参考链接:https://blog.csdn.net/weixin_43996161/article/details/113994433

猜你喜欢

转载自blog.csdn.net/m0_46749624/article/details/122401474