当前位置:   article > 正文

windows上yolov5 opencv dnn c++部署 cuda加速_dnn: cuda backend requires cudnn. please resolve d

dnn: cuda backend requires cudnn. please resolve dependency or disable openc

目录

前置环境

前言

一,安装cuda,cudnn

二,重新编译opencv+opencv_contrib

1,cmake编译opencv+opencv_contrib

2,VS生成解决方案

三,VS运行opencv dnn加载onnx源码

1,加载大佬的onnx模型

2,加载自己的模型

3,  jetson nano上运行

1)环境配置

2)g++方式编译

3)cmake方式编译

4)jetson nano运行结果

四,总结        

问题记录

①export导出onnx文件报错

②opencv dnn加载cuda失败

③DNN: CUDA backend requires cuDNN. Please resolve dependency or disableOPENCV_DNN_CUDA=OFF

④CONFIGURATION IS NOT SUPPORTED: validate setupvars script in installdirectory

⑤setUpNet DNN module was not built with CUDA backend;

⑥环境配好后加载自己模型失败

⑦AttributeError: 'Upsample' object has no attribute 'recompute_scale_factor'


前置环境

windows安装配置opencv opencv_contrib_野马AS的博客-CSDN博客

前言

        GitHub大佬opencv dnn加载onnx源码源码地址

        大佬的源码是在Ubuntu上运行的,但是windows上opencv环境配好后也可直接运行。由于第一次装的时候,没有编译cuda,所以只能运行cpu版本,只有5~6fps。且只能运行大佬的onnx模型,自己的yolov5模型用不了。记录一下cuda加速,opencv环境配置,以及opencv dnn调用自己yolov5训练导出生成的onnx。

一,安装cuda,cudnn

        cuda下载官网:CUDA Toolkit Archive | NVIDIA Developer

        cudnn下载官网:cuDNN Archive | NVIDIA Developer

        前排提醒:下载之前注意一下cuda和cudnn版本对应,不对应后面会出找不到cudnn的问题。还要注意一下VS和cuda版本,cuda必须是在vs之后出的版本,否则安装cuda会提示检测不到VS,导致VS最后生成解决方案失败,生成不了opencv的dll和lib文件。不过博主由于VS和cuda不对应,我选择的是能对应的cuda11.6.1,cudnn没有出for cuda11.6,就用的最新的11.5,最后报错下载zlip解决。

        ①选择完版本后,选择网络好的话选择本地下载,网络不好的可以选择网络下载。网络下载优点是包小,缺点是如果安装失败又得重新在安装时下载完整安装包。

         安装时,这一步不用选位置,,最后会消失的,好像是临时文件,不是安装文件。后面的cuda toolkit才是安装文件。(疑神疑鬼了好久,为什么cuda文件夹消失了,还重装了两次)

        

        ②cuda选择精简安装,如果不报VS的错则直接选择下一步到安装完成,开始cudann安装

                        

         ②-1,VS报错的情况不要按照网上的别的教程取消勾选Visual Studio Intergration,然后添加文件到cuda路径。我试过,这样的结果是在最后一步生成解决方案失败,然后全部重新来过。我的解决办法是找最新cuda版本以适应我最新的VS2022版本,最后生成解决方案成功。对于cuda版本有要求的,可降低VS版本。             ·                                                               

                 

        ②-2,选择好合适的版本,点击精简安装直接出现下图,则cuda安装,VS的问题就解决了

                 

        ③安装cuda nn注意对应版本,下载时注意选择zip安装,不要exe安装,cmake编译时找不到cudnn(血坑!!!)

        

        

        ④下载解压后将其中所有文件移到cuda安装目录中,我的路径为:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.5,license也移一下。安装完成                                                

        ⑤(zip安装好了的朋友跳过这一步)博主后知后觉,重试了几遍,对安装cuda和cudnn文件夹熟悉之后,发现cudnn的exe方式安装的文件在路径C:\Program Files\NVIDIA\CUDNN\v8.3中,如果用的这种安装方式的朋友要做环境变量中添加该路径,则就能检测到cudnn。zip安装方式不用添加。

                        

        ⑥按照以上步骤,没有报错弄完之后,以博主五六次重试的经验担保,cuda和cudnn已经安装完成。

二,重新编译opencv+opencv_contrib

1,cmake编译opencv+opencv_contrib

        做了前置环境的,应该比较熟悉这一步,没有做过的可以看看,编译时需要加上cuda。

如果第一次编译没有加上cuda,或者版本对应不对会出现如下报错。

        

         已经装过opencv和opencv_contrib的朋友,需要删除之前的build文件夹,重新编译opencv和opnecv_contrib,也可参考前置环境安装。出现下图则cuda和cudnn编译成功(选项框爆红再次configure即可)。

         

2,VS生成解决方案

        前面步骤没有出问题的话,这一步不会有问题,不过比较费时间,之前不加cuda生成需要几十分钟,加上cuda需要三四个小时。

三,VS运行opencv dnn加载onnx源码

1,加载大佬的onnx模型

        源码内容:

  1. #include <fstream>
  2. #include <opencv2/opencv.hpp>
  3. std::vector<std::string> load_class_list()
  4. {
  5. std::vector<std::string> class_list;
  6. std::ifstream ifs("config_files/classes.txt");
  7. std::string line;
  8. while (getline(ifs, line))
  9. {
  10. class_list.push_back(line);
  11. }
  12. return class_list;
  13. }
  14. void load_net(cv::dnn::Net &net, bool is_cuda)
  15. {
  16. auto result = cv::dnn::readNet("config_files/yolov5s.onnx");
  17. if (is_cuda)
  18. {
  19. std::cout << "Attempty to use CUDA\n";
  20. result.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
  21. result.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA_FP16);
  22. }
  23. else
  24. {
  25. std::cout << "Running on CPU\n";
  26. result.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
  27. result.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
  28. }
  29. net = result;
  30. }
  31. const std::vector<cv::Scalar> colors = {cv::Scalar(255, 255, 0), cv::Scalar(0, 255, 0), cv::Scalar(0, 255, 255), cv::Scalar(255, 0, 0)};
  32. const float INPUT_WIDTH = 640.0;
  33. const float INPUT_HEIGHT = 640.0;
  34. const float SCORE_THRESHOLD = 0.2;
  35. const float NMS_THRESHOLD = 0.4;
  36. const float CONFIDENCE_THRESHOLD = 0.4;
  37. struct Detection
  38. {
  39. int class_id;
  40. float confidence;
  41. cv::Rect box;
  42. };
  43. cv::Mat format_yolov5(const cv::Mat &source) {
  44. int col = source.cols;
  45. int row = source.rows;
  46. int _max = MAX(col, row);
  47. cv::Mat result = cv::Mat::zeros(_max, _max, CV_8UC3);
  48. source.copyTo(result(cv::Rect(0, 0, col, row)));
  49. return result;
  50. }
  51. void detect(cv::Mat &image, cv::dnn::Net &net, std::vector<Detection> &output, const std::vector<std::string> &className) {
  52. cv::Mat blob;
  53. auto input_image = format_yolov5(image);
  54. cv::dnn::blobFromImage(input_image, blob, 1./255., cv::Size(INPUT_WIDTH, INPUT_HEIGHT), cv::Scalar(), true, false);
  55. net.setInput(blob);
  56. std::vector<cv::Mat> outputs;
  57. net.forward(outputs, net.getUnconnectedOutLayersNames());
  58. float x_factor = input_image.cols / INPUT_WIDTH;
  59. float y_factor = input_image.rows / INPUT_HEIGHT;
  60. float *data = (float *)outputs[0].data;
  61. const int dimensions = 85;
  62. const int rows = 25200;
  63. std::vector<int> class_ids;
  64. std::vector<float> confidences;
  65. std::vector<cv::Rect> boxes;
  66. for (int i = 0; i < rows; ++i) {
  67. float confidence = data[4];
  68. if (confidence >= CONFIDENCE_THRESHOLD) {
  69. float * classes_scores = data + 5;
  70. cv::Mat scores(1, className.size(), CV_32FC1, classes_scores);
  71. cv::Point class_id;
  72. double max_class_score;
  73. minMaxLoc(scores, 0, &max_class_score, 0, &class_id);
  74. if (max_class_score > SCORE_THRESHOLD) {
  75. confidences.push_back(confidence);
  76. class_ids.push_back(class_id.x);
  77. float x = data[0];
  78. float y = data[1];
  79. float w = data[2];
  80. float h = data[3];
  81. int left = int((x - 0.5 * w) * x_factor);
  82. int top = int((y - 0.5 * h) * y_factor);
  83. int width = int(w * x_factor);
  84. int height = int(h * y_factor);
  85. boxes.push_back(cv::Rect(left, top, width, height));
  86. }
  87. }
  88. data += 85;
  89. }
  90. std::vector<int> nms_result;
  91. cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, nms_result);
  92. for (int i = 0; i < nms_result.size(); i++) {
  93. int idx = nms_result[i];
  94. Detection result;
  95. result.class_id = class_ids[idx];
  96. result.confidence = confidences[idx];
  97. result.box = boxes[idx];
  98. output.push_back(result);
  99. }
  100. }
  101. int main(int argc, char **argv)
  102. {
  103. std::vector<std::string> class_list = load_class_list();
  104. cv::Mat frame;
  105. cv::VideoCapture capture("sample.mp4");
  106. if (!capture.isOpened())
  107. {
  108. std::cerr << "Error opening video file\n";
  109. return -1;
  110. }
  111. bool is_cuda = argc > 1 && strcmp(argv[1], "cuda") == 0;
  112. cv::dnn::Net net;
  113. load_net(net, is_cuda);
  114. auto start = std::chrono::high_resolution_clock::now();
  115. int frame_count = 0;
  116. float fps = -1;
  117. int total_frames = 0;
  118. while (true)
  119. {
  120. capture.read(frame);
  121. if (frame.empty())
  122. {
  123. std::cout << "End of stream\n";
  124. break;
  125. }
  126. std::vector<Detection> output;
  127. detect(frame, net, output, class_list);
  128. frame_count++;
  129. total_frames++;
  130. int detections = output.size();
  131. for (int i = 0; i < detections; ++i)
  132. {
  133. auto detection = output[i];
  134. auto box = detection.box;
  135. auto classId = detection.class_id;
  136. const auto color = colors[classId % colors.size()];
  137. cv::rectangle(frame, box, color, 3);
  138. cv::rectangle(frame, cv::Point(box.x, box.y - 20), cv::Point(box.x + box.width, box.y), color, cv::FILLED);
  139. cv::putText(frame, class_list[classId].c_str(), cv::Point(box.x, box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
  140. }
  141. if (frame_count >= 30)
  142. {
  143. auto end = std::chrono::high_resolution_clock::now();
  144. fps = frame_count * 1000.0 / std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
  145. frame_count = 0;
  146. start = std::chrono::high_resolution_clock::now();
  147. }
  148. if (fps > 0)
  149. {
  150. std::ostringstream fps_label;
  151. fps_label << std::fixed << std::setprecision(2);
  152. fps_label << "FPS: " << fps;
  153. std::string fps_label_str = fps_label.str();
  154. cv::putText(frame, fps_label_str.c_str(), cv::Point(10, 25), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
  155. }
  156. cv::imshow("output", frame);
  157. if (cv::waitKey(1) != -1)
  158. {
  159. capture.release();
  160. std::cout << "finished by user\n";
  161. break;
  162. }
  163. }
  164. std::cout << "Total frames: " << total_frames << "\n";
  165. return 0;
  166. }

        在配有opencv环境的VS项目下,大佬的源码可直接运行,如果上述步骤配置好,则会cuda加速GPU运行;没有配置好,则会cpu运行。GPU是CPU的三倍,感觉opencv的加速还是不够理想,运行起来,GPU并没有消耗太多,最高22fps,最低11fps,平均18fps左右。

        运行效果: 

2,加载自己的模型

        ①这一步,首先得有自己的模型,避免踩坑提前说一下,下载yolov5 v6.1版本训练的模型导出才能使用。yolov5-6.1版本训练看这篇博客的前面部分。导出onnx模型,yolov5有export.py文件(导出onnx需要下载onnx包),可直接使用导出。yolov5 6.1需注意pytorch版本,我使用时导出onnx模型,还不支持pytorch 1.11,可conda创建一个较低的pytorch版本用于导出。

  1. #python export文件路径 --weights pt文件路径 --include onnx
  2. python export.py --weights yolov5s.pt --include onnx

        ①-1,(更新)随着对yolov5模型理解的加深,明白了之前为什么导出的onnx模型,使用不成功。在我那一版yolov5中,他的模型结构还没有优化完全,output分支有三个,没有整合到一起。而大佬源码处理的是整合到一起的onnx模型,也就是输出为[1.25200,85]的模型。

        原来的yolov5 5.0导出onnx模型结构:

        现在yolov5 6.1导出的onnx模型结构:

        ①-2,查看模型结构软件Netron,大力推荐,后续进一步学习必备工具。下载地址

        ②修改源码

        在8行修改为自己的分类txt文件路径。19行修改为自己的模型文件路径,

        ②-1,110行修改分类,这个85=80 (COCO 数据集的类数) + 1 (confidence) + 4 (xywh),所以你的模型分类为2的话,那么这就改为data+=7。

 

         ②-2,132行修改输入流——路径:视频文件;0:电脑自带摄像头;1:usb摄像头;139行选择运行模型的设备为CPU还是GPU,CPU修改红框内容为0GPU修改红框内容为1。源码这句话是,获取ubuntu命令行运行可执行文件时手动输入cuda的信息,如终端./yolo_example cuda。就会以GPU方式运行。windows运行如果不修改,就会默认cpu加载模型。

        ③点击运行即可,我使用的是yolov5n的模型,FPS贼高,非常适合移动端的部署。

3,  jetson nano上运行

1)环境配置

        jetson的ubuntu系统镜像上面自带cuda,所以ubuntu安装cuda的过程就省略了(后续有机会安装,再更新一下)。openc和opencv_contrib的编译安装,由于raw网址的封禁,所以编译的时候往往会编译失败。建议在windows上编译成功了,再复制文件jetson nano上进行编译,这样由于在windows上配置的时候,缺的包已经补齐,所以可一次编译成功。

        windows上编译参考前置环境安装.

        ①windows上编译成功后,新建opencv-4.5.5文件夹(4.5.5为版本信息,根据自己的版本命名),将能够成功编译的opencv中的source中所有文件,移到新建文件夹中。再将能够成功编译的opencv_contrib文件夹移到新建文件夹中。

         ②然后将这个文件夹拷贝到jetson nano上,在这个文件夹中,新建build文件夹,新建build.sh,用执行build.sh文件的方式,可避免再次编译时重新输入参数的麻烦,也可以记录编译时选择的配置,以后可根据需求增删,重新编译

cd opencv-4.5.5   #打开opencv-4.5.5 

mkdir build        #新建build文件夹

cd build        #打开build

touch build.sh      #新建build.sh

chmod 777 build.sh  #给build可执行权限,777:给文件所有权限

gedit build.sh         #编辑build.sh

        ③在build.sh中添加cmake编译指令。

  1. cmake \
  2. -DCMAKE_BUILD_TYPE=Release \
  3. -DBUILD_PNG=ON \
  4. -DBUILD_TIFF=ON \
  5. -DBUILD_TBB=OFF \
  6. -DBUILD_JPEG=ON \
  7. -DBUILD_JASPER=OFF \
  8. -DBUILD_ZLIB=ON \
  9. -DBUILD_EXAMPLES=OFF \
  10. -DBUILD_opencv_java=OFF \
  11. -DBUILD_opencv_python2=OFF \
  12. -DBUILD_opencv_python3=ON \ #选择opencv3
  13. -DENABLE_PRECOMPILED_HEADERS=OFF \
  14. -DWITH_OPENCL=ON \
  15. -DWITH_OPENMP=OFF \
  16. -DWITH_FFMPEG=ON \
  17. -DWITH_GSTREAMER=ON \
  18. -DWITH_GSTREAMER_0_10=OFF \
  19. -DWITH_CUDA=ON \ #链接cuda
  20. -DWITH_GTK=ON \
  21. -DWITH_VTK=OFF \
  22. -DWITH_TBB=ON \
  23. -DWITH_1394=OFF \
  24. -DWITH_OPENEXR=OFF \
  25. -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda \
  26. -DCUDA_ARCH_BIN=5.3\ #根据自己显卡算力修改,jetson nano为5.3
  27. -DCUDA_ARCH_PTX="" \
  28. -DINSTALL_C_EXAMPLES=OFF \
  29. -DOPENCV_ENABLE_NONFREE=ON \
  30. -DINSTALL_TESTS=OFF \
  31. -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.5.5/modules \ #根据自己的版本改
  32. -DCMAKE_INSTALL_PREFIX=/usr/ \
  33. ..
  34. make -j4
  35. sudo make install

        ④最后执行build

./build.sh

2)g++方式编译

        不使用cuda

git clone https://github.com/doleron/yolov5-opencv-cpp-python.git
cd yolov5-opencv-cpp-python
g++ -O3 cpp/yolo.cpp -o yolo_example `pkg-config --cflags --libs opencv4`
./yolo_example

      使用cuda( 且cuda编译成功)

git clone https://github.com/doleron/yolov5-opencv-cpp-python.git
cd yolov5-opencv-cpp-python
g++ -O3 cpp/yolo.cpp -o yolo_example `pkg-config --cflags --libs opencv4`
./yolo_example cuda

3)cmake方式编译

git clone https://github.com/doleron/yolov5-opencv-cpp-python.git

cd yolov5-opencv-cpp-python

touch CMakeLists.txt

gedit CMakeLists.txt

        在CMakeLists.txt中添加如下内容

  1. cmake_minimum_required(VERSION 2.8)
  2. SET(CMAKE_CXX_STANDARD 11)
  3. PROJECT(yolo_example)
  4. find_package(OpenCV REQUIRED)
  5. include_directories( ${OpenCV_INCLUDE_DIRS} )
  6. add_executable(yolo_example cpp/yolo.cpp)
  7. target_link_libraries(yolo_example ${OpenCV_LIBS})

        然后cmake编译执行,生成可执行文件yolo_example

cmake ./
make

        cpu运行

./yolo_example

        cuda运行

./yolo_example cuda

4)jetson nano运行结果

        ①yolov5s运行,cpu模式只有零点几帧,cuda模式运行稳定后有3.5帧左右

         ②yolov5n运行,cpu有1.5帧左右,cuda模式有9.6帧左右。不得不说,yolov5n真的强。

四,总结        

        从第一眼看到大佬源码的惊喜,再到加载自己模型始终成功不了的绝望,再到看懂大佬源码进行修改,一步一步学到了很多。不过总感觉深度学习入门,还是配置环境问题,一个模型的训练,到部署需要很多环境才能实现。进一步,就是对算法源码的理解,对模型的理解。目前对于博主来说,关于yolov5这种算法的环境部署大致弄懂。但对模型结构理解还不是很通透,所以使用别人的源码,出了很多问题,不过还好解决问题过程,也是学习的过程。

        关于实现github大佬源码有什么问题,欢迎在评论区留言讨论。

问题记录

①export导出onnx文件报错

ONNX export failure: No module named 'onnx'

解决方法:在环境中下载onnx

②opencv dnn加载cuda失败

        解决办法:配置cuda和cudnn

③DNN: CUDA backend requires cuDNN. Please resolve dependency or disable
OPENCV_DNN_CUDA=OFF

        解决办法:正确配置cudnn,在cmake编译时,能在报错框显示cudnn已找到

                                

④CONFIGURATION IS NOT SUPPORTED: validate setupvars script in install
directory

        解决办法:忽略,不用管

⑤setUpNet DNN module was not built with CUDA backend;

        解决办法:不懂原理,下载zlib添加环境变量解决。解决办法链接

⑥环境配好后加载自己模型失败

                               

        解决办法:更换yolov5版本,换为yolov5-6.1版本训练导出,导出时注意自己的pytorch版本,pytorch版本<=1.10才行。

⑦AttributeError: 'Upsample' object has no attribute 'recompute_scale_factor'

        解决办法:降低pytorch版本,pytorch版本<=1.10才行。

参考文章

深度学习GPU环境CUDA详细安装过程(简单快速有效) - 知乎

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/161548
推荐阅读
相关标签
  

闽ICP备14008679号