pt-onnx-ncnn转换的问题记录(接yolov5训练)

训练好模型后,对于如何部署模型,我很困惑。后面问了大佬,大佬让我尝试把训练得到的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)
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第1张图片
choices = [‘yolov5s’, ‘yolov5l’, ‘yolov5m’, ‘yolov5x’]
修改成:choices = [ ‘yolov5l’]
运行convert_yaml2py.py,得到yolov5l.py文件:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第2张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第3张图片
检查opencv版本:

>>> import cv2 
>>> print( cv2.__version__ )

pt-onnx-ncnn转换的问题记录(接yolov5训练)_第4张图片

2.转onn

根据教程所写,创建My_YOLO函数,代码如教程中所示。
修改convert_onnx中的类型名,改成自己模型的名字:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第5张图片
把自己模型结构的py文件名称替换yolov5s,这里就是上面需要My_YOLO函数的原因:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第6张图片
换成:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第7张图片
修改一部分:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第8张图片
34行的default和 choices里面的模型名都改为自己的模型名,41行也要改模型名:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第9张图片
运行后报错:
在这里插入图片描述

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'

标记一下,然后Debug查看:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第10张图片
通过对比原作者用的pth文件加载出来的数据,其中 的OrderedDict有序字典就是要用的。
原作者的是已经排好的有序字典:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第11张图片
我的还包含有其他数据:
在这里插入图片描述
而有序字典是在‘model’中,所以把model提取出来另外赋值:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第12张图片
最终,加载模型这段代码如图:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第13张图片
成功:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第14张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第15张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第16张图片

3.pt转pth:

打开代码后,先改模型名:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第17张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第18张图片
在这里插入图片描述
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第19张图片
运行后缺少models :
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第20张图片

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)

在这里插入图片描述
把要转化的也丢进主目录下,运行:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第21张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第22张图片
在这里插入图片描述
查看另一个模型:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第23张图片
不用另外提取有序字典,用下面这一句就可:
在这里插入图片描述
成功:
在这里插入图片描述
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第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

编译protobuf-3.4.0前要先下载cmake
官网:https://cmake.org/download/
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第25张图片
cmake下载:https://cmake.org/files/
安装教程:http://t.csdn.cn/I6VOc
安装后重启
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第26张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第27张图片

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

尝试解决(可跳过):

cmake -G "MinGW Makefiles" ../

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

后面去stackoverflow上面问了大佬关于“cmake:cl is not a full path and was not found in the PATH. ”的问题,发现是visual studio 编译器的路径没有放:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第28张图片
输入命令:nmake
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第29张图片
输入命令:nmake install
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第30张图片
在这里插入图片描述
编译成功后,后会产生build-2022文件夹以及该文件夹下的若干文件夹及文件:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第31张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第32张图片

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的目录,根据自己的来修改。)

开始编译: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

pt-onnx-ncnn转换的问题记录(接yolov5训练)_第33张图片
问题: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 ..

pt-onnx-ncnn转换的问题记录(接yolov5训练)_第34张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第35张图片
指令:

nmake
nmake install

在ncnn/tools/onnx/路径下得到onnx2ncnn.cpp文件:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第36张图片
同时在ncnn/build/tools/onnx/目录下得到运行文件onnx2ncnn,如下图,运行这个onnx2ncnn文件就可以将onnx模型转化为ncnn模型了:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第37张图片
下载并安装opencv
官网:https://opencv.org/releases/
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第38张图片
安装后放路径:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第39张图片
安装 onnx-simplifier

pip3 install onnx-simplifier

pt-onnx-ncnn转换的问题记录(接yolov5训练)_第40张图片
在这里插入图片描述
报错: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

pt-onnx-ncnn转换的问题记录(接yolov5训练)_第41张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第42张图片
将模型文件拖入浏览器页面即可显示。将文件拖入浏览器,可看到模型结构,网站:
https://netron.app/
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第43张图片

先利用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')

pt-onnx-ncnn转换的问题记录(接yolov5训练)_第44张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第45张图片
对比一下简化前和简化后的模型:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第46张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第47张图片

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 (命令错误) 

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

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

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

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

正确命令:onnx2ncnn bestsim.onnx bestsim.param bestsim.bin
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第48张图片
搞定了

onnx2ncnn leafsim.onnx leafsim.param leafsim.bin

pt-onnx-ncnn转换的问题记录(接yolov5训练)_第49张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第50张图片
其中param存放的是模型结构,可以理解为网络的配置文件,bin存放的是类似卷积这些op的权重文件,可以理解为网络的参数(各种权重)文件。

动态尺寸推理

最后 Reshape 层把输出grid数写死了,根据 ncnn Reshape 参数含义,把写死的数量改为 -1 便可以自适应
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第51张图片
在这里插入图片描述
替换后用 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

我把 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
在这里插入图片描述
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第52张图片
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第53张图片
优化前:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第54张图片
优化后:
pt-onnx-ncnn转换的问题记录(接yolov5训练)_第55张图片
另一个模型:

ncnnoptimize leafsim.param leafsim.bin leafopt.param leafopt.bin 0

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

你可能感兴趣的:(深度学习,计算机视觉,目标检测,深度学习)