yolov5.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include <iostream>
  2. #include <opencv2/opencv.hpp>
  3. #include <opencv2/dnn/dnn.hpp>
  4. #include <string>
  5. #include <vector>
  6. using cv::Mat;
  7. using std::cout;
  8. using std::endl;
  9. using std::string;
  10. using std::vector;
  11. static const vector<string> class_name = { "cat", "chicken", "cow", "dog", "fox", "goat", "horse", "person", "racoon", "skunk" };
  12. vector<vector<float>> get_info(const Mat& result, float conf = 0.7, int len_data = 15)
  13. {
  14. float* pdata = (float*)result.data;
  15. vector<vector<float>> info;
  16. for (int i = 0; i < result.total() / len_data; i++)
  17. {
  18. if (pdata[4] > conf)
  19. {
  20. vector<float> info_line;
  21. for (int j = 0; j < len_data; j++)
  22. {
  23. // cout << pdata[j] << " ";
  24. info_line.push_back(pdata[j]);
  25. }
  26. // cout << endl;
  27. info.push_back(info_line);
  28. }
  29. pdata += len_data;
  30. }
  31. return info;
  32. }
  33. void info_simplify(vector<vector<float>>& info)
  34. {
  35. for (auto i = 0; i < info.size(); i++)
  36. {
  37. info[i][5] = std::max_element(info[i].cbegin() + 5, info[i].cend()) - (info[i].cbegin() + 5);
  38. info[i].resize(6);
  39. float x = info[i][0];
  40. float y = info[i][1];
  41. float w = info[i][2];
  42. float h = info[i][3];
  43. info[i][0] = x - w / 2.0;
  44. info[i][1] = y - h / 2.0;
  45. info[i][2] = x + w / 2.0;
  46. info[i][3] = y + h / 2.0;
  47. }
  48. }
  49. vector<vector<vector<float>>> split_info(vector<vector<float>>& info)
  50. {
  51. vector<vector<vector<float>>> info_split;
  52. vector<int> class_id;
  53. for (auto i = 0; i < info.size(); i++)
  54. {
  55. if (std::find(class_id.begin(), class_id.end(), (int)info[i][5]) == class_id.end())
  56. {
  57. class_id.push_back((int)info[i][5]);
  58. vector<vector<float>> info_;
  59. info_split.push_back(info_);
  60. }
  61. info_split[std::find(class_id.begin(), class_id.end(), (int)info[i][5]) - class_id.begin()].push_back(info[i]);
  62. }
  63. return info_split;
  64. }
  65. void nms(vector<vector<float>>& info, float iou = 0.4)
  66. {
  67. int counter = 0;
  68. vector<vector<float>> return_info;
  69. while (counter < info.size())
  70. {
  71. return_info.clear();
  72. float x1 = 0;
  73. float x2 = 0;
  74. float y1 = 0;
  75. float y2 = 0;
  76. std::sort(info.begin(), info.end(), [](vector<float> p1, vector<float> p2)
  77. { return p1[4] > p2[4]; });
  78. for (auto i = 0; i < info.size(); i++)
  79. {
  80. if (i < counter)
  81. {
  82. return_info.push_back(info[i]);
  83. continue;
  84. }
  85. if (i == counter)
  86. {
  87. x1 = info[i][0];
  88. y1 = info[i][1];
  89. x2 = info[i][2];
  90. y2 = info[i][3];
  91. return_info.push_back(info[i]);
  92. continue;
  93. }
  94. if (info[i][0] > x2 or info[i][2] < x1 or info[i][1] > y2 or info[i][3] < y1)
  95. {
  96. return_info.push_back(info[i]);
  97. }
  98. else
  99. {
  100. float over_x1 = std::max(x1, info[i][0]);
  101. float over_y1 = std::max(y1, info[i][1]);
  102. float over_x2 = std::min(x2, info[i][2]);
  103. float over_y2 = std::min(y2, info[i][3]);
  104. float s_over = (over_x2 - over_x1) * (over_y2 - over_y1);
  105. float s_total = (x2 - x1) * (y2 - y1) + (info[i][0] - info[i][2]) * (info[i][1] - info[i][3]) - s_over;
  106. if (s_over / s_total < iou)
  107. {
  108. return_info.push_back(info[i]);
  109. }
  110. }
  111. }
  112. info = return_info;
  113. counter += 1;
  114. }
  115. }
  116. void draw_box(Mat& img, const vector<vector<float>>& info)
  117. {
  118. for (int i = 0; i < info.size(); i++)
  119. {
  120. cv::Point topLeft(info[i][0], info[i][1]);
  121. cv::Point bottomRight(info[i][2], info[i][3]);
  122. int thickness = 2;
  123. cv::Scalar color(0, 255, 0);
  124. int lineType = cv::LINE_8;
  125. const int cornerRadius = 5;
  126. cv::rectangle(img, topLeft, bottomRight, color, thickness, lineType);
  127. string label = class_name[static_cast<int>(info[i][5])] + " " + std::to_string(info[i][4]);
  128. cv::Size textSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.6, 1, nullptr);
  129. cv::Rect textBgRect(topLeft.x, topLeft.y - textSize.height - 5, textSize.width + 10, textSize.height + 5);
  130. cv::rectangle(img, textBgRect, color, cv::FILLED);
  131. cv::putText(img, label, cv::Point(topLeft.x + 5, topLeft.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.6, CV_RGB(255, 255, 255), 2);
  132. }
  133. }
  134. int main()
  135. {
  136. // Load the network and set the backend to CUDA
  137. cv::dnn::Net net = cv::dnn::readNetFromONNX("best.onnx");
  138. // Set the DNN backend to CUDA and target to CUDA
  139. net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
  140. net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
  141. Mat img = cv::imread("fox.jpg");
  142. cv::resize(img, img, cv::Size(640, 640));
  143. Mat blob = cv::dnn::blobFromImage(img, 1.0 / 255.0, cv::Size(640, 640), cv::Scalar(), true);
  144. net.setInput(blob);
  145. vector<Mat> netoutput;
  146. vector<string> out_name = { "output" };
  147. net.forward(netoutput, out_name);
  148. Mat result = netoutput[0];
  149. vector<vector<float>> info = get_info(result);
  150. info_simplify(info);
  151. vector<vector<vector<float>>> info_split = split_info(info);
  152. for (auto i = 0; i < info_split.size(); i++)
  153. {
  154. nms(info_split[i]);
  155. draw_box(img, info_split[i]);
  156. }
  157. cv::imshow("test", img);
  158. cv::waitKey(0);
  159. return 0;
  160. }