点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达

本文转载自:OpenCV学堂

YOLOv5在OpenVINO上的部署,网上有很多python版本的代码,但是基本都有个很内伤的问题,就是还在用pytorch的一些库做解析,C++的代码有个更大的内伤就是自定义解析解释的不是很清楚,所以本人阅读YOLOv5的pytorch代码推理部分,从原始的三个输出层解析实现了boxes, classes, nms等关键C++代码输出,实现了纯OpenVINO+OpenCV版本的YOLOv5s模型推理的代码演示。下面就是详细的系统环境与各个部分解释,以及代码实现与演示图像。

系统版本信息与依赖

  • Window 10 64bit

  • Pytorch1.7+CUDA10.0

  • Python3.8.5

  • VS2015

  • OpenVINO_2021.2.185

01

YOLOv5下载与测试运行

YOLOv5是第二个非官方的YOLO对象检测版本,也是第一个Pytorch实现的YOLO对象检测版本。Github地址如下:

https://github.com/ultralytics/yolov5

需要克隆到本地

git clone https://github.com/ultralytics/yolov5.git

然后运行

pip install -r requirements.txt

安装所有依赖。

最后运行一段视频或者图像完成测试

python detect.py --source D:\images\video\SungEun.avi --weights yolov5s.pt --conf 0.25

视频测试结果如下:

图像测试结果如下:

02

模型转换

模型转换主要是把原始的YOLOv5的pytorch模型文件转换为通用的开放模型格式ONNX与OpenVIN特有的文件格式IR(*.xml与*.bin)。

OpenVINO从2020R02以后版本开始支持直接读取ONNX格式文件,所以我们既可以通过脚本直接导出onnx格式文件,直接给OpenVINO调用,也可以对得到ONNX文件通过OpenVINO的模型转换脚本做进一步转换生成IR中间格式(*.bin文件与*.xml文件)。

导出ONNX格式文件的脚本

Pytorch的YOLOv5项目本身已经提供了转换脚本,命令行运行方式如下:

# export at 640x640 with batch size 1
python models/export.py --weights yolov5s.pt --img 640 --batch 1

然后生成的yolov5s.onnx文件就在同一目录下面。

ONNX转为为IR中间格式

把ONNX转换为IR中间格式,运行结果如下

03

OpenVINO SDK+YOLOv5s代码演示

上面我们已经成功转换为YOLOv5s模型IR,现在就可以基于最新的SDK来说完成调用解析与调用。

第一步:

初始Core对象,读取模型(加载ONNX格式或者IR格式均可以,亲测有效)

// 创建IE插件, 查询支持硬件设备
Core ie;
vector<string> availableDevices = ie.GetAvailableDevices();
for (int i = 0; i < availableDevices.size(); i++) {printf("supported device name : %s \n", availableDevices[i].c_str());
}//  加载检测模型
auto network = ie.ReadNetwork("D:/python/yolov5/yolov5s.xml", "D:/python/yolov5/yolov5s.bin");
// auto network = ie.ReadNetwork("D:/python/yolov5/yolov5s.onnx");

第二步:

设置输入与输出格式,YOLOv5s输入的图像被归一化到0~1之间,而且是RGB通道顺序,输入与输出格式设置数据为浮点数,这部分的代码如下:

// 设置输入格式
for (auto &item : input_info) {auto input_data = item.second;input_data->setPrecision(Precision::FP32);input_data->setLayout(Layout::NCHW);input_data->getPreProcess().setResizeAlgorithm(RESIZE_BILINEAR);input_data->getPreProcess().setColorFormat(ColorFormat::RGB);
}// 设置输出格式
for (auto &item : output_info) {auto output_data = item.second;output_data->setPrecision(Precision::FP32);
}
auto executable_network = ie.LoadNetwork(network, "CPU");

第三步:

设置输入图像数据并实现推理预测

int64 start = getTickCount();
/** Iterating over all input blobs **/
for (auto & item : input_info) {auto input_name = item.first;/** Getting input blob **/auto input = infer_request.GetBlob(input_name);size_t num_channels = input->getTensorDesc().getDims()[1];size_t h = input->getTensorDesc().getDims()[2];size_t w = input->getTensorDesc().getDims()[3];size_t image_size = h*w;Mat blob_image;resize(src, blob_image, Size(w, h));cvtColor(blob_image, blob_image, COLOR_BGR2RGB);// NCHWfloat* data = static_cast<float*>(input->buffer());for (size_t row = 0; row < h; row++) {for (size_t col = 0; col < w; col++) {for (size_t ch = 0; ch < num_channels; ch++) {data[image_size*ch + row*w + col] = float(blob_image.at<Vec3b>(row, col)[ch])/255.0;}}}
}// 执行预测
infer_request.Infer();

上面的代码跟SSD对象检测的OpenVINO调用基本上没有太大区别。主要的区别是在对推理完成结果的解析部分。

第四步:

解析输出结果,实现显示输出。要完成这个部分,首先需要看一下YOLOv5项目中的yolo.py中对推理部分的组装。首先输出层,从YOLOv3开始到YOLOv5,输出层都是3层,分别对应的降采样的倍数是32、16、8。

以输入640x640大小的图像为例,得到三个输出层大小应该分别是20、40、80。每个层上对应三个尺度的anchor,表示如下:

模型的预测是在20x20、40x40、80x80每个输出层的每个特征点上预测三个框,每个框预测分类!每个框的维度大小为 cx,cy,w,h,conf + number of class, 图示如下:

以YOLOv5项目的预训练模型是基于COCO的80个对象类别为例,在检测阶段最终三个输出层是:

1x3x20x20x85
1x3x40x40x85
1x3x80x80x85

我电脑上实际加载模型之后的三个输出层实现运行结果:

然后循环每个输出层,解析每个特征点对应的3个框与相关数据。由于在导出的时候ONNX格式文件时模型的推理得到的三个输出层原始结果,所以还需要对每个数据先完成sigmoid归一化,然后再计算相关值,这部分的代码实现我参考了项目中的yolo.py中的Detection部分,得到初始每个对象的检测框之后,采用OpenVINO中自带非最大抑制函数,完成非最大抑制,就得到了最终的预测框,然后绘制显示。所以最终的解析输出层部分的代码如下:

for (int i = 0; i < side_square; ++i) {for (int c = 0; c < out_c; c++) {int row = i / side_h;int col = i % side_h;int object_index = c*side_data_square + row*side_data_w + col*side_data;// 阈值过滤float conf = sigmoid_function(output_blob[object_index + 4]);if (conf < 0.25) {continue;}// 解析cx, cy, width, heightfloat x = (sigmoid_function(output_blob[object_index]) * 2 - 0.5 + col)*stride;float y = (sigmoid_function(output_blob[object_index + 1]) * 2 - 0.5 + row)*stride;float w = pow(sigmoid_function(output_blob[object_index + 2]) * 2, 2)*anchors[anchor_index + c * 2];float h = pow(sigmoid_function(output_blob[object_index + 3]) * 2, 2)*anchors[anchor_index + c * 2 + 1];float max_prob = -1;int class_index = -1;// 解析类别for (int d = 5; d < 85; d++) {float prob = sigmoid_function(output_blob[object_index + d]);if (prob > max_prob) {max_prob = prob;class_index = d - 5;}}// 转换为top-left, bottom-right坐标int x1 = saturate_cast<int>((x - w / 2) * scale_x);  // top left xint y1 = saturate_cast<int>((y - h / 2) * scale_y);  // top left yint x2 = saturate_cast<int>((x + w / 2) * scale_x);  // bottom right xint y2 = saturate_cast<int>((y + h / 2) * scale_y); // bottom right y// 解析输出classIds.push_back(class_index);confidences.push_back((float)conf);boxes.push_back(Rect(x1, y1, x2 - x1, y2 - y1));// rectangle(src, Rect(x1, y1, x2 - x1, y2 - y1), Scalar(255, 0, 255), 2, 8, 0);}
}

非最大抑制的代码如下:

vector<int> indices;
NMSBoxes(boxes, confidences, 0.25, 0.5, indices);
for (size_t i = 0; i < indices.size(); ++i)
{int idx = indices[i];Rect box = boxes[idx];rectangle(src, box, Scalar(140, 199, 0), 4, 8, 0);
}
float fps = getTickFrequency() / (getTickCount() - start);
float time = (getTickCount() - start) / getTickFrequency();

官方的两张测试图像,测试结果如下:

加速,OpenVINO+YOLOv5 真的可以在一起!(CORE i78th)。

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目31讲

在「小白学视觉」公众号后台回复:Python视觉实战项目31讲即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

下载4:leetcode算法开源书

在「小白学视觉」公众号后台回复:leetcode即可下载。每题都 runtime beats 100% 的开源好书,你值得拥有!


交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

YOLOv5在最新OpenVINO 2021R02版本的部署与代码演示详解相关推荐

  1. Ubuntu16.04下Mongodb官网安装部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 在这篇博客里,我采用了非官网的安装步骤,来进行安装.走了弯路,同时,也是不建议.因为在大数据领域和实际生产里,还是要走正规的为好. Ubuntu16.04下Mongodb(离线安 ...

  2. 阿里云linux centos 一键部署web环境--图文详解

    阿里云linux centos 一键部署web环境--图文详解 标签: linux阿里云一键部署 2017-04-15 12:28 386人阅读 评论(0) 收藏 举报  分类: linux(11)  ...

  3. Ubuntu14.04下Mongodb数据库可视化工具安装部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 前期博客 Ubuntu14.04下Mongodb(离线安装方式|非apt-get)安装部署步骤(图文详解)(博主推荐) Ubuntu14.04下Mongodb官网安装部署步骤(图 ...

  4. thinksns php7,centos 7 部署Thinksns的思路详解

    因为Thinksns是PHP项目,我们这里部署需要搭建Apache+mysql+php环境. 1.mysql的安装,这里使用yum安装可以解决很多依赖包的问题.由于centos 7 没有自带mysql ...

  5. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(一)概要和介绍

    前言 本文隶属于专栏<大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据技术体系 目录 Spark 3.2.0 ...

  6. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(二)背景和动机

    前言 本文隶属于专栏<大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据技术体系 目录 Spark 3.2.0 ...

  7. Ubuntu16.04下Mongodb官网卸载部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 前期博客 Ubuntu16.04下Mongodb官网安装部署步骤(图文详解)(博主推荐) https://docs.mongodb.com/manual/tutorial/ins ...

  8. 最新NVIDIA Ada Lovelace架构 和 RTX 40系列详解

    最新NVIDIA Ada Lovelace架构 和 RTX 40系列详解 Nvidia 的 Ada 架构和 GeForce RTX 40 系列显卡计划于 10 月 12 日开始到货,从 GeForce ...

  9. oracle导入导出版本规则,Oracle不同版本间的导入导出命令详解 - wangzhuoyan的专栏 - CSDN博......

    wangzhuoyan的专栏 明月松间照,清泉石上流 登录 注册 欢迎 退出 我的博客 配置 写文章 文章管理 博客首页   全站 当前博客  空间 博客 好友 相册 留言 用户操作 [发私信]  [ ...

最新文章

  1. (三)设置Jenkins为MLOps构建CI/CD管道
  2. 基于libpcan库can总线操作的Barrett 机械手控制及腕部六维力传感器驱动
  3. [转]在python中删除list中元素的3种方法:remove、pop、del
  4. lnmp部署 -----1
  5. web文件上传(三)--webapi后台接收参数和文件
  6. 倒计时_考研倒计时30天,拼了
  7. 修改linux文本模式下的分辨率
  8. K8s中原生配置中心探究
  9. 解决无法ping通 127.0.0.1
  10. 不同内核浏览器的差异以及浏览器渲染简介(转)
  11. Java 二维码及条形码处理
  12. Java性能优化从20s优化到500ms,我用了这三招,内容知识满满
  13. 竞品分析(淘宝、京东)
  14. 赛维安讯LiveCloud直播云服务介绍
  15. Dom对象和java
  16. 持续集成/持续部署(1)Git Gitlab
  17. CodeKK源码地址
  18. 库卡工业机器人负载曲线图_德国库卡机器人选型帮助(负载篇)
  19. 按键精灵 容器 html,按键精灵容器控件
  20. IBM小型机日常维护命令

热门文章

  1. “搞垮” 微博服务器?每天上亿条用户推送是如何做到的
  2. 7行Python代码,搭建可以识花的机器学习App|视频教程
  3. 大数据时代,谁的眼神锁定你?
  4. 双十一报名截止,决赛在即!AI Challenger2018极客峰会免费抢票!
  5. 今晚8点开播 | 深度解析知识图谱发展关键阶段技术脉络
  6. 利用RNN训练Seq2Seq已经成为过去,CNN才是未来?
  7. 新来的同事问我 where 1=1 是什么意思
  8. 线程池的一个BUG,被我发现了
  9. 大白话带你认识Kafka
  10. 机器学习中的L1与L2正则化图解!