当前位置:   article > 正文

c++windows+yolov5-6.2+openvino模型部署超详细_yolov5-6.2模型转openvino

yolov5-6.2模型转openvino

自我记录:代码是根据自己的项目需求,进行了修改,主要是需要检测的图片非常大,目标小,所以对图片进行了分割再检测。下载完配置好环境之后可以直接跑。

我的环境是:windows+vs2019+openvino2022.2+opencv4.5.5+cmake3.14.0

步骤:

1、下载openvino,我用的版本是2022.2

官网网址:https://docs.openvino.ai/latest/index.html

 

 就是这个链接:https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit/download.html

 

 解压之前记得给电脑设置一下,启动长路径,很简单,教程在这儿:https://blog.csdn.net/weixin_46356818/article/details/121029550

 解压后,配置电脑系统变量,下面是我的:

 下面是代码:

h文件

  1. #pragma once
  2. #include <opencv2/dnn.hpp>
  3. #include <openvino/openvino.hpp>
  4. #include <opencv2/opencv.hpp>
  5. using namespace std;
  6. class YOLO_OPENVINO
  7. {
  8. public:
  9. YOLO_OPENVINO();
  10. ~YOLO_OPENVINO();
  11. public:
  12. struct Detection
  13. {
  14. int class_id;
  15. float confidence;
  16. cv::Rect box;
  17. };
  18. struct Resize
  19. {
  20. cv::Mat resized_image;
  21. int dw;
  22. int dh;
  23. };
  24. Resize resize_and_pad(cv::Mat& img, cv::Size new_shape);
  25. void yolov5_compiled(std::string xml_path, ov::CompiledModel &compiled_model);
  26. void yolov5_detector(ov::CompiledModel compiled_model, cv::Mat input_detect_img, cv::Mat output_detect_img, vector<cv::Rect>& nms_box);
  27. private:
  28. const float SCORE_THRESHOLD = 0.4;
  29. const float NMS_THRESHOLD = 0.4;
  30. const float CONFIDENCE_THRESHOLD = 0.4;
  31. vector<cv::Mat>images;//图像容器
  32. vector<cv::Rect> boxes;
  33. vector<int> class_ids;
  34. vector<float> confidences;
  35. vector<cv::Rect>output_box;
  36. Resize resize;
  37. };

cpp文件

  1. #include"yolo_openvino.h"
  2. YOLO_OPENVINO::YOLO_OPENVINO()
  3. {
  4. }
  5. YOLO_OPENVINO::~YOLO_OPENVINO()
  6. {
  7. }
  8. YOLO_OPENVINO::Resize YOLO_OPENVINO::resize_and_pad(cv::Mat& img, cv::Size new_shape)
  9. {
  10. float width = img.cols;
  11. float height = img.rows;
  12. float r = float(new_shape.width / max(width, height));
  13. int new_unpadW = int(round(width * r));
  14. int new_unpadH = int(round(height * r));
  15. cv::resize(img, resize.resized_image, cv::Size(new_unpadW, new_unpadH), 0, 0, cv::INTER_AREA);
  16. resize.dw = new_shape.width - new_unpadW;//w方向padding值
  17. resize.dh = new_shape.height - new_unpadH;//h方向padding值
  18. cv::Scalar color = cv::Scalar(100, 100, 100);
  19. cv::copyMakeBorder(resize.resized_image, resize.resized_image, 0, resize.dh, 0, resize.dw, cv::BORDER_CONSTANT, color);
  20. return resize;
  21. }
  22. void YOLO_OPENVINO::yolov5_compiled(std::string xml_path, ov::CompiledModel& compiled_model)
  23. {
  24. // Step 1. Initialize OpenVINO Runtime core
  25. ov::Core core;
  26. // Step 2. Read a model
  27. //std::shared_ptr<ov::Model> model = core.read_model("best.xml");
  28. std::shared_ptr<ov::Model> model = core.read_model(xml_path);
  29. // Step 4. Inizialize Preprocessing for the model 初始化模型的预处理
  30. ov::preprocess::PrePostProcessor ppp = ov::preprocess::PrePostProcessor(model);
  31. // Specify input image format 指定输入图像格式
  32. ppp.input().tensor().set_element_type(ov::element::u8).set_layout("NHWC").set_color_format(ov::preprocess::ColorFormat::BGR);
  33. // Specify preprocess pipeline to input image without resizing 指定输入图像的预处理管道而不调整大小
  34. ppp.input().preprocess().convert_element_type(ov::element::f32).convert_color(ov::preprocess::ColorFormat::RGB).scale({ 255., 255., 255. });
  35. // Specify model's input layout 指定模型的输入布局
  36. ppp.input().model().set_layout("NCHW");
  37. // Specify output results format 指定输出结果格式
  38. ppp.output().tensor().set_element_type(ov::element::f32);
  39. // Embed above steps in the graph 在图形中嵌入以上步骤
  40. model = ppp.build();
  41. compiled_model = core.compile_model(model, "CPU");
  42. }
  43. void YOLO_OPENVINO::yolov5_detector(ov::CompiledModel compiled_model, cv::Mat input_detect_img, cv::Mat output_detect_img, vector<cv::Rect>& nms_box)
  44. {
  45. // Step 3. Read input image
  46. cv::Mat img = input_detect_img.clone();
  47. int img_height = img.rows;
  48. int img_width = img.cols;
  49. if (img_height < 5000 && img_width < 5000)
  50. {
  51. images.push_back(img);
  52. }
  53. else
  54. {
  55. images.push_back(img(cv::Range(0, 0.6 * img_height), cv::Range(0, 0.6 * img_width)));
  56. images.push_back(img(cv::Range(0, 0.6 * img_height), cv::Range(0.4 * img_width, img_width)));
  57. images.push_back(img(cv::Range(0.4 * img_height, img_height), cv::Range(0, 0.6 * img_width)));
  58. images.push_back(img(cv::Range(0.4 * img_height, img_height), cv::Range(0.4 * img_width, img_width)));
  59. }
  60. for (int m = 0; m < images.size(); m++)
  61. {
  62. // resize image
  63. Resize res = resize_and_pad(images[m], cv::Size(1280, 1280));
  64. // Step 5. Create tensor from image
  65. float* input_data = (float*)res.resized_image.data;//缩放后图像数据
  66. ov::Tensor input_tensor = ov::Tensor(compiled_model.input().get_element_type(), compiled_model.input().get_shape(), input_data);
  67. // Step 6. Create an infer request for model inference
  68. ov::InferRequest infer_request = compiled_model.create_infer_request();
  69. infer_request.set_input_tensor(input_tensor);
  70. infer_request.infer();
  71. //Step 7. Retrieve inference results
  72. const ov::Tensor& output_tensor = infer_request.get_output_tensor();
  73. ov::Shape output_shape = output_tensor.get_shape();
  74. float* detections = output_tensor.data<float>();
  75. for (int i = 0; i < output_shape[1]; i++)//遍历所有框
  76. {
  77. float* detection = &detections[i * output_shape[2]];//bbox(x y w h obj cls)
  78. float confidence = detection[4];//当前bbox的obj
  79. if (confidence >= CONFIDENCE_THRESHOLD) //判断是否为前景
  80. {
  81. float* classes_scores = &detection[5];
  82. cv::Mat scores(1, output_shape[2] - 5, CV_32FC1, classes_scores);
  83. cv::Point class_id;
  84. double max_class_score;
  85. cv::minMaxLoc(scores, 0, &max_class_score, 0, &class_id);//返回最大得分和最大类别
  86. if (max_class_score > SCORE_THRESHOLD)//满足得分
  87. {
  88. confidences.push_back(confidence);
  89. class_ids.push_back(class_id.x);
  90. float x = detection[0];//框中心x
  91. float y = detection[1];//框中心y
  92. float w = detection[2];//49
  93. float h = detection[3];//50
  94. float rx = (float)images[m].cols / (float)(res.resized_image.cols - res.dw);//x方向映射比例
  95. float ry = (float)images[m].rows / (float)(res.resized_image.rows - res.dh);//y方向映射比例
  96. x = rx * x;
  97. y = ry * y;
  98. w = rx * w;
  99. h = ry * h;
  100. if (m == 0)
  101. {
  102. x = x;
  103. y = y;
  104. }
  105. else if (m == 1)
  106. {
  107. x = x + 0.4 * img_width;
  108. y = y;
  109. }
  110. else if (m == 2)
  111. {
  112. x = x;
  113. y = y + 0.4 * img_height;
  114. }
  115. else if (m == 3)
  116. {
  117. x = x + 0.4 * img_width;
  118. y = y + 0.4 * img_height;
  119. }
  120. float xmin = x - (w / 2);//bbox左上角x
  121. float ymin = y - (h / 2);//bbox左上角y
  122. boxes.push_back(cv::Rect(xmin, ymin, w, h));
  123. }
  124. }
  125. }
  126. }
  127. std::vector<int> nms_result;
  128. cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, nms_result);
  129. std::vector<Detection> output;
  130. for (int i = 0; i < nms_result.size(); i++)
  131. {
  132. Detection result;
  133. int idx = nms_result[i];
  134. result.class_id = class_ids[idx];
  135. result.confidence = confidences[idx];
  136. result.box = boxes[idx];
  137. nms_box.push_back(result.box);//传给Qt NMS后的box
  138. output.push_back(result);
  139. }
  140. // Step 9. Print results and save Figure with detections
  141. for (int i = 0; i < output.size(); i++)
  142. {
  143. auto detection = output[i];
  144. auto box = detection.box;
  145. auto classId = detection.class_id;
  146. auto confidence = detection.confidence;
  147. /*cout << "Bbox" << i + 1 << ": Class: " << classId << " "
  148. << "Confidence: " << confidence << " Scaled coords: [ "
  149. << "cx: " << (float)(box.x + (box.width / 2)) / img.cols << ", "
  150. << "cy: " << (float)(box.y + (box.height / 2)) / img.rows << ", "
  151. << "w: " << (float)box.width / img.cols << ", "
  152. << "h: " << (float)box.height / img.rows << " ]" << endl;*/
  153. float xmax = box.x + box.width;
  154. float ymax = box.y + box.height;
  155. cv::rectangle(img, cv::Point(box.x, box.y), cv::Point(xmax, ymax), cv::Scalar(0, 255, 0), 3);
  156. cv::rectangle(img, cv::Point(box.x, box.y - 20), cv::Point(xmax, box.y), cv::Scalar(0, 255, 0), cv::FILLED);
  157. cv::putText(img, std::to_string(classId), cv::Point(box.x, box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
  158. img.copyTo(output_detect_img);
  159. }
  160. cv::imwrite("./fz.jpg", output_detect_img);
  161. }

main.cpp

  1. #include"yolo_openvino.h"
  2. using namespace std;
  3. YOLO_OPENVINO yolo_openvino;
  4. std::string path = "./best.xml";
  5. ov::CompiledModel model;
  6. cv::Mat input_img, output_img;
  7. vector<cv::Rect>output_box;
  8. int main()
  9. {
  10. input_img = cv::imread("140_0_0.jpg");
  11. yolo_openvino.yolov5_compiled(path, model);
  12. yolo_openvino.yolov5_detector(model, input_img, output_img, output_box);
  13. /* for (int i = 0; i < output_box.size(); i++)
  14. {
  15. cv::rectangle(input_img, cv::Point(output_box[i].x, output_box[i].y), cv::Point(output_box[i].x + output_box[i].width, output_box[i].y + output_box[i].height), cv::Scalar(0, 255, 0), 3);
  16. }
  17. cv::imshow("a", input_img);
  18. cv::waitKey(0)*/;
  19. return 0;
  20. }

接下来配置项目的包含目录、库目录、附加依赖项

 2、下载cmake3.14.0

这个下完之后解压,然后配置个环境变量就行,不下cmake应该也是可以的。

 

 3、跑代码:

放一个onnx转xml、bin文件的方法,现在可以直接从Yolov5中用export_openvino直接导出,其导出函数定义为:

  1. def export_openvino(model, im, file, prefix=colorstr('OpenVINO:')):
  2. # YOLOv5 OpenVINO export
  3. try:
  4. check_requirements(('openvino-dev',)) # requires openvino-dev: https://pypi.org/project/openvino-dev/
  5. import openvino.inference_engine as ie
  6. LOGGER.info(f'\n{prefix} starting export with openvino {ie.__version__}...')
  7. f = str(file).replace('.pt', '_openvino_model' + os.sep)
  8. cmd = f"mo --input_model {file.with_suffix('.onnx')} --output_dir {f}"
  9. subprocess.check_output(cmd, shell=True)
  10. LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')
  11. except Exception as e:
  12. LOGGER.info(f'\n{prefix} export failure: {e}')

所以只需要在yolov5里面运行下面命令:

“mo --input_model {file.with_suffix('.onnx')} --output_dir {f}”

///然后代码里的模型路径改成你自己的,就可以跑了。

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

闽ICP备14008679号