yolov8_seg.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include"yolov8_seg.h"
  2. //using namespace std;
  3. //using namespace cv;
  4. //using namespace cv::dnn;
  5. bool Yolov8Seg::ReadModel(cv::dnn::Net& net, std::string& netPath, bool isCuda = false) {
  6. try {
  7. if (!CheckModelPath(netPath))
  8. return false;
  9. net = cv::dnn::readNetFromONNX(netPath);
  10. #if CV_VERSION_MAJOR==4 &&CV_VERSION_MINOR<7
  11. std::cout << "Yolov8-seg Need OpenCV Version >=4.7.0" << std::endl;
  12. return false;
  13. #endif
  14. #if CV_VERSION_MAJOR==4 &&CV_VERSION_MINOR==7&&CV_VERSION_REVISION==0
  15. net.enableWinograd(false); //bug of opencv4.7.x in AVX only platform ,https://github.com/opencv/opencv/pull/23112 and https://github.com/opencv/opencv/issues/23080
  16. //net.enableWinograd(true); //If your CPU supports AVX2, you can set it true to speed up
  17. #endif
  18. }
  19. catch (const std::exception&) {
  20. return false;
  21. }
  22. if (isCuda) {
  23. //cuda
  24. net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
  25. net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); //or DNN_TARGET_CUDA_FP16
  26. }
  27. else {
  28. //cpu
  29. std::cout << "Inference device: CPU" << std::endl;
  30. net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
  31. net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
  32. }
  33. return true;
  34. }
  35. bool Yolov8Seg::Detect(cv::Mat& srcImg, cv::dnn::Net& net, std::vector<OutputParams>& output) {
  36. cv::Mat blob;
  37. output.clear();
  38. int col = srcImg.cols;
  39. int row = srcImg.rows;
  40. cv::Mat netInputImg;
  41. cv::Vec4d params;
  42. LetterBox(srcImg, netInputImg, params, cv::Size(_netWidth, _netHeight));
  43. cv::dnn::blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(_netWidth, _netHeight), cv::Scalar(0, 0, 0), true, false);
  44. //**************************************************************************************************************************************************/
  45. //如果在其他设置没有问题的情况下但是结果偏差很大,可以尝试下用下面两句语句
  46. // If there is no problem with other settings, but results are a lot different from Python-onnx , you can try to use the following two sentences
  47. //
  48. //$ cv::dnn::blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(_netWidth, _netHeight), cv::Scalar(104, 117, 123), true, false);
  49. //$ cv::dnn::blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(_netWidth, _netHeight), cv::Scalar(114, 114,114), true, false);
  50. //****************************************************************************************************************************************************/
  51. net.setInput(blob);
  52. std::vector<cv::Mat> net_output_img;
  53. std::vector<std::string> output_layer_names{ "output0","output1" };
  54. net.forward(net_output_img, output_layer_names); //get outputs
  55. std::vector<int> class_ids;// res-class_id
  56. std::vector<float> confidences;// res-conf
  57. std::vector<cv::Rect> boxes;// res-box
  58. std::vector<std::vector<float>> picked_proposals; //output0[:,:, 4 + _className.size():net_width]===> for mask
  59. cv::Mat output0 = cv::Mat(cv::Size(net_output_img[0].size[2], net_output_img[0].size[1]), CV_32F, (float*)net_output_img[0].data).t(); //[bs,116,8400]=>[bs,8400,116]
  60. int rows = output0.rows;
  61. int net_width = output0.cols;
  62. int socre_array_length = net_width - 4 - net_output_img[1].size[1];
  63. float* pdata = (float*)output0.data;
  64. for (int r = 0; r < rows; ++r) {
  65. cv::Mat scores(1, socre_array_length, CV_32FC1, pdata + 4);
  66. cv::Point classIdPoint;
  67. double max_class_socre;
  68. minMaxLoc(scores, 0, &max_class_socre, 0, &classIdPoint);
  69. max_class_socre = (float)max_class_socre;
  70. if (max_class_socre >= _classThreshold) {
  71. std::vector<float> temp_proto(pdata + 4 + socre_array_length, pdata + net_width);
  72. picked_proposals.push_back(temp_proto);
  73. //rect [x,y,w,h]
  74. float x = (pdata[0] - params[2]) / params[0];
  75. float y = (pdata[1] - params[3]) / params[1];
  76. float w = pdata[2] / params[0];
  77. float h = pdata[3] / params[1];
  78. int left = MAX(int(x - 0.5 * w + 0.5), 0);
  79. int top = MAX(int(y - 0.5 * h + 0.5), 0);
  80. class_ids.push_back(classIdPoint.x);
  81. confidences.push_back(max_class_socre);
  82. boxes.push_back(cv::Rect(left, top, int(w + 0.5), int(h + 0.5)));
  83. }
  84. pdata += net_width;//next line
  85. }
  86. //NMS
  87. std::vector<int> nms_result;
  88. cv::dnn::NMSBoxes(boxes, confidences, _classThreshold, _nmsThreshold, nms_result);
  89. std::vector<std::vector<float>> temp_mask_proposals;
  90. cv::Rect holeImgRect(0, 0, srcImg.cols, srcImg.rows);
  91. for (int i = 0; i < nms_result.size(); ++i) {
  92. int idx = nms_result[i];
  93. OutputParams result;
  94. result.id = class_ids[idx];
  95. result.confidence = confidences[idx];
  96. result.box = boxes[idx] & holeImgRect;
  97. if (result.box.area() < 1)
  98. continue;
  99. temp_mask_proposals.push_back(picked_proposals[idx]);
  100. output.push_back(result);
  101. }
  102. MaskParams mask_params;
  103. mask_params.params = params;
  104. mask_params.srcImgShape = srcImg.size();
  105. mask_params.netHeight = _netHeight;
  106. mask_params.netWidth = _netWidth;
  107. mask_params.maskThreshold = _maskThreshold;
  108. for (int i = 0; i < temp_mask_proposals.size(); ++i) {
  109. GetMask2(cv::Mat(temp_mask_proposals[i]).t(), net_output_img[1], output[i], mask_params);
  110. }
  111. //******************** ****************
  112. // 老版本的方案,如果上面在开启我注释的部分之后还一直报错,建议使用这个。
  113. //If the GetMask2() still reports errors , it is recommended to use GetMask().
  114. //cv::Mat mask_proposals;
  115. //for (int i = 0; i < temp_mask_proposals.size(); ++i) {
  116. // mask_proposals.push_back(cv::Mat(temp_mask_proposals[i]).t());
  117. //}
  118. //GetMask(mask_proposals, net_output_img[1], output, mask_params);
  119. //*****************************************************/
  120. if (output.size())
  121. return true;
  122. else
  123. return false;
  124. }