Bootstrap

(Windows 10)Yolov5-5.0模型的TensorRT加速+ C++部署 + VS2019封装 dll (CMake) + Qt调用

前置条件

确保已经完成了yolov5的环境配置并实现了训练自己的数据集,得到权重文件
本文整体结构和流程参考:Yolov5训练自己的数据集+TensorRT加速+Qt部署
完善知识体系的知识:win32和x86以及x64的区别
本人使用的环境记录:TensorRT版本不同,对应的lib库会有不同

Win10
cuda 11.1
cudnn 8.5.0
TensorRT 8.2.1.8
Visual Studio 2019
Opencv 4.5.5
Qt 5.14.2

在这里插入图片描述

  • 为自己的电脑配置可能需要的环境变量做的笔记,便于复制

头文件包含目录:

D:\Program Files\TensorRT-8.2.1.8\include
D:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\include
D:\OpenCV\v455\opencv\build\include
D:\OpenCV\v455\opencv\build\include\opencv2

lib 库目录:TensorRT的lib文件夹不分x64和Win32,Ohttps://blog.csdn.net/qq_22487889/article/details/127040950penCV只有x64,CUDA分x64和Win32

D:\Program Files\TensorRT-8.2.1.8\lib
D:\OpenCV\v455\opencv\build\x64\vc15\lib
D:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\lib\x64
D:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\lib\Win32
//一般不用最后一行的Win32

附加依赖项:根据环境的不同,需要依赖的lib文件可能不同(注意注意:不要在附加依赖项中添加成了dll文件!!!!

//前5个(一般不用)是CUDA/vxx.x/lib/Win32拥有的,5-8是x64所拥有的
//再后面除了opencv以外都是TensorRT拥有的,但是我用的
cuda.lib
cudadevrt.lib
cudart_static.lib
OpenCL.lib
cudart.lib
cublas.lib
cudnn.lib
cudnn64_8.lib
myelin64_1.lib
nvinfer.lib
nvinfer_plugin.lib
nvonnxparser.lib
nvparsers.lib
opencv_world455.lib	//opencv版本不同就不一样

由于TensorRT8.2.18没有myelin64_1.lib,会报错:无法打开输入文件“myelin64_1.lib“,如果是没有该库文件的,删除myelin64_1.lib这一行

一、 利用TenbsorRT进行模型的加速

.pt文件→.wts文件→.engine文件

1.1 生成 .wts 文件

此处参考Yolov5训练自己的数据集+TensorRT加速+Qt部署的 3.1 节即可

1.2 生成 .engine 文件

1.2.1 下载电脑支持的CUDA版本以及对应的cuDNN和TensorRT

  1. 我下载的是CUDA 11.1.1版本,具体查看自己电脑支持的CUD【A版本可以上网搜资料。记得使用VS2019及以下版本比较好。
    Pytorch,查看Pytorch版本,查看CUDA版本,查看cudnn版本,查看pytorch可用性,查看cuda可用性,查看cudnn可用性
    Cuda和cuDNN安装教程(超级详细)
    如果在没有显卡的电脑上安装,只有intel核显,没有出现第二行
    在这里插入图片描述
    还出现了如下问题:Win10系统安装CUDA10.0和cuDNN
    卸载了VS2022,然后安装VS2019,问题得到了解决。
    在这里插入图片描述
  2. 然后是安装TensorRT
    TensorRT下载网站
    windows上安装TensorRT
    在sample_mnist.sln下,重新生成解决方案,再执行
    一些问题的解决:

1.2.2 根据自己使用的VS版本下载对应版本的OpenCV

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<iostream>
using namespace cv;
using namespace std;
 
int main() {
	Mat image = Mat::zeros(300, 600, CV_8UC3);
	circle(image, Point(300, 200), 100, Scalar(0, 255, 120), -100);
	circle(image, Point(400, 200), 100, Scalar(255, 255, 255), -100);
	imshow("show window", image);
	waitKey(0);
	return 0;
}

结果:
在这里插入图片描述

  • 配置Release模式:刚刚我们配置的只能在DeBug|x64中运行,下面我们配置Release|x64的属性表,可以在Release|x64中运行。
    在visual studio中找到属性管理器
    VS2022永久配置OpenCV开发环境
    注意配置release版本,在“通用属性-链接器-输入-附加依赖项”中添加一定要是****.lib,而不是debug版本中的****d.lib,因为只有.lib才对应的是Release版本
    在这里插入图片描述

1.2.3 编译生成可执行文件

参考:
BiliBili:win10 使用TensorRT部署 yolov5-v4.0(C++)(二)
CSDN:win10 使用TensorRT部署 yolov5-v4.0(C++)
如果使用的是自己的数据集,记得修改 yololayer.h 头文件,主要是修改分类和识别框
在这里插入图片描述
错误记录:直接使用参考博客的 CMakeLists 会出现错误,需要添加tensorrtx/yolov5/CMakeLists.txt

add_definitions(-DAPI_EXPORTS)

注意是 yolov5-5.0 版本,最后我的 CMakeLists 如下:文件目录要和自己的对应

cmake_minimum_required(VERSION 2.8)

#=========================================================
project(yolov5)                                 #1 工程名
set(OpenCV_DIR "D:\\OpenCV\\v455\\opencv\\build")    #2 opencv目录
set(OpenCV_INCLUDE_DIRS ${OpenCV_DIR}\\include) #3 
set(OpenCV_LIB_DIRS ${OpenCV_DIR}\\x64\\vc15\\lib) #4
set(OpenCV_Debug_LIBS "opencv_world455d.lib")     #5
set(OpenCV_Release_LIBS "opencv_world455.lib")    #6
set(TRT_DIR "D:\\Program Files\\TensorRT-8.2.1.8")  #7
set(TRT_INCLUDE_DIRS ${TRT_DIR}\\include) #8
set(TRT_LIB_DIRS ${TRT_DIR}\\lib)         #9
set(Dirent_INCLUDE_DIRS "D:\\DeepLearning\\tensorrtx-yolov5-v5.0\\yolov5")  #10
#=========================================================

add_definitions(-std=c++11)
add_definitions(-DAPI_EXPORTS)
option(CUDA_USE_STATIC_CUDA_RUNTIME OFF)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE Debug)

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)

# setup CUDA
find_package(CUDA REQUIRED)
message(STATUS "    libraries: ${CUDA_LIBRARIES}")
message(STATUS "    include path: ${CUDA_INCLUDE_DIRS}")

include_directories(${CUDA_INCLUDE_DIRS})

####
enable_language(CUDA)  # add this line, then no need to setup cuda path in vs
####
include_directories(${PROJECT_SOURCE_DIR}/include) #11
include_directories(${TRT_INCLUDE_DIRS}) #12
link_directories(${TRT_LIB_DIRS}) #13
include_directories(${OpenCV_INCLUDE_DIRS}) #14
link_directories(${OpenCV_LIB_DIRS}) #15
include_directories(${Dirent_INCLUDE_DIRS}) #16


# -D_MWAITXINTRIN_H_INCLUDED for solving error: identifier "__builtin_ia32_mwaitx" is undefined
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Ofast -D_MWAITXINTRIN_H_INCLUDED")

# setup opencv
find_package(OpenCV QUIET
    NO_MODULE
    NO_DEFAULT_PATH
    NO_CMAKE_PATH
    NO_CMAKE_ENVIRONMENT_PATH
    NO_SYSTEM_ENVIRONMENT_PATH
    NO_CMAKE_PACKAGE_REGISTRY
    NO_CMAKE_BUILDS_PATH
    NO_CMAKE_SYSTEM_PATH
    NO_CMAKE_SYSTEM_PACKAGE_REGISTRY
)

message(STATUS "OpenCV library status:")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    lib path: ${OpenCV_LIB_DIRS}")
message(STATUS "    Debug libraries: ${OpenCV_Debug_LIBS}")
message(STATUS "    Release libraries: ${OpenCV_Release_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")

add_executable(yolov5 ${PROJECT_SOURCE_DIR}/yolov5.cpp ${PROJECT_SOURCE_DIR}/common.hpp ${PROJECT_SOURCE_DIR}/yololayer.cu ${PROJECT_SOURCE_DIR}/yololayer.h)   #17
target_link_libraries(yolov5 "nvinfer" "nvinfer_plugin") #18
target_link_libraries(yolov5 debug ${OpenCV_Debug_LIBS}) #19
target_link_libraries(yolov5 optimized ${OpenCV_Release_LIBS}) #20
target_link_libraries(yolov5 ${CUDA_LIBRARIES}) #21
target_link_libraries(yolov5 Threads::Threads)  

在这里插入图片描述

  • 最终的项目结构如下:
    在这里插入图片描述
  • Debug和Release模式的区别:编译工具条内的Debug与Release选项有什么含义
    Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。Debug带有大量的调试代码,运行时需要相应的运行库,发布模式程序紧凑不含有调试代码和信息,直接可以运行(如果不需要运行库)。
    顺便补充一下 gcc 和 g++ 的知识
    GCC的DEBUG和release版本编译方法

1.2.4 wts文件生成engine文件

  1. 对之前生成的.wts文件使用命令:exe 文件和 wts 具体名称以及文件夹自己修改
    也可以直接将权重文件复制到生成的目录(Debug或者Release)下进行如下执行
yolov5.exe -s best20220918.wts best20220918.engine s

在这里插入图片描述
生成成功:
在这里插入图片描述

  1. 测试:模型预测
    在刚刚的地方直接新建一个文件夹用来存放预测图象
    在这里插入图片描述
    然后输入命令:处理image_dir文件夹内的图片,可以看到处理速度,处理后的图片会显示识别框以及标签的 id
yolov5.exe -d best20220918.engine ./image_dir

在这里插入图片描述

二、 模型的封装

将模型封装成动态链接库(.dll)的形式,从而在Qt中调用。
用于完善自己知识体系的知识:
VS中空项目、win32项目、控制台程序的区别

2.1 VS2019创建 dll 并调用动态库的方法

该节的内容比较长,新写了一个文章,内容请看:VS2019 - 动态库的编写和调用
本节参考:
CSDN:VS2019环境下C++动态链接库(DLL)的创建与调用
BIliBili:Visual Studio 2019-编写C++动态链接库
BiliBili:Visual Studio 2019-显式调用C++动态库

2.2 将yolov5封装成一个导出类,生成动态链接库 dll

该节的内容请看:(win10) yolov5-v5.0导出动态链接库-TensorRT+VS2019+CMake
本节新增参考参考:CSDN:yolov5动态链接库DLL导出(TensorRT)
BiliBili:win10 使用TensorRT部署 yolov5-v4.0(C++)(三)
上述采用的是yolov5-v4.0,而我的是yolov5-v5.0,因此代码是需要根据自己的版本进行更改的

2.3 在VS中进行检测封装好的模型是否能够运行

  1. 创建空项目
    在这里插入图片描述
  2. 将需要的文件放入项目中,文件在属性中的包含了的文件夹内其实也可以不放
  • 需要的文件
    在这里插入图片描述
    在这里插入图片描述
  • 项目内容如下: main.cpp 是自己写的,参考:三.测试
    在这里插入图片描述
  1. 项目结构及代码如下:注意属性要与 dll 的导出属性相同,我的均在Release | x64 下实现
    在这里插入图片描述
//main.cpp
#pragma once
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include "Detection.h"
#include "dirent.h"
#include "yololayer.h"

using namespace std;

int main()
{

	Connect connect;
	YOLOV5* yolo_dll = connect.Create_YOLOV5_Object();

	cv::VideoCapture capture(0);
	if (!capture.isOpened()) {
		std::cout << "Error opening video stream or file" << std::endl;
		return -1;
	}
	yolo_dll->Initialize("./best20220918.engine", 0);
	while (1)
	{
		cv::Mat frame;
		capture >> frame;
		vector<cv::Rect> Boxes;
		vector<const char*> ClassLables;

		yolo_dll->Detecting(frame, Boxes, ClassLables);
		cv::imshow("output", frame);
		cv::waitKey(1);
	}
	connect.Delete_YOLOV5_Object(yolo_dll);
	return 0;
}
  1. 配置环境需要配置,不一定每一行都需要,我是一刀切了
#将此路径加入项目属性包含目录中
D:\DeepLearning\tensorrtx-yolov5-v5.0_dll\yolov5
D:\Program Files\TensorRT-8.2.1.8\include
D:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\include
D:\OpenCV\v455\opencv\build\include
D:\OpenCV\v455\opencv\build\include\opencv2
 
#将此路径加入项目属性的库目录中,也就是我们刚刚生成dll的文件目录
#TensorRT的lib文件夹不分x64和Win32,OpenCV只有x64,CUDA分x64和Win32
D:\DeepLearning\tensorrtx-yolov5-v5.0_dll\yolov5\build_dll\Release
D:\Program Files\TensorRT-8.2.1.8\lib
D:\OpenCV\v455\opencv\build\x64\vc15\lib
D:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\lib\x64
D:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\lib\Win32

#在输入链接器添加依赖库
yolov5.lib
#前5个(一般不用)是CUDA/vxx.x/lib/Win32拥有的,5-8是x64所拥有的
#再后面除了opencv以外都是TensorRT拥有的
cuda.lib
cudadevrt.lib
cudart_static.lib
OpenCL.lib
cudart.lib
cublas.lib
cudnn.lcucuda
cudnn64_8.lib
nvinfer.lib
nvinfer_plugin.lib
nvonnxparser.lib
nvparsers.lib
opencv_world455.lib
opencv_world455d.lib	//opencv版本不同就不一样

三、 利用QT部署

方法1(我没有使用):Visual Studio 2019 配置 Qt5.14.2 开发环境并部署,参考:该博客的五、利用Qt进行部署
该方法要注意:Qt中使用的编译器(MinGW or MSVC)必须和编译库使用的编译器相同!!!

3.1 Visual Studio 2019 的项目进行打包并与Qt互相传递参数

3.1.1 修改main.cpp文件,从而获取参数

参考:OpenCV中Rect()函数常用操作和使用详解(含绘图示例)+Rectangle()函数用法 按照自己需要选取参数。
我增加的代码如下:

for (auto r : Boxes) {
			cout << "Boxes:" << r << endl;
			cout << "左上:" << r.tl() << "右下" << r.br() << "\t";
		}

输出如图:可以看出Boxes的参数是【宽 × 长 from 左上角】
在这里插入图片描述

3.1.2 对VS项目进行打包

  1. 首先对项目的属性进行修改:
    vs2019 生成包含dll的exe
    https://blog.csdn.net/love521963/article/details/107326320
    然后生成解决方案因为我测试 dll 的环境是Release | x64 的环境,就改成多线程(/MT),点击生成解决方案,根据下方项目路径找到exe文件:
    在这里插入图片描述
  2. 然后进入文件夹中添加文件,最后文件夹所需的所有内容如下:
    在这里插入图片描述
  3. 在别人的电脑上会出现以下问题:这是因为运行的电脑要有和配置环境的电脑拥有相同的环境
    在这里插入图片描述

3.2 QT调用VS打包后的exe文件并获取参数

3.2.1 参考:QT调用外部程序exe并互相传递参数

;