1. 码云仓库链接:https://gitee.com/myboyhood/yolo-tensorrt
2. 参考博客:
1. 用C/C++写一个简单的音乐播放器(基于windows控制台编程):https://blog.csdn.net/lwx1051046458/article/details/128889992
3. 过程记录:
1. 下载工程代码:
git clone https://gitee.com/myboyhood/yolo-tensorrt.git
2. 代码结构:
3. 尝试编译:
作者建议在ubuntu 上使用 cmake编译,在 windows 上使用 Visual Studio xxxx 编辑器使用打开 .sln 文件的方式打开此工程进行编译,因为我对 Visual Studio xxxx 不熟,感觉 vs 界面操作很难受,又要建属性表什么的,所以我这里使用原始的编译命令,因为在 windows 上使用 minGW、cymin 等的 g++ 无法编译使用了 cuda、tensorRT 等使用到操作系统底层硬件的项目,所以我这里使用 vs 中 msvc 自带的 cl.exe 工具来进行编译,例如我电脑上 cl.exe 的位置如下所示:
复制博客 windows + tensorRT + yolov8 环境 mp4 视频物体检测测试( C++版本 ) 中的 cl语句如下:
cl ^
-I"D:\install\VisualStudio2022_comm\VC\Tools\MSVC\14.40.33807\include" ^
-I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt" ^
-I"D:\install\opencv\opencv\build\include" ^
-I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\include" ^
-Fe"./build/test.exe" ^
./src/test.cpp ^
./src/objectCheck.cpp ^
-link libcpmt.lib ^
-link kernel32.lib ^
-link libucrt.lib ^
-link cudart.lib ^
-link nvinfer.lib ^
-link opencv_world4100.lib ^
-link opencv_world4100d.lib ^
-LIBPATH:"D:\install\VisualStudio2022_comm\VC\Tools\MSVC\14.40.33807\lib\x64" ^
-LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\x64" ^
-LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\ucrt\x64" ^
-LIBPATH:"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\lib\x64" ^
-LIBPATH:"D:\install\opencv\opencv\build\x64\vc16\lib"
稍做修改,虽然我不熟悉 .sln工程,但是通过 .sln工程中的 .vcxproj 文件能获取一些有用的信息,比如参与编译的 .cpp、.c文件,需要包含的头文件目录,需要链接的库的目录和库名称等,接下来就是阅读 .vcxproj 文件,转换成等价 cl 编译语句。
以 dll_detector 为例( props应该是 vs 生成的属性表,用于将为 Opencv、cuda等设置的头文件目录、库目录等持久化成的配置文件,要使用的直接导进去,不用每次新建工程都从零开始设置 ):
打开 dll_detector.vcxproj 文件:
于是修改后的 cl 编译语句如下:
cl ^
-I"D:\install\VisualStudio2022_comm\VC\Tools\MSVC\14.40.33807\include" ^
-I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt" ^
-I"D:\install\opencv\opencv\build\include" ^
-I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\include" ^
-I"D:\code\c_code\cpp_study_demo\vs2022\yolo-tensorrt\extra" ^
-I"D:\code\c_code\cpp_study_demo\vs2022\yolo-tensorrt\modules" ^
-Fe"./build/test.exe" ^
./samples/sample_detector.cpp ^
./modules/calibrator.cpp ^
./modules/class_detector.cpp ^
./modules/ds_image.cpp ^
./modules/plugin_factory.cpp ^
./modules/trt_utils.cpp ^
./modules/yolo.cpp ^
./modules/yoloplugin_lib.cpp ^
./modules/yolov2.cpp ^
./modules/yolov3.cpp ^
./modules/yolov4.cpp ^
./modules/yolov5.cpp ^
./modules/chunk.cu ^
./modules/detect.cu ^
./modules/hardswish.cu ^
./modules/kernel.cu ^
./modules/mish.cu ^
-link libcpmt.lib ^
-link kernel32.lib ^
-link libucrt.lib ^
-link cudart.lib ^
-link nvinfer.lib ^
-link opencv_world4100.lib ^
-link opencv_world4100d.lib ^
-LIBPATH:"D:\install\VisualStudio2022_comm\VC\Tools\MSVC\14.40.33807\lib\x64" ^
-LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\x64" ^
-LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\ucrt\x64" ^
-LIBPATH:"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\lib\x64" ^
-LIBPATH:"D:\install\opencv\opencv\build\x64\vc16\lib"
执行 cl 语句,报如下错:
trt_utils.cpp
D:\install\VisualStudio2022_comm\VC\Tools\MSVC\14.40.33807\include\experimental/filesystem(29):
fatal error C1189: #error: The <experimental/filesystem> header providing std::experimental::filesystem is deprecated by Microsoft and will be REMOVED.
It is superseded by the C++17 <filesystem> header providing std::filesystem.
You can define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING to suppress this error.
打开 trt_utils.cpp 文件,发现有如下内容:
#include "trt_utils.h"
#include <NvInferRuntimeCommon.h>
#ifdef HAVE_FILESYSTEM
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
确实是 trt_utils.cpp 导致的这个报错,于是在 trt_utils.h 中加入如下内容:
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
执行 cl语句,发现不报这个错了,但是会报如下错:
.\modules\chunk.cu : fatal error LNK1107: 文件无效或损坏: 无法在 0x18FB 处读取
出现损坏字样,难道真的是下载时出问题了,把 chunk.cu 注释掉执行 cl 语句,报如下错:
.\modules\detect.cu : fatal error LNK1107: 文件无效或损坏: 无法在 0x1D78 处读取
这时候已经能断定不是 .cu文件下载时损坏了导致的,应该是 cl 命令不支持 .cu文件的编译,研究了下有 .cu文件的应该算是 cuda 项目,应该使用 cuda 的 nvcc命令,直接将 cl 替换为 nvcc 试试,报错:
nvcc fatal : Unknown option '-Fe./build/test.exe'
应该是 nvcc 不支持该写法,直接把这个删掉,即不手动指定 exe 文件的输出位置,执行报错:
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\include\crt/host_config.h(153): fatal error C1189: #error: -- unsupported Microsoft Visual Studio version! Only the versions between 2017 and 2022 (inclusive) are supported! The nvcc flag '-allow-unsupported-compiler' can be used to override this version check; however, using an unsupported host compiler may cause compilation failure or incorrect run time execution. Use at your own risk.
按照提示,在 nvcc 后面加上 -allow-unsupported-compiler 标记,执行,报错:
LINK : fatal error LNK1181: 无法打开输入文件“opencv_world4100.lib”
现在 .cu不报错了,但是 opencv 的 lib文件有链接不进来了,百度了下说是 nvcc 的语法和 cl 语法不太一样,应该将
-LIBPATH:"D:\install\opencv\opencv\build\x64\vc16\lib"
换成
-LD:\install\opencv\opencv\build\x64\vc16\lib
将
-link opencv_world4100.lib ^
-link opencv_world4100d.lib ^
换成
-lopencv_world4100 ^
-lopencv_world4100d ^
执行 nvcc 编译语句,控制台输入如下所示:
chunk.cu
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.6/include\NvInfer.h(6125): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.6/include\NvInfer.h(6125): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
detect.cu
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.6/include\NvInfer.h(6125): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.6/include\NvInfer.h(6125): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
hardswish.cu
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.6/include\NvInfer.h(6125): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.6/include\NvInfer.h(6125): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
kernel.cu
mish.cu
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.6/include\NvInfer.h(6125): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.6/include\NvInfer.h(6125): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
libcpmt.lib
kernel32.lib
libucrt.lib
cudart.lib
nvinfer.lib
正在创建库 a.lib 和对象 a.exp
LINK : warning LNK4217:符号“??0Detector@@QEAA@XZ (public: __cdecl Detector::Detector(void))”(在“ tmpxft_0000397c_00000000-35_class_detector.obj”中定义)已由“tmpxft_0000397c_00000000-29_sample_detector.obj”(函数“main”中)导入
LINK : warning LNK4217:符号“??1Detector@@QEAA@XZ (public: __cdecl Detector::~Detector(void))”(在“ tmpxft_0000397c_00000000-35_class_detector.obj”中定义)已由“tmpxft_0000397c_00000000-29_sample_detector.obj”(函数“"public: void * __cdecl Detector::`scalar deleting destructor'(unsigned int)" (??_GDetector@@QEAAPEAXI@Z)”中)导入
LINK : warning LNK4217:符号“?init@Detector@@QEAAXAEBUConfig@@@Z (public: void __cdecl Detector::init(struct Config const &))”(在“ tmpxft_0000397c_00000000-35_class_detector.obj”中定义)已由“tmpxft_0000397c_00000000-29_sample_detector.obj”(函数“main”中)导入
LINK : warning LNK4217:符号“?detect@Detector@@QEAAXAEBV?$vector@VMat@cv@@V?$allocator@VMat@cv@@@std@@@std@@AEAV?$vector@V?$vector@UResult@@V?$allocator@UResult@@@std@@@std@@V?$allocator@V?$vector@UResult@@V?$allocator@UResult@@@std@@@std@@@2@@3@@Z (public: void __cdecl Detector::detect(class std::vector<class cv::Mat,class std::allocator<class cv::Mat> > const &,class std::vector<class std::vector<struct Result,class std::allocator<struct Result> >,class std::allocator<class std::vector<struct Result,class std::allocator<struct Result> > > > &))”(在“ tmpxft_0000397c_00000000-35_class_detector.obj”中定义)已由“tmpxft_0000397c_00000000-29_sample_detector.obj”(函数“main”中)导入
虽然看着挺吓人的,但是已经搜不出 'error' 字样了,都是一些 'warning' 信息,发现 a.exe 已经生成了,执行 a.exe,报错:
File does not exist : ../configs/yolov4-tiny.cfg
Assertion failed: fileExists(cfgFilePath), file D:\code\c_code\cpp_study_demo\vs2022\yolo-tensorrt\modules\yolo.cpp, line 985
应该在 configs 所在目录新建一个目录,比如叫 build,将 a.exe 复制进来,再执行 a.exe,控制台输出如下:
发现确实是在用显卡了,而且也出效果了,证明编译的 exe 应该是没问题的,只是目前不清楚该程序的作用,后面慢慢研究过吧...
最终完整的 nvcc_build.bat 如下:
nvcc -allow-unsupported-compiler ^
-I"D:\install\VisualStudio2022_comm\VC\Tools\MSVC\14.40.33807\include" ^
-I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt" ^
-I"D:\install\opencv\opencv\build\include" ^
-I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\include" ^
-I"D:\code\c_code\cpp_study_demo\vs2022\yolo-tensorrt\extra" ^
-I"D:\code\c_code\cpp_study_demo\vs2022\yolo-tensorrt\modules" ^
./samples/sample_detector.cpp ^
./modules/calibrator.cpp ^
./modules/class_detector.cpp ^
./modules/ds_image.cpp ^
./modules/plugin_factory.cpp ^
./modules/trt_utils.cpp ^
./modules/yolo.cpp ^
./modules/yoloplugin_lib.cpp ^
./modules/yolov2.cpp ^
./modules/yolov3.cpp ^
./modules/yolov4.cpp ^
./modules/yolov5.cpp ^
./modules/chunk.cu ^
./modules/detect.cu ^
./modules/hardswish.cu ^
./modules/kernel.cu ^
./modules/mish.cu ^
-link libcpmt.lib ^
-link kernel32.lib ^
-link libucrt.lib ^
-link cudart.lib ^
-link nvinfer.lib ^
-lopencv_world4100 ^
-lopencv_world4100d ^
-LIBPATH:"D:\install\VisualStudio2022_comm\VC\Tools\MSVC\14.40.33807\lib\x64" ^
-LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\x64" ^
-LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\ucrt\x64" ^
-LIBPATH:"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\lib\x64" ^
-LD:\install\opencv\opencv\build\x64\vc16\lib
补充:
其实 nvcc 进行编译,内部是需要调用 cl.exe的,例如将我电脑上将 D:\install\VisualStudio2022_comm\VC\Tools\MSVC\14.40.33807\bin\Hostx64\x64 下的 cl.exe 修改下名称,执行 nvcc_build.bat 会如下错:
nvcc fatal : Cannot find compiler 'cl.exe' in PATH