赞
踩
这篇主要内容就是yolo目标检测网络和Unet语义分割网络的联合C++部署。用到yolo主要是为了节省Unet部分的计算资源和分割精度,因为检测框会将非目标物删除,这样分割网络只需分割目标框内的二维信息即可。
开始吧,
计划已经制定,那就分四步走:
这个网上有很多优秀的教程,可以借鉴参考,此处不赘述。
我使用的是yolov5训练的,yolov7也是大致相同的部署方式。yolov7和yolov5差距并不大,且yolov5部署后的速度更快一些,精度的话yolov7更优,看自己的需求了。
首先,将训练好的yolo权重文件(也就是.pt文件)转成onnx,这一步官方代码的export.py可实现,其他的优化、剪枝等操作本篇不做介绍,这些网上也有很多教程,感兴趣的可以多多学习,在网络模型部署时(尤其是终端部署)会用到。
好了,这时候我们有了一个yolo的onnx文件,可以放到Netron查看输入输出的维度,看看结构也有助于对神经网络的理解。这时候我们就可以开始创建一个新的C++项目,新建一个头文件和源文件。这里需要用到Opencv里面的图片读写和Dnn模块(支持对神经网络的调用),我使用的时opencv455(也可以使用其他更高的版本)。
头文件代码如下:
- #include<iostream>
- #include<opencv2/opencv.hpp>
-
- struct Output {
- int id; //结果类别id
- float confidence; //结果置信度
- cv::Rect box; //矩形框
- };
-
- class Yolo {
- public:
- Yolo() {
- }
- ~Yolo() {}
- bool readModel(cv::dnn::Net& net, std::string& netPath, bool isCuda);
- bool Detect(cv::Mat& SrcImg, cv::dnn::Net& net, std::vector<Output>& output);
- void drawPred(cv::Mat& img, std::vector<Output> result, int i);
-
- private:
-
- float sigmoid_x(float x)
- {
- return static_cast<float>(1.f / (1.f + exp(-x)));
- }
- const float netAnchors[3][6] = { { 10, 13, 16, 30, 33, 23 }, { 30, 61, 62, 45, 59, 119 }, { 116, 90, 156, 198, 373, 326 } };//yolo anchors
-
- const int netWidth = 640; //ONNX图片输入宽度
- const int netHeight = 640; //ONNX图片输入高度
- const int strideSize = 3; //stride size
-
- const float netStride[4] = { 8, 16.0,32,64 };
-
- float boxThreshold = 0.75;
- float classThreshold = 0.65;
- float nmsThreshold = 0.55;
- float nmsScoreThreshold = boxThreshold * classThreshold;
-
- std::vector<std::string> className = { "yolo类别"};
- };
其中的anchor在训练的时候,网络会给到你,将你的anchor替换即可。
源文件如下:
- #include "头文件.h"
- #include <iostream>
- #include<opencv2//opencv.hpp>
- #include<math.h>
- #include <opencv2/dnn.hpp>
- #include <fstream>
- #define USE_CUDA false //可以使用cuda加速
-
- using namespace std;
- using namespace cv;
- using namespace dnn;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。