U版YOLOV3用NCNN部署时的问题记录

项目场景:

现在将模型部署到嵌入式端,选择的是YOLOV3模型。训练代码使用的是U版的YOLOV3,由于各种原因,我选择直接由pytorch->onnx->ncnn进行部署。而不是直接darknet->ncnn。


问题描述:

  1. onnx转ncnn时,先是报错,什么Unsqueerze不支持之类的。
  2. 模型执行时,我惊讶的发现输出节点的维度不对。

原因分析:

  1. 对于问题1,很快就得到了答案,使用onnx-simplifer工具就可以搞定。原因是ncnn不支持一些冗余操作。
  2. 对于问题2,我的直觉就是在python端的tensor那些后处理上有问题,对于既定的网络层出问题的概率比较小。大概率就是YOLO层的forward结果导出的那些操作翻译成ncnn出问题了。后面我也是从这个思路上解决了问题。

解决方案:

问题1:onnx转ncnn报错

这里给出的方案是安装onnx-simplifer包,然后去冗余.

pip install onnx-simplifier
python -m onnxsim input.onnx input_sim.onnx

问题2:onnx转ncnn输出节点维度不对

  • 首先我们使用netron.app在线可视化转化后的模型结构
  • 分析一下后处理的地方。在下面这张图里面,红色框出的地方都有问题。这就是代码里面后处理的部分。主要就是体现在从Reshape开始维度就不对了,然后下面全错。
    模型结构问题

模型文件修改

  1. Reshape层,原来是0=6,即W=6,修改为 0=6 1=1200 2=1,W=6,H=1200,C=1 (这边注意上面改变了维度顺序)
  2. Crop层 原来是-23309=1,0 -23310=1,2 -23311=1,0 修改为 -23309=1,0 -23310=1,2 -23311=1,2 也就是我们是在CHW的排列下拆分W
  3. Concat层,上面三个concat 是在H上拼接,改成0=1,最后一个是在W上拼接,改成0=2
  4. MmeoryData 后面加一个维度,即加一个 2=1
  5. 其实我上面的1、4修改的维度操作都是瞎试的,都是改一下输出一下节点维度。

结论

  1. 对于网络结果的后处理需要格外小心,我是不知道怎么修改导出方式自动完成,只能手动修改。
  2. 后处理过程最好在C++端完成,这样应该不会出错。

猜你喜欢

转载自blog.csdn.net/qq_16952303/article/details/121106341