win10+vs2017+opencv4.5.3+yolov5-5.0

注意此处一定要使用的OpenCV版本是4.5版本以上,否则在后面读取onnx模型会失败

这里使用opencv的dnn模块读取onnx模型进行目标检测,目前已经部署成功了

也就是说明不需要安装libtorch安装包就能直接读取onnx模型,不需要读取pt模型

https://blog.csdn.net/dongjuexk/article/details/124243178
opencv dnn模块实现Yolov5_6.1

1,安装OpenCV4.5.3配置环境

下载OpenCV版本如下
https://sourceforge.net/projects/opencvlibrary/files/4.5.3/opencv-4.5.3-vc14_vc15.exe/download

下载直接解压到当前文件即可

属性表的配置如下:
这里是debug 64位的
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2,进行模型加载

https://blog.csdn.net/nihate/article/details/112731327#comments_14884604
用opencv的dnn模块做yolov5目标检测(重要必看,运行成功)

下方的github文件是使用OpenCV部署YOLOX,支持YOLOX-S、YOLOX-M、YOLOX-L、YOLOX-X、YOLOX-Darknet53五种结构
而本人之前是使用yolov5_s结构的所以应该是可以的

https://github.com/hpc203/yolox-opencv-dnn

下载上方的github文件
在这里插入图片描述

只需要main.cpp coco.names images即可

使用OpenCV部署YOLOX,支持YOLOX-S、YOLOX-M、YOLOX-L、YOLOX-X、YOLOX-Darknet53五种结构,包含C++和Python两种版本的程序
onnx文件在百度云盘,下载链接:https://pan.baidu.com/s/11UAVSPWbDKY_LmmoHlUQXw 提取码:147w
下载完成后,把文件放在代码文件所在目录里,就可以运行程序了。如果出现读取onnx文件失败, 那很有可能是你的opencv版本低了,需要升级到4.5以上的

在本地新建空项目,直接把main.cpp文件导入,配置好OpenCV环境,然后读取其给的yolox_s.onnx模型

目前已经成功读取onnx读取测试成功了

关键就是如何获得onnx的模型文件,即如何将pt模型转换成onnx模型,用于此处的导入

3,如何导出自己的onnx模型

https://blog.csdn.net/qq_34124780/article/details/114666312
c++下使用opencv部署yolov5模型(一)(必看)
https://blog.csdn.net/qq_34124780/article/details/115363855
2021.04.15更新 c++下使用opencv部署yolov5模型 (二)

https://blog.csdn.net/qq_34124780/article/details/116464727
2021.09.02更新说明 c++下使用opencv部署yolov5模型 (三)
在这里插入图片描述

上方三个博客是必看的,最后本人成功将其导出onnx并进行部署了

参考上方文件后,将

发现使用yolov5的export直接导出时,出现问题,无法导出onnx(本地环境问题直接使用了谷歌实验室导出成功)
https://github.com/ultralytics/yolov5

在本地导出yolov5的onnx模型失败

尝试在谷歌实验室导出看看效果
在这里插入图片描述

https://blog.csdn.net/qq_45057749/article/details/115016683
yolov5模型转换(一) pt文件转onnx

注意这里的是在YOLOV5的releases的5.0的源代码版本下导出的

并且在谷歌实验室及云服务器导出onnx成功了,本地环境导出onnx失败,可能是被污染了环境

所以这次在本地搭建界面,然后去云服务器pyinstaller为exe再转到本地运行看看效果

注意直接导出的onnx是1个输入,3个输出,在前面的C++程序代码中无法调用,需要更改导出的代码

(1)下载YOLOv5的5.0版本的代码

https://github.com/ultralytics/yolov5/releases
在这里插入图片描述

此版本代码也是本地进行模型训练的代码,注意不是主页的代码,而是历史5.0的代码
https://github.com/ultralytics/yolov5/issues/251

注意要先安装相关环境如下:

git clone https://github.com/ultralytics/yolov5cd yolov5
pip install -r requirements.txt
pip install -U coremltools onnx scikit-learn==0.19.2  # export requirements

python models/export.py --weights weights/yolov5s.pt --img 640 --batch 1
  # export at 640x640 with batch size 1

在这里插入图片描述

(2)在谷歌实验室更改两部分代码

参考https://blog.csdn.net/qq_34124780/article/details/115363855
2021.04.15更新 c++下使用opencv部署yolov5模型 (二)
要更改两部分代码

1.一个是focus切片代码
2.一个是将三个输出变成一个输出代码(注意改完后,要再次进行训练的时候需要改回来,可以将一个YOLOV5-5.0代码作为专门用于将pt文件转onnx的工具,这样之间就不会相互干扰了)

(1-1)在model文件下的common.py更改focus模块为下(直接参考上面链接即可,下面的模块选择第一个就行,另一个注释掉即可)

class Focus(nn.Module):
    # Focus wh information into c-space
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super(Focus, self).__init__()
        #self.contract=Conv(c1 * 4, c2, k, s, p, g, act)
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
    def forward(self, x):  # x(b,c,w,h) -> y(b,4c,w/2,h/2)
        #return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))
        N, C, H, W = x.size()  # assert (H / s == 0) and (W / s == 0), 'Indivisible gain'
        s = 2
        x = x.view(N, C, H // s, s, W // s, s)  # x(1,64,40,2,40,2)
        x = x.permute(0, 3, 5, 1, 2, 4).contiguous()  # x(1,2,2,64,40,40)
        y=x.view(N, C * s * s, H // s, W // s)  # x(1,256,40,40)
        return self.conv(y)
 
################################################################
##############       另外一种比较简单的方法         ##############
################################################################
class Focus(nn.Module):
    # Focus wh information into c-space
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super().__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
 
    def forward(self, x):  # x(b,c,w,h) -> y(b,4c,w/2,h/2)
        contract = Contract(gain=2)
        #return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))
        return self.conv(contract(x))

(1-2),最后发现只要修改下yolo.py中的detect模块就可以达到修改网络输出格式的效果。先看下/models/yolo.py里面的detect模块

在这里插入图片描述
在这里插入图片描述

(2)导出onnx,在输入如下

!python models/export.py --weights weights/yolov5s.pt --img 640 --batch 1

在这里插入图片描述

导出后生成的yolov5s.onnx会在yolov5s.pt权重文件所在文件夹下生成的

然后下载,最后就是和C++联合使用了

(3)打包导出工具

专门用来导出的文件已经更改完成了,这样就不用一值更改其它文件了
在这里插入图片描述

4,C++加载onnx模型识别图片

这里直接使用的是OpenCV4.5.3的代码
参考https://blog.csdn.net/qq_34124780/article/details/116464727
2021.09.02更新说明 c++下使用opencv部署yolov5模型 (三)

上面的博客一定要读

本人已经在本地搭建好了环境如下

本人将此运行成功的环境及模型放到百度云上,
在这里插入图片描述

一共三个代码文件如下

Yolo.h

//yolo.h
#pragma once
#include<iostream>
#include<math.h>
#include<opencv2/opencv.hpp>

//结果结构体
struct Output {
	int id;//结果类别id
	float confidence;//结果置信度
	cv::Rect box;//矩形框
};

class Yolo {

	//参数为私有参数,当然也可以是设置成公开或者保护。
private:
	//计算归一化函数
	float Sigmoid(float x) {
		return static_cast<float>(1.f / (1.f + exp(-x)));
	}
	//anchors
	const float netAnchors[3][6] = { { 10.0, 13.0, 16.0, 30.0, 33.0, 23.0 },{ 30.0, 61.0, 62.0, 45.0, 59.0, 119.0 },{ 116.0, 90.0, 156.0, 198.0, 373.0, 326.0 } };
	//stride
	const float netStride[3] = { 8.0, 16.0, 32.0 };
	const int netWidth = 640; //网络模型输入大小
	const int netHeight = 640;
	float nmsThreshold = 0.45;
	float boxThreshold = 0.35;
	float classThreshold = 0.35;
	//类名
	std::vector<std::string> className = { "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
		"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
		"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
		"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
		"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
		"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
		"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
		"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
		"hair drier", "toothbrush" };

public:
	//在yolo.h中的 Yolo类中添加成员函数readModel:
	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, std::vector<cv::Scalar> color);

	Yolo() {
	}
	~Yolo() {}
};

Yolo.cpp

//yolo.cpp中实现readModel函数
//在yolo.cpp中使用命名空间
#include "yolo.h"
using namespace std;
using namespace cv;
using namespace dnn;

bool Yolo::readModel(Net &net, string &netPath, bool isCuda = false) {
	try {
		net = readNetFromONNX(netPath);
	}
	catch (const std::exception&) {
		return false;
	}
	//cuda
	if (isCuda) {
		net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
		net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
	}
	//cpu
	else {
		net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
		net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
	}
	return true;
}

bool Yolo::Detect(Mat &SrcImg, Net &net, vector<Output> &output) {
	Mat blob;
	blobFromImage(SrcImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), Scalar(0, 0, 0), true, false);
	net.setInput(blob);
	vector<Mat> netOutputImg;
	net.forward(netOutputImg, net.getUnconnectedOutLayersNames());
	//接上面
	vector<int> classIds;//结果id数组
	vector<float> confidences;//结果每个id对应置信度数组
	vector<Rect> boxes;//每个id矩形框
	float ratio_h = (float)SrcImg.rows / netHeight;
	float ratio_w = (float)SrcImg.cols / netWidth;
	int net_width = className.size() + 5;  //输出的网络宽度是类别数+5
	float* pdata = (float*)netOutputImg[0].data;
	for (int stride = 0; stride < 3; stride++) {    //stride
		int grid_x = (int)(netWidth / netStride[stride]);
		int grid_y = (int)(netHeight / netStride[stride]);
		for (int anchor = 0; anchor < 3; anchor++) { //anchors
			const float anchor_w = netAnchors[stride][anchor * 2];
			const float anchor_h = netAnchors[stride][anchor * 2 + 1];
			for (int i = 0; i < grid_y; i++) {
				for (int j = 0; j < grid_y; j++) {
					float box_score = Sigmoid(pdata[4]);//获取每一行的box框中含有某个物体的概率
					if (box_score > boxThreshold) {
						//为了使用minMaxLoc(),将85长度数组变成Mat对象
						cv::Mat scores(1, className.size(), CV_32FC1, pdata + 5);
						Point classIdPoint;
						double max_class_socre;
						minMaxLoc(scores, 0, &max_class_socre, 0, &classIdPoint);
						max_class_socre = Sigmoid((float)max_class_socre);
						if (max_class_socre > classThreshold) {
							//rect [x,y,w,h]
							float x = (Sigmoid(pdata[0]) * 2.f - 0.5f + j) * netStride[stride];  //x
							float y = (Sigmoid(pdata[1]) * 2.f - 0.5f + i) * netStride[stride];   //y
							float w = powf(Sigmoid(pdata[2]) * 2.f, 2.f) * anchor_w;   //w
							float h = powf(Sigmoid(pdata[3]) * 2.f, 2.f) * anchor_h;  //h
							int left = (x - 0.5*w)*ratio_w;
							int top = (y - 0.5*h)*ratio_h;
							classIds.push_back(classIdPoint.x);
							confidences.push_back(max_class_socre);
							boxes.push_back(Rect(left, top, int(w*ratio_w), int(h*ratio_h)));
						}
					}
					pdata += net_width;//指针移到下一行
				}
			}
		}
	}

	//接上面
	//执行非最大抑制以消除具有较低置信度的冗余重叠框(NMS)
	vector<int> nms_result;
	NMSBoxes(boxes, confidences, classThreshold, nmsThreshold, nms_result);
	for (int i = 0; i < nms_result.size(); i++) {
		int idx = nms_result[i];
		Output result;
		result.id = classIds[idx];
		result.confidence = confidences[idx];
		result.box = boxes[idx];
		output.push_back(result);
	}

	if (output.size())
		return true;
	else
		return false;
}

//这里的color是颜色数组,对没一个id随机分配一种颜色
void Yolo::drawPred(Mat &img, vector<Output> result, vector<Scalar> color) {
	for (int i = 0; i < result.size(); i++) {
		int left, top;
		left = result[i].box.x;
		top = result[i].box.y;
		int color_num = i;
		rectangle(img, result[i].box, color[result[i].id], 2, 8);

		string label = className[result[i].id] + ":" + to_string(result[i].confidence);

		int baseLine;
		Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
		top = max(top, labelSize.height);
		//rectangle(frame, Point(left, top - int(1.5 * labelSize.height)), Point(left + int(1.5 * labelSize.width), top + baseLine), Scalar(0, 255, 0), FILLED);
		putText(img, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 1, color[result[i].id], 2);
	}
	//namedWindow("窗口名", 0);//创建窗口
	//imshow("res", img);
	//imwrite("./result.jpg", img);
	//waitKey();
	//destroyAllWindows();
}

Main.cpp

#include "yolo.h"
#include <iostream>
#include<opencv2//opencv.hpp>
#include<math.h>

using namespace std;
using namespace cv;
using namespace dnn;


int main()
{
	cout << "Hello World" << endl;
	string img_path = "./bus.jpg";
	string model_path = "./yolov5s.onnx";

	Yolo test;
	Net net;
	if (test.readModel(net, model_path, true)) {
		cout << "read net ok!" << endl;
	}
	else {
		return -1;
	}

	//生成随机颜色
	vector<Scalar> color;
	srand(time(0));
	for (int i = 0; i < 80; i++) {
		int b = rand() % 256;
		int g = rand() % 256;
		int r = rand() % 256;
		color.push_back(Scalar(b, g, r));
	}
	vector<Output> result;
	Mat img = imread(img_path);
	if (test.Detect(img, net, result)) {
		test.drawPred(img, result, color);
		namedWindow("res", 0);//创建窗口Flags=0,是WINDOW_NORMAL
		imshow("res", img);
	}
	else {
		cout << "Detect Failed!" << endl;
	}

//system("pause");
	waitKey(0);
	destroyAllWindows();
	return 0;
}

最后运行结果如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5,测试本人的阀板训练模型

将之前的阀板训练模型 云服务器bs10 epoch50 workers4
的导出onnx看效果如何

注意,更换onnx的时候要在 头文件中更改类名
如下std::vector<std::string> className = { "gridingDefect" };
在这里插入图片描述

检测结果如下:

在这里插入图片描述

### 回答1: win10+vs2017+qt+opencv 是一种常用的开发环境组合,可以用于开发图像处理、计算机视觉等应用程序。其中,win10 是操作系统,vs2017 是集成开发环境,qt 是跨平台应用程序开发框架,opencv 是计算机视觉库。这种组合可以提高开发效率,简化开发流程,同时也具有良好的兼容性和稳定性。 ### 回答2: Win10 vs2017 Qt OpenCV,其实是三个不同的对象,下面将它们逐一进行分析。 Win10,顾名思义,就是Windows 10操作系统的缩写。Windows是全球最为知名的操作系统之一,其在操作界面、软件支持、硬件厂商等方面具有较为广泛的应用和覆盖。Win10更是在基础操作系统的基础上,对界面、安全性、易用性、兼容性等方面进行了优化和改善,使其成为一个更为齐全且更易于使用的操作系统,目前得到了广泛的用户认可。 Vs2017,是Visual Studio的缩写,2017表示该版本发布的年份。Vs是由美国微软公司开发的一款用于软件开发的集成开发环境。Vs不仅包含了代码编写、调试、编译等方面的工具,还提供了一系列辅助开发技术,例如代码重构、版本管理、跨平台开发等等。Vs被广泛应用于Windows平台下的开发,除此之外也支持其他操作系统、开发语言以及开发模式等等,其本身也在持续地更新升级以适应日益变化的开发环境。 Qt,是一个跨平台的C++应用程序开发框架,也被称为“跨平台图形用户界面应用程序开发框架”。Qt是由挪威Trolltech公司于1991年开始开发的,旨在为开发人员提供高效的框架,并能够快速构建新的应用程序。Qt具有良好的可扩展性并提供丰富的开发API,使得其可以被用于开发桌面应用、移动应用、嵌入式应用等等。在跨平台方面,Qt提供了大量的平台支持,例如Windows、Linux、macOS、Android、iOS等等,极大地方便了开发人员的工作。 OpenCV,全称是“开源计算机视觉库”,是一套基于BSD许可协议的跨平台计算机视觉应用程序开发库,可用于开发实时的计算机视觉应用程序。该库广泛应用于学术研究、科研领域以及商业领域,其支持的领域也很广泛,例如目标检测、图像处理、运动跟踪、机器学习等等。OpenCV支持众多编程语言,例如C++、Python、Java等等,也可以被用于多种操作系统上,例如Windows、Linux、macOS等等。 从以上几个对象的简介来看,Win10Vs2017、Qt、OpenCV分别是一款操作系统、一个开发工具、一个应用框架和一个开发库。它们是在不同的层面上为开发者和用户提供更好的工具和服务,目的是为了更好地完成软件开发的工作。不过在这些工具之间使用并不是互相排斥的,有时候我们也需要使用它们的组合,以便于完成某些特定的开发任务。 ### 回答3: Win10 VS2017 QT OpenCV是现今非常热门的开发环境,被广泛用于开发图形图像领域。 Win10是目前Microsoft推出的最新的操作系统,与之前的操作系统相比,更加注重用户体验,同时也更注重安全性和稳定性。Win10的更新速度很快,对开发环境与软件的兼容性比之前的版本都要更好。 VS2017是Microsoft推出的最新的开发IDE,它更加注重与异构工具链、云开发的集成,提高了团队合作的效率,同时提供了许多新的代码分析和调试工具,能够更准确地定位出现的错误。此外,VS2017也提供了用于跨平台开发的工具,非常适用于在Win10系统上进行开发。 QT是一个跨平台的C++开发框架, 其提供了丰富的GUI类库和工具。QT的特点是:跨平台,简单易用,一致性强,可定制化程度高。QT是一款免费的开源软件,因此十分受欢迎。在Win10系统上使用QT进行开发,可以帮助开发者快速地编写GUI应用程序。 OpenCV是一款流行的计算机视觉库,它提供了许多图像和视频处理的函数和算法。OpenCV可用于各大平台的开发,操作方便而深受开发者的青睐。OpenCV适用于Win10系统上,可以在QT环境中使用,为开发者提供优雅高效的图像处理解决方案。 综上所述,在Win10系统中,使用VS2017作为开发IDE,配合QT进行GUI界面的实现与OpenCV进行计算机视觉处理,能够快速地搭建起强大的开发环境。Win10 VS2017 QT OpenCV的组合能够提高开发者的效率与开发程序的稳定性,并应用于图形图像领域的快速开发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾名招财

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值