当前位置:   article > 正文

YOLOV8 C++ opecv_dnn模块部署_opencv4.7 cudnn yolov8

opencv4.7 cudnn yolov8

废话不多说:opencv>=4.7.0

opencv编译不做解释,需要的话翻看别的博主的编译教程

代码饱含V5,V7,V8部署内容

头文件yoloV8.h

  1. #pragma once
  2. #include<iostream>
  3. #include<opencv2/opencv.hpp>
  4. using namespace std;
  5. using namespace cv;
  6. using namespace cv::dnn;
  7. struct Detection
  8. {
  9. int class_id{ 0 };//结果类别id
  10. float confidence{ 0.0 };//结果置信度
  11. cv::Rect box{};//矩形框
  12. };
  13. class Yolo {
  14. public:
  15. bool readModel(cv::dnn::Net& net, std::string& netPath, bool isCuda);
  16. void drawPred(cv::Mat& img, std::vector<Detection> result, std::vector<cv::Scalar> color);
  17. virtual vector<Detection> Detect(cv::Mat& SrcImg, cv::dnn::Net& net) = 0;
  18. float sigmoid_x(float x) { return static_cast<float>(1.f / (1.f + exp(-x))); }
  19. Mat formatToSquare(const cv::Mat& source)
  20. {
  21. int col = source.cols;
  22. int row = source.rows;
  23. int _max = MAX(col, row);
  24. cv::Mat result = cv::Mat::zeros(_max, _max, CV_8UC3);
  25. source.copyTo(result(cv::Rect(0, 0, col, row)));
  26. return result;
  27. }
  28. const int netWidth = 640; //ONNX图片输入宽度
  29. const int netHeight = 640; //ONNX图片输入高度
  30. float modelConfidenceThreshold{ 0.0 };
  31. float modelScoreThreshold{ 0.0 };
  32. float modelNMSThreshold{ 0.0 };
  33. std::vector<std::string> classes = { "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
  34. "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
  35. "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
  36. "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
  37. "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
  38. "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
  39. "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
  40. "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
  41. "hair drier", "toothbrush" };
  42. };
  43. class Yolov5 :public Yolo {
  44. public:
  45. vector<Detection> Detect(Mat& SrcImg, Net& net);
  46. private:
  47. float confidenceThreshold{ 0.25 };
  48. float nmsIoUThreshold{ 0.45 };
  49. };
  50. class Yolov7 :public Yolo {
  51. public:
  52. vector<Detection> Detect(Mat& SrcImg, Net& net);
  53. private:
  54. float confidenceThreshold{ 0.25 };
  55. float nmsIoUThreshold{ 0.45 };
  56. const int strideSize = 3; //stride size
  57. const float netStride[4] = { 8.0, 16.0, 32.0, 64.0 };
  58. const float netAnchors[3][6] = { {12, 16, 19, 36, 40, 28},{36, 75, 76, 55, 72, 146},{142, 110, 192, 243, 459, 401} }; //yolov7-P5 anchors
  59. };
  60. class Yolov8 :public Yolo {
  61. public:
  62. vector<Detection> Detect(Mat& SrcImg, Net& net);
  63. private:
  64. float confidenceThreshold{ 0.25 };
  65. float nmsIoUThreshold{ 0.70 };
  66. };

源文件yoloV8.cpp:

  1. #include"yoloV8.h"
  2. bool Yolo::readModel(Net& net, string& netPath, bool isCuda = false) {
  3. try {
  4. net = readNetFromONNX(netPath);
  5. }
  6. catch (const std::exception&) {
  7. return false;
  8. }
  9. if (isCuda) {
  10. net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
  11. net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
  12. }
  13. else {
  14. net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
  15. net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
  16. }
  17. return true;
  18. }
  19. void Yolo::drawPred(Mat& img, vector<Detection> result, vector<Scalar> colors) {
  20. for (int i = 0; i < result.size(); ++i)
  21. {
  22. Detection detection = result[i];
  23. cv::Rect box = detection.box;
  24. cv::Scalar color = colors[detection.class_id];
  25. // Detection box
  26. cv::rectangle(img, box, color, 2);
  27. // Detection box text
  28. std::string classString = classes[detection.class_id] + ' ' + std::to_string(detection.confidence).substr(0, 4);
  29. cv::Size textSize = cv::getTextSize(classString, cv::FONT_HERSHEY_DUPLEX, 1, 2, 0);
  30. cv::Rect textBox(box.x, box.y - 40, textSize.width + 10, textSize.height + 20);
  31. cv::rectangle(img, textBox, color, cv::FILLED);
  32. cv::putText(img, classString, cv::Point(box.x + 5, box.y - 10), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 0, 0), 2, 0);
  33. }
  34. }
  35. //vector<Detection> Yolov5::Detect(Mat& img, Net& net) {
  36. //
  37. // img = formatToSquare(img);
  38. // cv::Mat blob;
  39. // cv::dnn::blobFromImage(img, blob, 1.0 / 255.0, Size(netWidth, netHeight), cv::Scalar(), true, false);
  40. // net.setInput(blob);
  41. //
  42. // std::vector<cv::Mat> outputs;
  43. // net.forward(outputs, net.getUnconnectedOutLayersNames());
  44. //
  45. //
  46. //
  47. // float* pdata = (float*)outputs[0].data;
  48. // float x_factor = (float)img.cols / netWidth;
  49. // float y_factor = (float)img.rows / netHeight;
  50. //
  51. // std::vector<int> class_ids;
  52. // std::vector<float> confidences;
  53. // std::vector<cv::Rect> boxes;
  54. //
  55. // // yolov5 has an output of shape (batchSize, 25200, 85) (Num classes + box[x,y,w,h] + confidence[c])
  56. // int rows = outputs[0].size[1];
  57. // int dimensions = outputs[0].size[2];
  58. //
  59. // for (int i = 0; i < rows; ++i)
  60. // {
  61. // float confidence = pdata[4];
  62. // if (confidence >= modelConfidenceThreshold)
  63. // {
  64. //
  65. // cv::Mat scores(1, classes.size(), CV_32FC1, pdata + 5);
  66. // cv::Point class_id;
  67. // double max_class_score;
  68. //
  69. // minMaxLoc(scores, 0, &max_class_score, 0, &class_id);
  70. //
  71. // if (max_class_score > modelScoreThreshold)
  72. // {
  73. // confidences.push_back(confidence);
  74. // class_ids.push_back(class_id.x);
  75. //
  76. // float x = pdata[0];
  77. // float y = pdata[1];
  78. // float w = pdata[2];
  79. // float h = pdata[3];
  80. //
  81. // int left = int((x - 0.5 * w) * x_factor);
  82. // int top = int((y - 0.5 * h) * y_factor);
  83. //
  84. // int width = int(w * x_factor);
  85. // int height = int(h * y_factor);
  86. //
  87. // boxes.push_back(cv::Rect(left, top, width, height));
  88. // }
  89. // }
  90. // pdata += dimensions;
  91. // }
  92. //
  93. // vector<int> nms_result;
  94. // NMSBoxes(boxes, confidences, confidenceThreshold, nmsIoUThreshold, nms_result);
  95. // vector<Detection> detections{};
  96. // for (unsigned long i = 0; i < nms_result.size(); ++i) {
  97. // int idx = nms_result[i];
  98. // Detection result;
  99. // result.class_id = class_ids[idx];
  100. // result.confidence = confidences[idx];
  101. // result.box = boxes[idx];
  102. // detections.push_back(result);
  103. // }
  104. // return detections;
  105. //}
  106. //
  107. //vector<Detection> Yolov7::Detect(Mat& SrcImg, Net& net) {
  108. // Mat blob;
  109. // int col = SrcImg.cols;
  110. // int row = SrcImg.rows;
  111. // int maxLen = MAX(col, row);
  112. // Mat netInputImg = SrcImg.clone();
  113. // if (maxLen > 1.2 * col || maxLen > 1.2 * row) {
  114. // Mat resizeImg = Mat::zeros(maxLen, maxLen, CV_8UC3);
  115. // SrcImg.copyTo(resizeImg(Rect(0, 0, col, row)));
  116. // netInputImg = resizeImg;
  117. // }
  118. // vector<Ptr<Layer> > layer;
  119. // vector<string> layer_names;
  120. // layer_names = net.getLayerNames();
  121. // blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(0, 0, 0), true, false);
  122. // net.setInput(blob);
  123. // std::vector<cv::Mat> netOutput;
  124. // net.forward(netOutput, net.getUnconnectedOutLayersNames());
  125. //#if CV_VERSION_MAJOR==4 && CV_VERSION_MINOR>6
  126. // std::sort(netOutput.begin(), netOutput.end(), [](Mat& A, Mat& B) {return A.size[2] > B.size[2]; });//opencv 4.6 三个output顺序为40 20 80,之前版本的顺序为80 40 20
  127. //#endif
  128. // std::vector<int> class_ids;//结果id数组
  129. // std::vector<float> confidences;//结果每个id对应置信度数组
  130. // std::vector<cv::Rect> boxes;//每个id矩形框
  131. // float ratio_h = (float)netInputImg.rows / netHeight;
  132. // float ratio_w = (float)netInputImg.cols / netWidth;
  133. // int net_width = classes.size() + 5; //输出的网络宽度是类别数+5
  134. // for (int stride = 0; stride < strideSize; stride++) { //stride
  135. // float* pdata = (float*)netOutput[stride].data;
  136. // int grid_x = (int)(netWidth / netStride[stride]);
  137. // int grid_y = (int)(netHeight / netStride[stride]);
  138. // // cv::Mat tmp(grid_x * grid_y * 3, classes.size() + 5, CV_32FC1, pdata);
  139. // for (int anchor = 0; anchor < 3; anchor++) { //anchors
  140. // const float anchor_w = netAnchors[stride][anchor * 2];
  141. // const float anchor_h = netAnchors[stride][anchor * 2 + 1];
  142. // for (int i = 0; i < grid_y; i++) {
  143. // for (int j = 0; j < grid_x; j++) {
  144. // float confidence = sigmoid_x(pdata[4]); ;//获取每一行的box框中含有物体的概率
  145. // cv::Mat scores(1, classes.size(), CV_32FC1, pdata + 5);
  146. // Point classIdPoint;
  147. // double max_class_socre;
  148. // minMaxLoc(scores, 0, &max_class_socre, 0, &classIdPoint);
  149. // max_class_socre = sigmoid_x(max_class_socre);
  150. // if (max_class_socre * confidence >= confidenceThreshold) {
  151. // float x = (sigmoid_x(pdata[0]) * 2.f - 0.5f + j) * netStride[stride]; //x
  152. // float y = (sigmoid_x(pdata[1]) * 2.f - 0.5f + i) * netStride[stride]; //y
  153. // float w = powf(sigmoid_x(pdata[2]) * 2.f, 2.f) * anchor_w; //w
  154. // float h = powf(sigmoid_x(pdata[3]) * 2.f, 2.f) * anchor_h; //h
  155. // int left = (int)(x - 0.5 * w) * ratio_w + 0.5;
  156. // int top = (int)(y - 0.5 * h) * ratio_h + 0.5;
  157. // class_ids.push_back(classIdPoint.x);
  158. // confidences.push_back(max_class_socre * confidence);
  159. // boxes.push_back(Rect(left, top, int(w * ratio_w), int(h * ratio_h)));
  160. // }
  161. // pdata += net_width;//下一行
  162. // }
  163. // }
  164. // }
  165. // }
  166. //
  167. // //执行非最大抑制以消除具有较低置信度的冗余重叠框(NMS)
  168. // vector<int> nms_result;
  169. // NMSBoxes(boxes, confidences, confidenceThreshold, nmsIoUThreshold, nms_result);
  170. // vector<Detection> detections{};
  171. // for (unsigned long i = 0; i < nms_result.size(); ++i) {
  172. // int idx = nms_result[i];
  173. // Detection result;
  174. // result.class_id = class_ids[idx];
  175. // result.confidence = confidences[idx];
  176. // result.box = boxes[idx];
  177. // detections.push_back(result);
  178. // }
  179. // return detections;
  180. //}
  181. vector<Detection> Yolov8::Detect(Mat& modelInput, Net& net) {
  182. modelInput = formatToSquare(modelInput);
  183. cv::Mat blob;
  184. cv::dnn::blobFromImage(modelInput, blob, 1.0 / 255.0, Size(netWidth, netHeight), cv::Scalar(), true, false);
  185. net.setInput(blob);
  186. std::vector<cv::Mat> outputs;
  187. net.forward(outputs, net.getUnconnectedOutLayersNames());
  188. // yolov8 has an output of shape (batchSize, 84, 8400) (Num classes + box[x,y,w,h])
  189. int rows = outputs[0].size[2];
  190. int dimensions = outputs[0].size[1];
  191. outputs[0] = outputs[0].reshape(1, dimensions);
  192. cv::transpose(outputs[0], outputs[0]);
  193. float* data = (float*)outputs[0].data;
  194. // Mat detect_output(8400, 84, CV_32FC1, data);// 8400 = 80*80+40*40+20*20
  195. float x_factor = (float)modelInput.cols / netWidth;
  196. float y_factor = (float)modelInput.rows / netHeight;
  197. std::vector<int> class_ids;
  198. std::vector<float> confidences;
  199. std::vector<cv::Rect> boxes;
  200. for (int i = 0; i < rows; ++i)
  201. {
  202. cv::Mat scores(1, classes.size(), CV_32FC1, data + 4);
  203. cv::Point class_id;
  204. double maxClassScore;
  205. minMaxLoc(scores, 0, &maxClassScore, 0, &class_id);
  206. if (maxClassScore > modelConfidenceThreshold)
  207. {
  208. confidences.push_back(maxClassScore);
  209. class_ids.push_back(class_id.x);
  210. float x = data[0];
  211. float y = data[1];
  212. float w = data[2];
  213. float h = data[3];
  214. int left = int((x - 0.5 * w) * x_factor);
  215. int top = int((y - 0.5 * h) * y_factor);
  216. int width = int(w * x_factor);
  217. int height = int(h * y_factor);
  218. boxes.push_back(cv::Rect(left, top, width, height));
  219. }
  220. data += dimensions;
  221. }
  222. //执行非最大抑制以消除具有较低置信度的冗余重叠框(NMS)
  223. vector<int> nms_result;
  224. NMSBoxes(boxes, confidences, confidenceThreshold, nmsIoUThreshold, nms_result);
  225. vector<Detection> detections{};
  226. for (unsigned long i = 0; i < nms_result.size(); ++i) {
  227. int idx = nms_result[i];
  228. Detection result;
  229. result.class_id = class_ids[idx];
  230. result.confidence = confidences[idx];
  231. result.box = boxes[idx];
  232. detections.push_back(result);
  233. }
  234. return detections;
  235. }

main.CPP

  1. #include "yoloV8.h"
  2. #include <iostream>
  3. #include<opencv2//opencv.hpp>
  4. #include<math.h>
  5. #define USE_CUDA false //use opencv-cuda
  6. using namespace std;
  7. using namespace cv;
  8. using namespace dnn;
  9. int main()
  10. {
  11. string img_path = "./bus.jpg";
  12. string model_path3 = "./yolov8n.onnx";
  13. Mat img = imread(img_path);
  14. vector<Scalar> color;
  15. srand(time(0));
  16. for (int i = 0; i < 80; i++) {
  17. int b = rand() % 256;
  18. int g = rand() % 256;
  19. int r = rand() % 256;
  20. color.push_back(Scalar(b, g, r));
  21. }
  22. /*Yolov5 yolov5; Net net1;
  23. Mat img1 = img.clone();
  24. bool isOK = yolov5.readModel(net1, model_path1, USE_CUDA);
  25. if (isOK) {
  26. cout << "read net ok!" << endl;
  27. }
  28. else {
  29. cout << "read onnx model failed!";
  30. return -1;
  31. }
  32. vector<Detection> result1 = yolov5.Detect(img1, net1);
  33. yolov5.drawPred(img1, result1, color);
  34. Mat dst = img1({ 0, 0, img.cols, img.rows });
  35. imwrite("results/yolov5.jpg", dst);
  36. Yolov7 yolov7; Net net2;
  37. Mat img2 = img.clone();
  38. isOK = yolov7.readModel(net2, model_path2, USE_CUDA);
  39. if (isOK) {
  40. cout << "read net ok!" << endl;
  41. }
  42. else {
  43. cout << "read onnx model failed!";
  44. return -1;
  45. }
  46. vector<Detection> result2 = yolov7.Detect(img2, net2);
  47. yolov7.drawPred(img2, result2, color);
  48. dst = img2({ 0, 0, img.cols, img.rows });
  49. imwrite("results/yolov7.jpg", dst);*/
  50. Yolov8 yolov8; Net net3;
  51. Mat img3 = img.clone();
  52. bool isOK = yolov8.readModel(net3, model_path3, USE_CUDA);
  53. if (isOK) {
  54. cout << "read net ok!" << endl;
  55. }
  56. else {
  57. cout << "read onnx model failed!";
  58. return -1;
  59. }
  60. vector<Detection> result3 = yolov8.Detect(img3, net3);
  61. yolov8.drawPred(img3, result3, color);
  62. Mat dst = img3({ 0, 0, img.cols, img.rows });
  63. cv::imshow("aaa", dst);
  64. imwrite("./yolov8.jpg", dst);
  65. cv::waitKey(0);
  66. return 0;
  67. }

opencv编译需要时间久,GPU版本可以达到实时,有问题先尝试解决,搞定不了私信留言。

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

闽ICP备14008679号