yolov5 6.0版本->onnx->ncnn +安卓部署 附加ncnn环境配置 保姆级详细教程

目标检测:yolov5 6.0版本 ncnn环境安装 至 +安卓部署 一条龙教程


背景

题主在模型部署时踩坑颇多,也看到yolov5 部署的参考资料不多,故本小萌新将自己踩坑的过程记录下来,也方便大家参考。yolov5->pt->onnx->ncnn float16位量化


一、准备阶段

1.参考文章

1.YoloV5官方github
YoloV5官方TFLite, ONNX, CoreML, TensorRT 的Export实现

2.nihui(ncnn作者)写的文章,感谢nihui大佬赏饭吃
ncnn github地址
ncnn-android-yolov5 github地址
详细记录u版YOLOv5目标检测ncnn实现
详细记录u版YOLOv5目标检测ncnn实现(PNNX版)

3.我踩坑时的参考文章
windows下最新yolov5转ncnn教程
YOLOv5转NCNN过程
yolov5 转onnx转ncnn
基本都是21年的文章,有些步骤现在其实不用了,大家可以参考参考

4.Linux下ncnn部署流程 –可参考
ncnn编译部署(Linux)

#2.流程

1.准备训练好的模型,建议先用官方的yolov5.pt模型自己整流程走一遍,再替换为自己的模型结构。Yolov5官方pt模型链接(链接为6.1版本)
2.pt模型->onnx
3.Windows下ncnn环境配置教程详解
4.onnx->ncnn
5.ncnn的安卓部署

二、pt模型->onnx

github上下载yolov5工程,按照 yolov5 README 指引,调用detect.py看下模型有没有问题。准备就绪后调用export.py进行模型转换
我使用的是yolov5-6.1工程,将yolov5s.pt复制到文件目录下

python export.py --weights yolov5s.pt --include onnx  --img 640 --train --simplify

6.1版本已经集成好了,很方便
添加–include 是指定导出类型为 torchscript/onnx ,读者按需转换即可。
添加–train 是为了去除后处理,即不直接输出一个分类结果output,而将3个特征图的作为输出。
添加–simplify 是为了简化模型,不需要像其他帖子一样单独进行onnxsim简化,省事。
如果是修改自己的模型 记得 --data xxx.yaml
最后得到文件

扫描二维码关注公众号,回复: 15931580 查看本文章
yolov5s.onnx

三、Windows下ncnn环境配置教程详解

最初我是学习nihui写的pnnx版yolo部署,失败了
后面再尝试onnx的过程中,发现很多参考资料和教程都没有加入ncnn环境部署部分。大多都直接讲 ncnn-android-yolov5 的安卓部署。
实际上对萌新来说(起码我是),跟着B站教程和资料时进行不下去了,这是因为它们分享onnx模型转ncnn模型经验的时候断档了,忽略了ncnn配置环节。

1.参考

文章:ncnn环境配置
这参考文章对我帮助不小,感谢作者。在这里我搬过来,侵删

准备项:VS、 cmake、 protobuf
讲道理,这3个的版本应该没关系,我觉得可以用最新版 [狗头]

2.VS安装

我用的是19版,19和22在这项目上应该差别不大。
下载地址: https://visualstudio.microsoft.com/zh-hans/vs/

下载VS后安装下面3个工作负荷
在这里插入图片描述
已经有VS的读者补充工具负荷即可:工具->获取工具和功能
在这里插入图片描述

3.cmake安装

我本身有cmake 所以当时是跳过的,此处是参考其他文章

cmake-3.16下载地址: 提取码: zme6
cmake需要变更环境变量
将解压后cmake-3.16.5-win64-x64文件夹点开进入bin将该路径添加至环境变量,
如路径为:D:\software\cmake-3.16.5-win64-x64\bin

4.protobuf安装

protobuf-3.4.0下载地址: 提取码: hd3z
下载后解压,然后打开vs2019的x64命令提示
在这里插入图片描述

在这里插入图片描述
跳转到刚解压的protobuf的根目录,然后创建build-vs2019的文件并进行cmake操作
注:protobuf-root-dir为protobuf的下载位置

> cd <protobuf-root-dir>
> mkdir build-vs2019
> cd build-vs2019
> cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF ../cmake
> nmake
> nmake install

成功后会在 .\protobuf\build-vs2019 下生成若干文件
在这里插入图片描述

5.ncnn编译

github上直接下载项目,并解压
ncnn github地址

接下来我们使用vs2019的x64命令,与protobuf的安装类似,我们按下述代码操作,

> cd <ncnn-root-dir>
> mkdir -p build-vs2019
> cd build-vs2019
> cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -DProtobuf_INCLUDE_DIR=<protobuf-root-dir>/build-vs2019/install/include -DProtobuf_LIBRARIES=<protobuf-root-dir>/build-vs2019/install/lib/libprotobuf.lib -DProtobuf_PROTOC_EXECUTABLE=<protobuf-root-dir>/build-vs2019/install/bin/protoc.exe -DNCNN_VULKAN=OFF ..
> nmake
> nmake install

注: ncnn-root-dir 为你的ncnn下载位置,而第四条命令cmake 里面所有(3个)的 protobuf-root-dir 都换成读者自己的protobuf路径 ,注意是绝对路径

成功后会在 .\nuxnn\build-vs2019 下生成若干文件
其中tools文件夹是我们最常用到的,里面的工具基本都集成好了
install中也包含有常用的lib、bin、include等库
在这里插入图片描述

四、onnx->ncnn

第二章 我们得到了 yolov5s.onnx
第三章配置好了 ncnn环境
这章我们进行模型转换

1.ncnn转换

下一步是还是用到vs2019的x64命令行,cd到 .\ncnn\build-vs2019\tools\onnx
会有onnx2ncnn.exe 应用程序,我们将yolov5s.onnx复制到目录下,然后输入

.\onnx2ncnn yolov5s.onnx yolov5s.param yolov5s.bin

此时我们 完成ncnn 转换,得到yolov5s.param和yolov5s.bin。
题主所用的模型为6.0版本前的yolov5s.pt模型,而ncnn不支持focus结构,因此需要手工修复下focus模块。
但6.0版后官方去掉了focus,建议大家检查下是否使用6.0版本的的pt模型,Yolov5官方pt模型链接(链接为6.1版本)

使用6.0版本以上的读者即可跳转至第五章,6.0版本以下的读者我们继续处理focus结构的报错问题:
同时报错很多 Unsupported slice step,这是focus模块转换的报错

Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !

如果报下面的错误的话 ,是不是你没模型导出时没–simpliffy呢?

Unsupported slice step !
Unsupported slice step !
...  ....
Unsupported slice step !
Unsupported slice step !
Shape not supported yet

2.param解释

我们先来一起分析一下NCNN的param文件,举例如下:

  7767517   # 文件头 魔数
  75 83     # 层数量  输入输出blob数量
            # 下面有75行
  Input            data             0 1 data 0=227 1=227 2=3
  Convolution      conv1            1 1 data conv1 0=64 1=3 2=1 3=2 4=0 5=1 6=1728
  ReLU             relu_conv1       1 1 conv1 conv1_relu_conv1 0=0.000000
  Pooling          pool1            1 1 conv1_relu_conv1 pool1 0=0 1=3 2=2 3=0 4=0
  Convolution      fire2/squeeze1x1 1 1 pool1 fire2/squeeze1x1 0=16 1=1 2=1 3=1 4=0 5=1 6=1024
  ...
  层类型            层名字   输入blob数量 输出blob数量  输入blob名字 输出blob名字   参数字典
  
  参数字典,每一层的意义不一样:
  数据输入层 Input            data             0 1 data 0=227 1=227 2=3   图像宽度×图像高度×通道数量
  卷积层    Convolution  ...   0=64     1=3      2=1    3=2     4=0    5=1    6=1728           
           0输出通道数 num_output() ; 1卷积核尺寸 kernel_size();  2空洞卷积参数 dilation(); 3卷积步长 stride(); 
           4卷积填充pad_size();       5卷积偏置有无bias_term();   6卷积核参数数量 weight_blob.data_size();
                                                              C_OUT * C_in * W_h * W_w = 64*3*3*3 = 1728
  池化层    Pooling      0=0       1=3       2=2        3=0       4=0
                      0池化方式:最大值、均值、随机     1池化核大小 kernel_size();     2池化核步长 stride(); 
                      3池化核填充 pad();   4是否为全局池化 global_pooling();
  激活层    ReLU       0=0.000000     下限阈值 negative_slope();
           ReLU6      0=0.000000     1=6.000000 上下限
  
  综合示例:
  0=1 1=2.5 -23303=2,2.0,3.0
  
  数组关键字 : -23300 
  -(-23303) - 23300 = 3 表示该参数在参数数组中的index
  后面的第一个参数表示数组元素数量,2表示包含两个元素

3.实现focus模块

ncnn转换后我们得到yolov5s.param和yolov5s.bin
记事本方式打开yolov5s.param
在这里插入图片描述

修改Split到Concat这10层,使用ncnn定义的YoloV5Focus层来替换这10层。
YoloV5Focus层的输入层顺接上一层的输出(橙色框),输出层顺接下一层的输入(蓝色框)。

param 开头第二行,layer_count 要对应修改,但 blob_count 只需确保大于等于实际数量即可。1层替换了10层,因此改为 185-10+1=176

一定要记得改这个,这里卡了我好久,当时很纳闷为什么App总是闪退。

然后,拖动到最后输出层,更改reshape的参数,将检测框修改为动态检测框。
在这里插入图片描述

OK,我们保存yolov5s.param后, 此时的yolov5s.param和yolov5s.bin已经可以正常使用了.

得到的bin和param根据自己需求部署到Linux/win/android/ios,如果需要部署到安卓端继续看

五、ncnn的安卓部署

nihui的教程已经写得很明白了,我们按步骤操作就好了。nihui YYDS!
ncnn-android-yolov5 github地址

此外建议大家使用Netron查看我们的模型

OK进入正题,假设读者已经安装好Android Studio,部署好了也用了nihui大佬的工程,测试能用没问题。我们下一步是将自己的模型替换到app上

1.模型替换

将第四章生成的bin和param放到

工程的所在目录下如 F:\ncnn-android-yolov5\app\src\main\assets

cpp处修改param和bin的名称,与你的自己的相对应

在这里插入图片描述

用Netron查看模型结构,然后修改input(1处)和output(3处)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

更改模型类别

最后如果你使用的是自己训练的模型,需要修改cpp下方的static const char* class_names[] ,更改为自己模型的类别。
最后可以对模型进行量化,精度不会下降多少,内存缩小了一半
cd 到ncnn的目录中 用命令器运行,与onnx转化ncnn的步骤相似

ncnnoptimize yolov5s.param yolov5s.bin yolov5s-opt.param yolov5s-opt.bin 65536

Done,Enjoy it boy!

猜你喜欢

转载自blog.csdn.net/CSDNXXXR/article/details/125502127