官网提供的yolov5代码中已经能实现pt转onnx,但为了在android端使用 需要将onnx转ncnn,由于yolov5的部分网络层并没有在ncnn代码库中封装,直接使用ncnn中的onnx2ncnn会存在一些不支持的问题。该博客就是借他人经验,将实现的过程重新整理了一遍。便于向我一样的新手在初次使用时快速上手。
实现步骤
1, 安装onnx-simplifier
1.1: pip install onnx-simplifier (具体该工具的作用自行百度)
1.2: python -m onnxsim ./yolov5.onnx ./yolo5-sim.onnx (简化转换得到的onnx)
2. ncnn代码库
2.1ncnn代码库的编译
// An highlighted block
git clone https://github.com/Tencent/ncnn.git
cd ncnn
mkdir build
cd build
cmake ..
make -j4
2.2 模型转换
// An highlighted block
cd tools/onnx
./onnx2ncnn your-yolov5s-path/yolov5-sim.onnx the-path-to-save/yolov5-sim.param the-path-to-save/yolov5-sim.bin
运行到该步骤时会出现下面的问题,问题出现的原因时下图中的split和crop网络层高在ncnn中没有定义的缘故,我们需要做的是将这个网络层消除:
// An highlighted block
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
3 ncnn格式模型修改
3.1 去掉不支持的网络层
打开转换得到的yolov5-sim.param文件
前几行的内容如下,我们需要删除的是标红的部分。
修改结果如下,其中180是由于之前的189网络层我们删除了10行,并用YoloV5Focus网络层代替,剩180个,而YoloV5Focus网络层中的images代表该层的输入,199代表输出名,这个可以根据我标红的位置填写。
3.2 修改网络的输出shape
当我们基于修改后的网络使用ncnn/examples/yolov5测试时发现图片中会出现一堆乱框,该情况下需要修改网络的输出部分
首先,在yolov5-sim.param中找到网络的输出接口:
图中绿框部分就是最终的网络输出层(由于网络层数设置的区别,不同的网络所在的位置不一样),该层中红框选中的部分就是网络的输出名(要保证yolov5.cpp中调用的输出名和网络的一致性,yolov5.cpp中的调用方式如下C代码)。在并保证输出名一致的情况下,修改黄色框中区域为0=-1,使得最终的输出shape不固定。结果见图