使用ncnn部署yolox详细记录
前言
之前本人使用ncnn部署都是用pnnx版将模型转换为ncnn,但由于ncnn的examples文件夹下没有yolox的pnnx版本的c++文件,所以ncnn部署yolox采用onnx版进行部署。
本文章为up本人部署时的理解并记录过程,若文章中有不正确的地方,请多批评指教。
若参考本文章进行ncnn部署yolox,需要有以下准备:
有一个yolox的模型
已经使用cmake成功编译ncnn
看懂C++和Python
模型转换onnx
根据yolox的tools路径下的export_onnx.py文件中的make_parser函数,设置模型转onnx的参数

由于up的模型修改yolox的exps/example/yolox_voc路径下的yolox_voc_s.py文件,修改改文件里的数据集目录以及类别等之后用该文件进行模型训练,所以export_onnx.py需要用参数中的-f 需要指定该文件;
模型训练完后,在yolox的YOLOX_output/yolox_voc_s路径下有训练好的模型,export_onnx.py需要用参数中的-c 需要指定使用的模型
所以本人需求运行以下命令将模型转换为onnx:
onnx转换ncnn
本人在ncnn路径下创建build文件夹并在该文件夹下make编译ncnn,所以编译之后的ncnn文件夹下的build/tools/onnx路径下有onnx2ncnn的可执行文件。(如果你没有tools的文件夹以及可执行文件等,你需要通过cmake成功编译ncnn)
将onnx文件放入当前路径下(也可放到你喜欢的路径下),执行onnx2ncnn的可执行文件,生成ncnn需要的param文件和bin文件

执行可执行文件,第0个参数为可执行文件名字,第一个参数是onnx文件,第二个参数是生成的param的名字,第三个参数是生成bin文件的名字,执行代码如下:
执行后不出意外的话就要出意外了,程序会报“Unsupported slice step !”的错误 ,并且也生成了我们需要的param文件和bin文件

根据ncnn的examples路径下的yolox.cpp文件中,我们能看到代码中的注释写着用着跟yolov5相同的focus,并且在ncnn加载模型前也先注册了YoloV5Focus


所以yolox的这个错误,我们可以跟yolov5一样手工修复param,把ncnn不支持的算子替换掉,这里我们可以参考nihui大佬的文章(https://zhuanlan.zhihu.com/p/275989233)
我们通过netron打开yolox.param文件,需要将红框内删除并换成YoloV5Focus

点击split,查看到split输入的是images

点击concat,查看到conca输出的是683

所以我们自定义的YoloV5Focus算子,它的输入是images,输出是683,并且是一个输入一个输出。
我们用记事本或者vscode打开param文件,找到split、crop、concat并删除

在原来的位置插入YoloV5Focus,并且写入1个输入,1个输出,输入的名字,输出的名字,如下图所示:

由于我们在param文件里删除了10行,再自己写了1行,所以根据本人的文件里的第二行第一个参数需要改成286(295-10+1)

修改完成后保存并替换原来的param文件,再进入ncnn的build/tools路径下,执行以下代码使用 ncnnoptimize 工具修正模型,顺便转为 fp16 存储减小模型体积。
执行成功结果如下:

通过netron查看修改后的模型,发现已经成功转换了模型的算子了

xiug
修改yolox.cpp文件
最后我们根据自己的需求修改yolox.cpp文件了
我们先修改加载模型的路径,并且由于我是在轻量级服务器跑的,所以不需要使用gpu得把
yolox.opt.use_vulkan_compute修改成false

还需要把修改类别,改成你的模型需要的

由于我在服务器跑ncnn,服务器没有桌面版Linux,所以把显示推理后图片改成保存推理后图片

修改完覆盖ncnn的examples路径下的yolox.cpp文件,并重新用cmake编译ncnn,编译完成如下图:

结果测试
我们打开ncnn的build/examples路径下将编译生成的yolox可执行文件复制到你想要的路径下(嫌麻烦也可以直接用),以我本人为例,将可执行文件复制到存放模型的文件夹里

执行可执行文件,第0个参数为可执行文件名字,第一个参数为需要推理的图片,推理完成后生成推理后的图片(如果你没改opencv为保存图片的话就是图片直接显示)

打开推理后的图片

总结
自此,ncnn部署yolox完毕!相信你已经完全掌握了ncnn部署yolox和yolov5的步骤。
如果你训练的模型在ncnn里面有可以使用pnnx版的话,通过pnnx转换为ncnn会方便很多。
nihui大佬yyds!
参考文章
https://zhuanlan.zhihu.com/p/275989233
https://zhuanlan.zhihu.com/p/471357671