目录
1. 项目准备
NCNN是腾讯公司开源的一个专为手机端极致优化的高性能神经网络前向计算框架,可以把电脑端生成在深度学习模型移植到手机端。NCNN从设计之初,就深刻考虑手机端的部署和使用,无需第三方依赖,跨平台,手机端CPU的速度快于目前所有已知的开源框架。基于NCNN,开发者能够将深度学习算法轻松移植到手机端高效执行,开发出人工智能APP,将AI带到你的指尖。
目前NCNN已经支持大部分的CNN网络,包括本文中用到的YOLOv5
NCNN源码:https://github.com/Tencent/ncnn
可以从这个网页上进行查看支持的具体平台
Releases · Tencent/ncnn · GitHub
我们接下来主要以带加速的ncnn-android-vulkan.zip展开
1.1 安装Android studio
这个百度上有很多对应的经验体,随便找一个教程,然后切换一下国内源,即可安装成功,Android studio安装的前提是必须保证安装了jdk1.8版本以上,android studio的官网:Download Android Studio & App Tools - Android Developers
这里需要说明一点,打开File-->Settings-->Android SDK,我们应该安装NDK、Cmake
根据自己的手机版本来选择对应的开发环境,最后点击应用下载
1.2 下载解压源码
下载解压NCNN和ncnn-android-yolov5工程
把ncnn-20240410-android-vulkan里面的文件复制一份到ncnn-android-yolov5-master的\app\src\main\jni目录下
2. 安卓源码重新编译
2.1 构建工程
用Android studio 打开这个ncnn-android-yolov5-master项目的build.gradle文件
之后Android studio会帮我们构建整个工程,耐心等待他走完
2.2 修改源码
(1)修改CMakeLists.txt中的路径
- 打开ncnn-android-yolov5-master\app\src\main\jni\CMakeLists.txt
将第五行的路径改为自己的路径
set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn-20240410-android-vulkan/${ANDROID_ABI}/lib/cmake/ncnn)
改为
set(ncnn_DIR ${CMAKE_SOURCE_DIR}/${ANDROID_ABI}/lib/cmake/ncnn)
也就是把作者的根目录给删除掉,修改之后
- 简单说明一下:ANDROID_ABI对应的是不同架构下的文件夹名称
2.3 重新重新Sync Project
2.4 安装APP到手机端
利用Android Studio连接手机进行APP的安装,连接手机教程在上面Android Studio安装教程里有详细教程,之后点击这个开始按钮即可
可以看到,手机端已经安装好这个APP了
点开看一下界面
3. 换成自己的训练模型
当我们训练好了自己的检测模型后,就需要一种中介,通过它在不同的框架之间进行转换,Open Neural Network Exchange 简称 ONNX,意思是开放神经网络交换格式,它就是我们需要的中介。
转换自己训练的pt权重为ncnn格式
我们采用.pt ->onnx->ncnn的路线来转换自己训练的模型
3.1 导出需要的onnx文件
(1)安装onnx包,在终端运行下面命令
pip install onnx coremltools onnx-simplifier
(2)使用YOLOv5自带的export.py进行转换
- 执行export.py操作前,修改weights和data的路径
- 这里有一点非常重要,一定要选择train模式去掉后处理,否则最终生成的APP会闪退
- 执行export.py操作后,会在权重文件夹下面生成一个onnx文
- 如果PyCharm直接运行无法生成onnx的话,使用下面的脚本命令应该就可以成功了
python export.py --train --weights weights/best.pt --include torchscript onnx
(3)对onnx文件进行压缩,进入到onnx文件所在目录,运行下面命令
python -m onnxsim best.onnx best-sim.onnx
- 压缩完之后会生成一个best-sim.onnx的文件,这一步是必须的,如果这一步不做,后面ONNX转NCNN可能会报错
3.2 将onnx文件转换成param文件
将best.onnx转成param和bin文件,可以下载以下文件之一
地址:Releases · Tencent/ncnn · GitHub
解压后,打开文件夹,并将best.onnx复制到该文件夹的对应位置,地址栏输入cmd后,在打开的命令行窗口输入例如onnx2ncnn.exe best.onnx best.param best.bin回车即可,原文件夹生成了需要的bin文件和param文件
3.3 修改项目源码
- 将刚才生成的best.bin、best.param文件放到ncnn-android-yolov5-master\app\src\main\assets文件夹下
- 然后我们修改yolov5ncnn_jni.cpp文件(上图中的绿色框)。修改模型权重路径,输入输出、anchors大小和类别名。
- 全局搜索yolov5.load_param,将后面的yolov5s.param修改为自己的param名。就在这个代码附近有bin的加载.同理修改
- 打开yolov5s.param,搜索Reshape层,将后面对应的 0=6400、0=1600、0=400 均修改为 0=-1 ,这是为了解决实际中出现的多检测框的问题,相对应的permute结点,在下面out既然点修改
- 将ncnn-android-yolov5-master\app\src\main\jni文件夹下的yolov5ncnn_jni.cpp的分类类别名改成自己模型的实际类别名
- 修改源码文件yolov5ncnn_jni.cpp中Permute 节点的 output
- 将param文件中permute部分与stride部分中blob_name后面的数字对应起来
- param文件中搜索permute会出来3个结果,我们选择
- 我们使用Notre打开这个yolov5s.param文件,找到permute节点,这个permute节点一共有3个,分别是128,256,512尺寸的,我们需要的是256和512的输出维度
3.4 测试
连上手机,点击run按钮,编译安装调试
4. 版本设置
Android Studio运行yolov5 7.0项目,以下版本只是参考,也可以用其他版本,根据错误提示下载相应版本即可
Android APP闪退问题
老版本的export.py 中,通过添加train参数,去除模型中的后处理。但是新版本中,这个参数没了,所以我们需要将模型中的后处理去掉。
找到yolov5代码中的models->yolo.py文件,将Detect类下面的forward函数替换(大概是56-80行),修改为下面的forward
def forward(self, x):
z = [] # inference output
for i in range(self.nl):
feat = self.m[i](x[i]) # conv
# x(bs,255,20,20) -> x(bs,20,20,255)
feat = feat.permute(0, 2, 3, 1).contiguous()
z.append(feat.sigmoid())
return tuple(z)
输入输出
打开https://netron.app/,然后将param拖进去, 最上面的这个名字是images,将images填写到ex.input中。 模型有三个输出,分别对应stride 8,stride 16和stride 32.将这个输出的名字也填写到对应位置。一般情况下,stride 8对应out0,stride 16对应out1,stride 32对应out2.
stride 8对应out0
stride 16对应out1
stride 32对应out2.