# c++实现yolov5的OpenVINO部署
## 模型训练
### 1. 首先获取yolov5工程
```shell
git clone https://github.com/ultralytics/yolov5.git
```
本文编辑的时间是2020年12月3日,官方最新的releases是v3.1,在v3.0的版本中,官网有如下的声明
> * August 13, 2020**: [v3.0 release](https://github.com/ultralytics/yolov5/releases/tag/v3.0): nn.Hardswish() activations, data autodownload, native AMP.
yolov5训练获得的原始的模型以.pt文件方式存储,要转换为OpenVINO的.xml和.bin的模型存储方式,需要经历两次转换.
两次转换所用到的工具无法同时支持nn.Hardswish()函数的转换,v3.0版本时需要切换到v2.0版本替换掉nn.Hardswish()函数才能够完成两次模型转换,当时要完成模型转换非常的麻烦.
在v3.1版本的yolov5中用于进行pt模型转onnx模型的程序对nn.Hardswish()进行了兼容,模型转换过程大为化简.
后续实现基于v3.1版本.
### 2. 训练准备
yolov5官方的指南: https://github.com/ultralytics/yolov5/wiki/Train-Custom-Data
#### 描述信息准备
在yolov5的文件夹下/yolov5/models/目录下可以找到以下文件
> yolov5s.yaml
>
> yolov5m.yaml
>
> yolov5l.yaml
这三个文件分别对应s(小尺寸模型),m(中尺寸模型)和l(大尺寸模型)的结构描述信息
其中为了实现自己的训练常常需要更改以下两个参数
* nc
需要识别的类别数量,yolov5原始的默认类别数量为80
* anchors
通过kmeans等算法根据自己的数据集得出合适的锚框.
这里需要注意:yolov5内部实现了锚框的自动计算训练过程默认使用自适应锚框计算.
经过实际测试,自己通过kmeans算法得到的锚框在特定数据集上能取得更好的性能
在3.执行训练中将提到禁止自动锚框计算的方法.
#### 数据准备
参考官方指南的
* Create Labels
* Organize Directories
部分的数据要求
注意标注格式是class x_center y_center width height,其中x_center y_center width height均是根据图像尺寸归一化的0到1之间的数值.
### 3. 执行训练
```python
python ~/src_repo/yolov5/train.py --batch 16 --epochs 10 --data ~/src_repo/rat.yaml --cfg ~/src_repo/yolov5/models/yolov5s.yaml --weights ""
```
其中
* --data 参数后面需要填充的是训练数据的说明文件.其中需要说明训练集,测试集,种类数目和种类名称等信息,具体格式可以参考yolov5/data/coco.yaml.
* --cfg 为在训练准备阶段完成的模型结构描述文件.
* --weights 后面跟预训练模型的路径,如果是""则重新训练一个模型.推荐使用预训练模型继续训练,不使用该参数则默认使用预训练模型.
* --noautoanchor 该参数可选,使用该参数则禁止自适应anchor计算,使用--cfg文件中提供的原始锚框.
## 模型转换
经过训练,模型的原始存储格式为.pt格式,为了实现OpenVINO部署,需要首先转换为.onnx的存储格式,之后再转化为OpenVINO需要的.xml和.bin的存储格式.
### 1. pt格式转onnx格式
这一步的转换主要由yolov5/models/export.py脚本实现.
可以参考yolov5提供的简单教程:https://github.com/ultralytics/yolov5/issues/251
使用该教程中的方法可以获取onnx模型,但直接按照官方方式获取的onnx模型其中存在OpenVINO模型转换中不支持的运算,因此,使用该脚本之前需要进行一些更改:
* opset_version
在/yolov5/models/export.py中
```python
torch.onnx.export(model, img, f, verbose=False, opset_version=12, input_names=['images'],
output_names=['classes', 'boxes'] if y is None else ['output'])
```
opset_version=12,将导致后面的OpenVINO模型装换时遇到未支持的运算
因此设置为opset_version=10.
* Detect layer export
```python
model.model[-1].export = True
```
设置为True则Detect层(包含nms,锚框计算等)不会输出到模型中.
设置为False包含Detect层的模型无法通过onnx到OpenVINO格式模型的转换.
需要执行如下指令:
```shell
python ./models/export.py --weight .pt文件路径 --img 640 --batch 1
```
需要注意的是在填入的.pt文件路径不存在时,该程序会自动下载官方预训练的模型作为转换的原始模型,转换完成则获得onnx格式的模型.
转换完成后可以使用Netron:https://github.com/lutzroeder/netron.git 进行可视化.对于陌生的模型,该可视化工具对模型结构的认识有很大的帮助.
![net](https://github.com/fb029ed/yolov5_cpp_openvino/blob/master/img/net.png)
### 2. onnx格式转换OpenVINO的xml和bin格式
OpenVINO是一个功能丰富的跨平台边缘加速工具箱,本文用到了其中的模型优化工具和推理引擎两部分内容.
OpenVINO的安装配置可以参考https://docs.openvinotoolkit.org/2019_R2/_docs_install_guides_installing_openvino_linux.html ,本文的所有实现基于2020.4版本,为确保可用,建议下载2020.4版本的OpenVINO.
安装完成后在~/.bashrc文件中添加如下内容,用于在终端启动时配置环境变量.
```shell
source /opt/intel/openvino/bin/setupvars.sh
source /opt/intel/openvino/opencv/setupvars.sh
```
安装完成后运行如下脚本实现onnx模型到xml bin模型的转换.
```shell
python /opt/intel/openvino/deployment_tools/model_optimizer/mo_onnx.py --input_model .onnx文件路径 --output_dir 期望模型输出的路径
```
运行成功之后会获得.xml和.bin文件,xml和bin是OpenVINO中的模型存储方式,后续将基于bin和xml文件进行部署.该模型转换工具还有定点化等模型优化功能,有兴趣可以自己试试.
## 使用OpenVINO进行推理部署
OpenVINO除了模型优化工具外,还提供了一套运行时推理引擎.
想使用OpenVINO的模型进行推理部署,有两种方式,第一种方式是使用OpenVINO原生的sdk,另外一种方式是使用支持OpenVINO的opencv(比如OpenVINO自带的opencv)进行部署,本文对原生sdk的部署方式进行介绍.
OpenVINO提供了相对丰富的例程,本文中实现的yolov5的部署参考了/opt/intel/openvino/deployment_tools/inference_engine/demos/object_detection_demo_yolov3_async文件夹中yolov3的实现方式.
### 1. 推理引擎的初始化
首先需要进行推理引擎的初始化,此部分代码封装在detector.cpp的init函数.
主要流程如下:
```c++
Core ie;
//读入xml文件,该函数会在xml文件的目录下自动读取相应的bin文件,无需手动指定
auto cnnNetwork = ie.ReadNetwork(_xml_path);
//从模型中获取输入数据的格式信息
InputsDataMap inputInfo(cnnNetwork.getInputsInfo());
InputInfo::Ptr& input = inputInfo.begin()->second;
_input_name = inputInfo.begin()->first;
input->setPrecision(Precision::FP32);
input->getInputData()->setLayout(Layout::NCHW);
ICNNNetwork::InputShapes inputShapes = cnnNetwork.getInputShapes();
SizeVector& inSizeVector = inputShapes.begin()->second;
cnnNetwork.reshape(inputShapes);
//从模型中获取推断结果的格式
_outputinfo = OutputsDataMap(cnnNetwork.getOutputsInfo());
for (auto &output : _outputinfo) {
output.second->setPrecision(Precision::FP32);
}
//获取可执行网络,这里的CPU指的是推断运行的器件,可选的还有"GPU",这里的GPU指的是intel芯片内部的核显
//配置好核显所需的GPU运行环境,使用GPU模式进行的推理速度上有很大提升,这里先拿CPU部署后面会提到GPU环境的配置方式
_network = ie.LoadNetwork(cnnNetwork, "CPU");
```
### 2. 数据准备
为了适配网络的输入数据格式要求,需要对原始的opencv读取的Mat数据进行预处理.
* resize
最简单的方式是将输入图像直接resize到640*640尺寸,此种方式会造成部分物体失真变形,识别准确率会受到部分影响,简单起见,在demo代码里使用了该方式.
在竞赛代码中,为了追求正确率,图像缩放的时候需要按图像原始比例将图像的长或宽缩放到640.假设�
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
算法部署_使用Openvin+Cpp部署YOLOv5目标检测算法_附详细流程教程_优质算法部署项目实战.zip (24个子文件)
算法部署_使用Openvin+Cpp部署YOLOv5目标检测算法_附详细流程教程_优质算法部署项目实战
cvmart_competition
rat.yaml 124B
openvino_cpp_code
my_detector.cpp 10KB
cov.txt 1KB
docker.txt 3KB
my_detector.h 1KB
cmakelist.txt 3KB
ji.cpp 5KB
read_data.py 3KB
make_dataset.py 3KB
yolov5l.yaml 1KB
dock.py 653B
save_data.py 2KB
train.py 673B
demo
detector.cpp 6KB
CMakeLists.txt 1KB
res
yolov5s.xml 289KB
yolov5s.bin 28.46MB
bus.jpg 476KB
main.cpp 2KB
detector.h 1KB
img
output.png 17KB
result.png 837KB
net.png 69KB
README.md 15KB
共 24 条
- 1
资源评论
极智视界
- 粉丝: 2w+
- 资源: 1412
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功