当前位置:   article > 正文

pt-onnx-ncnn转换的问题记录(接yolov5训练)_onnx含有gather、range、unsqueeze 转ncnn报错

onnx含有gather、range、unsqueeze 转ncnn报错

训练好模型后,对于如何部署模型,我很困惑。后面问了大佬,大佬让我尝试把训练得到的pt和pth文件转换成onnx,最后转为ncnn后,把ncnn部署在vs上。
提供一下大佬推荐的代码:
tx的ncnn有yolov5的部署教程和案例

和另一个大佬推荐的教程(这个我没试过,当时我已经换了另外的方法并且准备答辩了):
【通用目标检测微信小程序(以yolov5作为后端演示)-哔哩哔哩】

接下来附上我的转换过程及报错等:
很多转换代码参考这位大佬的众多文章:https://blog.csdn.net/nihate?type=blog
和他的代码:https://github.com/Tencent

1.网络模型转换

教程:http://t.csdn.cn/o3F0V
配置相应的网络模型,需要把网络模型yaml文件转换成py文件
打开convert_yaml2py.py(该代码用于把网络模型yaml文件转换成py文件:http://t.csdn.cn/SWv6O
在这里插入图片描述
choices = [‘yolov5s’, ‘yolov5l’, ‘yolov5m’, ‘yolov5x’]
修改成:choices = [ ‘yolov5l’]
运行convert_yaml2py.py,得到yolov5l.py文件:
在这里插入图片描述
在这里插入图片描述
检查opencv版本:

>>> import cv2 
>>> print( cv2.__version__ )
  • 1
  • 2

在这里插入图片描述

2.转onn

根据教程所写,创建My_YOLO函数,代码如教程中所示。
修改convert_onnx中的类型名,改成自己模型的名字:
在这里插入图片描述
把自己模型结构的py文件名称替换yolov5s,这里就是上面需要My_YOLO函数的原因:
在这里插入图片描述
换成:
在这里插入图片描述
修改一部分:
在这里插入图片描述
34行的default和 choices里面的模型名都改为自己的模型名,41行也要改模型名:
在这里插入图片描述
运行后报错:
在这里插入图片描述

Traceback (most recent call last):
  File "D:/PycharmProject/yolov5-dnn-cpp-python-main/convert-onnx/convert_onnx.py", line 57, in <module>
    if not operator.eq(a.shape, b.shape):
AttributeError: 'collections.OrderedDict' object has no attribute 'shape'
  • 1
  • 2
  • 3
  • 4

标记一下,然后Debug查看:
在这里插入图片描述
通过对比原作者用的pth文件加载出来的数据,其中 的OrderedDict有序字典就是要用的。
原作者的是已经排好的有序字典:
在这里插入图片描述
我的还包含有其他数据:
在这里插入图片描述
而有序字典是在‘model’中,所以把model提取出来另外赋值:
在这里插入图片描述
最终,加载模型这段代码如图:
在这里插入图片描述
成功:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.pt转pth:

打开代码后,先改模型名:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
运行后缺少models :
在这里插入图片描述

ModuleNotFoundError: No module named ‘models’

其实是没仔细看该代码的使用要求:
在这里插入图片描述
在yolov5的源代码(随意一个)主目录中新建py文件,复制代码进去:

import torch
from collections import OrderedDict
import pickle
import os

device = 'cuda' if torch.cuda.is_available() else 'cpu'

if __name__ == '__main__':
    choices = ['best']  #修改yolov5s为你自己模型的名字
    modelfile = choices[0] + '.pt'
    utl_model = torch.load(modelfile, map_location=device)
    print(utl_model)
    utl_param = utl_model['model'].model
    torch.save(utl_param.state_dict(), os.path.splitext(modelfile)[0] + '.pth')
    own_state = utl_param.state_dict()
    print(len(own_state))

    numpy_param = OrderedDict()
    for name in own_state:
        numpy_param[name] = own_state[name].data.cpu().numpy()
    print(len(numpy_param))
    with open(os.path.splitext(modelfile)[0] + '_numpy_param.pkl', 'wb') as fw:
        pickle.dump(numpy_param, fw)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这里插入图片描述
把要转化的也丢进主目录下,运行:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看另一个模型:
在这里插入图片描述
不用另外提取有序字典,用下面这一句就可:
在这里插入图片描述
成功:
在这里插入图片描述
在这里插入图片描述

4.安装ncnn和onnx-simplifier及简化onnx

ncnn 是一个为手机端极致优化的高性能神经网络前向计算框架。ncnn 从设计之初深刻考虑手机端的部署和使用。无第三方依赖,跨平台,手机端 cpu 的速度快于目前所有已知的开源框架。基于 ncnn,开发者能够将深度学习算法轻松移植到手机端高效执行,开发出人工智能 APP,将 AI 带到你的指尖。ncnn 目前已在腾讯多款应用中使用,如QQ,Qzone,微信,天天P图等。

在windows下编译ncnn前需要先下载编译protobuf-3.4.0,下载后解压,编译命令过程如下:

cd D:/protobuf-3.4.0   #cd <protobuf-root-dir>
mkdir build-2022      #建文件夹
cd build-2022
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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

编译protobuf-3.4.0前要先下载cmake
官网:https://cmake.org/download/
在这里插入图片描述
cmake下载:https://cmake.org/files/
安装教程:http://t.csdn.cn/I6VOc
安装后重启
在这里插入图片描述
在这里插入图片描述

报错:cmake:cl is not a full path and was not found in the PATH.

尝试解决(可跳过):

cmake -G "MinGW Makefiles" ../
  • 1

在这里插入图片描述
报错:CMake Error: Error: generator : MinGW Makefiles
安装MinGW并配置环境

后面去stackoverflow上面问了大佬关于“cmake:cl is not a full path and was not found in the PATH. ”的问题,发现是visual studio 编译器的路径没有放:
在这里插入图片描述
输入命令:nmake
在这里插入图片描述
输入命令:nmake install
在这里插入图片描述
在这里插入图片描述
编译成功后,后会产生build-2022文件夹以及该文件夹下的若干文件夹及文件:
在这里插入图片描述
在这里插入图片描述

5.编译ncnn

编译完后再编译ncnn,编译命令过程如下:

git clone https://github.com/Tencent/ncnn.git
cd ncnn
git submodule update --init         # 如果这一步一直更新不了的话,需要把cmake编译时候的-DNCNN_VULKAN设置为OFF,不然编译不通过
 
mkdir build && cd build
cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -DProtobuf_INCLUDE_DIR=D:/protobuf-3.4.0/build-2022/install/include -DProtobuf_LIBRARIES=D:/protobuf-3.4.0/build-2022/install/lib/libprotobuf.lib -DProtobuf_PROTOC_EXECUTABLE=D:/protobuf-3.4.0/build-2022/install/bin/protoc.exe -DNCNN_VULKAN=OFF ..
nmake
nmake install
(protobuf-root-dir 是刚才编译的protobuf的目录,根据自己的来修改。)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

开始编译:git clone https://github.com/Tencent/ncnn.git
在这里插入图片描述
失败,进入网站:https://codeload.github.com/Tencent/ncnn/zip/refs/heads/master
下载并解压,进入git cmd,输入命令:

cd D:\ncnn
git submodule update --init
  • 1
  • 2

在这里插入图片描述
问题:fatal: not a git repository (or any of the parent directories): .git
提示说没有.git这样一个目录,解决办法如下:git init
在这里插入图片描述
打开VS2019的X64命令行,进入ncnn根目录:

mkdir build-2022
cd build-2022
cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -DProtobuf_INCLUDE_DIR=D:/protobuf-3.4.0/build-2022/install/include -DProtobuf_LIBRARIES=D:/protobuf-3.4.0/build-2022/install/lib/libprotobuf.lib -DProtobuf_PROTOC_EXECUTABLE=D:/protobuf-3.4.0/build-2022/install/bin/protoc.exe -DNCNN_VULKAN=OFF ..
  • 1
  • 2
  • 3

在这里插入图片描述
在这里插入图片描述
指令:

nmake
nmake install
  • 1
  • 2

在ncnn/tools/onnx/路径下得到onnx2ncnn.cpp文件:
在这里插入图片描述
同时在ncnn/build/tools/onnx/目录下得到运行文件onnx2ncnn,如下图,运行这个onnx2ncnn文件就可以将onnx模型转化为ncnn模型了:
在这里插入图片描述
下载并安装opencv
官网:https://opencv.org/releases/
在这里插入图片描述
安装后放路径:
在这里插入图片描述
安装 onnx-simplifier

pip3 install onnx-simplifier
  • 1

在这里插入图片描述
在这里插入图片描述
报错:WARNING: You are using pip version 22.0.3; however, version 22.0.4 is available.
You should consider upgrading via the ‘D:\Anaconda\python.exe -m pip install --upgrade pip’ command.
原因:pip版本过低导致安装第三方库失败

python -m pip install --upgrade pip -i https://pypi.douban.com/simple
  • 1

在这里插入图片描述
在这里插入图片描述
将模型文件拖入浏览器页面即可显示。将文件拖入浏览器,可看到模型结构,网站:
https://netron.app/
在这里插入图片描述

先利用onnx-simplifier简化onnx模型:

下载了一个简化代码运行不成功,就直接在它的onnxsim文件夹里面新建了一个sim文件,把要简化的onnx模型放入onnxsim文件夹里,直接运行sim文件。加载onnx文件,simplify处理后重新保存,代码如下(我放了个资源包):

import onnx
from tables import leaf
from onnxsim import simplify

onnx_model = onnx.load('leaf.onnx')  #output_path:path + model_name + '.onnx'
model_simp, check = simplify(onnx_model)
assert check, "Simplified ONNX model could not be validated"
onnx.save(model_simp, 'leafsim.onnx')
print('finished exporting onnx')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述
在这里插入图片描述
对比一下简化前和简化后的模型:
在这里插入图片描述
在这里插入图片描述

6.onnx转ncnn

使用onnx2ncnn工具进行转换,进入 ncnn/build/tools/onnx 路径下再输入./onnx2ncnn 命令。 其中 model.onnx 是需要转为ncnn的简化后的 onnx 模型,model.param 和 model.bin 即为转为 ncnn 后输出的两个文件,注意这两个文件的顺序不能写反了!

cd D:\ncnn\build-2022\tools\onnx
onnx2ncnn C:/Users/priesty/Desktop/onnx2ncnn/bestsim.onnx C:/Users/priesty/Desktop/onnx2ncnn/bestsim.param C:/Users/priesty/Desktop/onnx2ncnn/bestsim.bin (命令错误) 
  • 1
  • 2

在这里插入图片描述
提示:Usage: onnx2ncnn [onnxpb] [ncnnparam] [ncnnbin]
用法:onnx2ncnn [onnxpb] [ncnnparam] [ncnnbin]

把要用的onnx文件复制到该目录中,然后:

onnx2ncnn [bestsim.onnx] [bestsim.param] [bestsim.bin]  (命令还是错误 )
  • 1

在这里插入图片描述
报错:
open failed [bestsim.onnx]
read_proto_from_binary failed

正确命令:onnx2ncnn bestsim.onnx bestsim.param bestsim.bin
在这里插入图片描述
搞定了

onnx2ncnn leafsim.onnx leafsim.param leafsim.bin
  • 1

在这里插入图片描述
在这里插入图片描述
其中param存放的是模型结构,可以理解为网络的配置文件,bin存放的是类似卷积这些op的权重文件,可以理解为网络的参数(各种权重)文件。

动态尺寸推理

最后 Reshape 层把输出grid数写死了,根据 ncnn Reshape 参数含义,把写死的数量改为 -1 便可以自适应
在这里插入图片描述
在这里插入图片描述
替换后用 ncnnoptimize 过一遍模型,ncnnoptimize 是优化整个网络模型,顺便转为 fp16 存储减小模型体积。ncnnoptimize 工具会自动将无用的 MemoryData 删除,并且自动将最终的 blob count 设置为合适的数量,所以前面步骤中不需要自己改 blob count。
进入 ncnn/build/tools 路径下再输入./ncnnoptimize 命令

ncnnoptimize /home/jiao/yolov5/yolov5s-best.param /home/jiao/yolov5/yolov5s-best.bin /home/jiao/yolov5/yolov5s-best-opt.param  /home/jiao/yolov5/yolov5s-best-opt.bin 0
  • 1

我把 bestsim.param和 bestsim.bin放入ncnn/build/tools文件中:
命令如下:ncnnoptimize bestsim.param bestsim.bin bestopt.param bestopt.bin
在这里插入图片描述
报错:usage: ncnnoptimize [inparam] [inbin] [outparam] [outbin] [flag] [cutstart] [cutend]
其中,flag指存储类型,0 代表 float32, 65535代表 float16。[inparam] [inbin] 是之前生成的文件,[outparam] [outbin] 是将要生成的文件
新命令:ncnnoptimize bestsim.param bestsim.bin bestopt.param bestopt.bin 0
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
优化前:
在这里插入图片描述
优化后:
在这里插入图片描述
另一个模型:

ncnnoptimize leafsim.param leafsim.bin leafopt.param leafopt.bin 0
  • 1

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/850171
推荐阅读
相关标签
  

闽ICP备14008679号