ncnn模型部署——训练自己YOLOv5模型转ncnn模型并部署到Android手机端

目录

  • 一、前述
  • 二、源码包准备
    • 2.1 配套源码包
    • 2.2 官网源码包
      • 2.2.1 ncnn版YOLOv5源码包下载
      • 2.2.2 ncnn预编译库下载
      • 2.2.3 拷贝ncnn预编译库
  • 三、可能遇到问题
    • 3.1 gradle下载失败
    • 3.2 CMake问题
      • 3.2.1 报错
      • 3.2.2 问题分析
      • 3.2.3 解决办法
      • 3.2.4 添加环境变量
      • 3.2.5 测试CMake
    • 3.3 Unable to make field private final java.lang.String java.io
    • 3.4 No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi
      • 3.4.1 报错
      • 3.4.2 问题分析
      • 3.4.3 解决办法
        • 3.4.3.1 官网手动下载
        • 3.4.3.2 Android Studio自动下载
    • 3.5 权限访问
  • 四、官网模型部署
    • 4.1 CMakeLists.txt文件参数修改
    • 4.2 指定部署平台
    • 4.2 构建
    • 4.3 连接手机
      • 4.3.1 连接没反应问题
    • 4.4 安装apk到Android手机端
      • 4.4.1 打开APP
      • 4.4.2 测试结果
      • 4.4.3 查看耗时
  • 五、自己训练模型部署
    • 5.1 Pytorch模型转onnx模型
      • 5.1.2 参数修改
      • 5.1.3 转换代码
      • 5.1.4 可视化网络结构
    • 5.2 onnx模型转ncnn模型
      • 5.2.1 ncnn模型在线转换工具
    • 5.3 修改.param文件参数
    • 5.4 修改yolov5ncnn_jni.cpp
    • 5.5 安装apk到Android手机端
  • 六、总结

一、前述

上一篇博文中将YOLOv5模型转到ncnn模型后部署到电脑端Ubuntu系统上,本教程讲解如何将YOLOv5模型转到ncnn模型后落地部署到Android手机端,主要在手机上检测单帧图像。在部署过程中我最开始用的是Vivo旗下的IQOO 6SE手机,通过Android Studio打包将apk安装到手机后,一直闪退,我折磨了很久,没解决,但使用手机模拟器是能够正常安装并检测。后来我翻出了老手机,部署到小米Max 3手机上可以正常检测。

本教程的讲解会涉及到之前写的一些博客,如果有不会的,对应学习之前的博文:
使用Yolov5训练自己制作的数据集
Android Studio详细安装教程及入门测试
Windows系统下安装java开发环境所需的JDK开发工具包

二、源码包准备

2.1 配套源码包

本教程的配套源码包获取方法文章末扫码到公众号「视觉研坊」中回复关键字:yolov5 ncnn模型Android部署。获取下载链接。

下载解压后的样子如下:

在这里插入图片描述

2.2 官网源码包

2.2.1 ncnn版YOLOv5源码包下载

ncnn版YOLOv5源码包下载地址为:ncnn版YOLOv5

在这里插入图片描述

2.2.2 ncnn预编译库下载

ncnn官网地址为:ncnn

打开ncnn官网地址后,找到realses打开,如下:

在这里插入图片描述

在这里插入图片描述

往下滑

在这里插入图片描述

下载好后的预编译库如下:

在这里插入图片描述

2.2.3 拷贝ncnn预编译库

上面下载好的两个包文件解压后,将预编译库中的4个文件都拷贝到yolov5_ncnn_Android\ncnn-android-yolov5-master/app/src/main/jni目录下,如下:

三、可能遇到问题

我自己在走这条路中遇到了很多问题,这里总结一下,学者如果也遇到类似我的问题,参考一下。

上面第二步骤都完成后,使用电脑上已经安装好的Android Studio打开ncnn-android-yolov5-master工程文件。打开后第一次构建可能遇到问题见下:

3.1 gradle下载失败

打开工程文件后会根据对应版本自动下载gradle,如果中途下载失败,可以点击reload或者直接去到C盘下找到.gradle文件夹,将整个.gradle文件夹删除,再重新下载,如下:

在这里插入图片描述

3.2 CMake问题

3.2.1 报错

Suppressed sync exceptions

CMake ‘3.10.2’ was not found in PATH or by cmake.dir property.
java.lang.RuntimeException: CMake ‘3.10.2’ was not found in PATH or by cmake.dir property.
at com.android.build.gradle.internal.cxx.configure.CmakeSearchContext.issueVersionNotFoundError g r a d l e ( C m a k e L o c a t o r . k t : 459 ) a t c o m . a n d r o i d . b u i l d . g r a d l e . i n t e r n a l . c x x . c o n f i g u r e . C m a k e L o c a t o r K t . f i n d C m a k e P a t h L o g i c ( C m a k e L o c a t o r . k t : 545 ) a t c o m . a n d r o i d . b u i l d . g r a d l e . i n t e r n a l . c x x . c o n f i g u r e . C m a k e L o c a t o r . f i n d C m a k e P a t h ( C m a k e L o c a t o r . k t : 560 ) a t c o m . a n d r o i d . b u i l d . g r a d l e . i n t e r n a l . c x x . m o d e l . T r y C r e a t e C x x M o d u l e M o d e l K t gradle(CmakeLocator.kt:459) at com.android.build.gradle.internal.cxx.configure.CmakeLocatorKt.findCmakePathLogic(CmakeLocator.kt:545) at com.android.build.gradle.internal.cxx.configure.CmakeLocator.findCmakePath(CmakeLocator.kt:560) at com.android.build.gradle.internal.cxx.model.TryCreateCxxModuleModelKt gradle(CmakeLocator.kt:459)atcom.android.build.gradle.internal.cxx.configure.CmakeLocatorKt.findCmakePathLogic(CmakeLocator.kt:545)atcom.android.build.gradle.internal.cxx.configure.CmakeLocator.findCmakePath(CmakeLocator.kt:560)atcom.android.build.gradle.internal.cxx.model.TryCreateCxxModuleModelKttryCreateCxxModuleModel 4 4 4cmake 1 1 1cmakeFolder 2. i n v o k e ( T r y C r e a t e C x x M o d u l e M o d e l . k t : 119 ) a t c o m . a n d r o i d . b u i l d . g r a d l e . i n t e r n a l . c x x . m o d e l . T r y C r e a t e C x x M o d u l e M o d e l K t 2.invoke(TryCreateCxxModuleModel.kt:119) at com.android.build.gradle.internal.cxx.model.TryCreateCxxModuleModelKt 2.invoke(TryCreateCxxModuleModel.kt:119)atcom.android.build.gradle.internal.cxx.model.TryCreateCxxModuleModelKttryCreateCxxModuleModel 4 4 4cmake 1 1 1cmakeFolder$2.invoke(TryCreateCxxModuleModel.kt:117)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)

在这里插入图片描述

3.2.2 问题分析

这个错误是因为 Android Studio 在构建项目时没有找到指定版本(3.10.2)的 CMake

3.2.3 解决办法

打开 Android Studio,然后选择 File -> Settings -> Appearance & Behavior -> Android SDK -> SDK Tools。

在 SDK Tools 选项卡中,找到 CMake,然后勾选 3.10.2 版本。

点击 Apply,等待下载和安装完成。
在这里插入图片描述

我自己原先版本是3.22.1,重新安装3.10.2版本:

在这里插入图片描述

在这里插入图片描述

3.2.4 添加环境变量

在电脑中打开系统变量,依次按照下面步骤添加环境变量:

在这里插入图片描述

3.2.5 测试CMake

在终端输入命令,如果输出CMake版本,说明安装成:

cmake --version

在这里插入图片描述

3.3 Unable to make field private final java.lang.String java.io

完整的报错是 Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not “opens java.io” to unnamed module @5de92e13

该问题的解决办法,见我另外一篇博文:Unable to make field private final java.lang.String java.io

3.4 No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi

3.4.1 报错

Execution failed for task ‘:app:stripDebugDebugSymbols’.

No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi

3.4.2 问题分析

这个错误通常发生在NDK版本过高,与Android Gradle Plugin(AGP)版本不匹配时。

3.4.3 解决办法

下载低版本的NDK,下载有两种方法。

3.4.3.1 官网手动下载

手动下载NDK链接为:NDK

打开网页后具体下载步骤见下:

在这里插入图片描述

在这里插入图片描述

直接下载r21 ndk安装包的链接为:https://dl.google.com/android/repository/android-ndk-r21e-windows-x86_64.zip

如果下载太慢,可以将此链接复制到迅雷中下载,速度较快。

在这里插入图片描述
下载解压后得到的文件如下:

在这里插入图片描述

将toolchains文件夹中除了llvm的其他文件全部复制到路径:C:\Users\Administrator\AppData\Local\Android\Sdk\ndk\26.2.11394342\toolchains下

在这里插入图片描述

3.4.3.2 Android Studio自动下载

在Andriod Studio中直接下载,先打开设置,具体步骤见下:

在这里插入图片描述

在这里插入图片描述

通过上面方法可以直接下载低版本的NDK。

3.5 权限访问

如果安装后没有权限打开,在AndroidManifest.xml文件中加入下面语句:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

在这里插入图片描述

四、官网模型部署

在第二步骤中从官网上下载得到的源码包中,已经包含了官网提供的ncnn模型,位于ncnn-android-yolov5-master/app/src/main/assets目录下。

4.1 CMakeLists.txt文件参数修改

CMakeLists.txt文件中需要修改的地方见下:

在这里插入图片描述

4.2 指定部署平台

在build.gradle文件中修改部署平台,见下:

在这里插入图片描述

4.2 构建

以上都准备好后,重新构建:

在这里插入图片描述

build文件中会保留上一次构建生成的信息,有时会影响构建,可以直接删除后重新构建生成:

在这里插入图片描述

构建成功样子如下:

在这里插入图片描述

4.3 连接手机

先在手机上开启开发者选项,不同手机开启方法不一样,之前写过一篇关于vivo手机开启开发者选项的方法,参考:vivo手机开启开发者选项

打开开发者选项后,用数据线连接手机和电脑具体见下:

最开始连接会弹出下面窗口,选择传输文件:

在这里插入图片描述

下面是在开发者选项中依次开启:

在这里插入图片描述

在这里插入图片描述

手机连接电脑后会在手机弹出允许USB调试吗? 点击允许,如下:

在这里插入图片描述

4.3.1 连接没反应问题

如果手机端和电脑端通过数据线连通后,手机只是处于充电转态,没有弹出上面的允许USB调试吗?出现该问题是因为手机和电脑还没有通信过,需要找第三方软件先接通,比如互传,360手机助手等,这些软件会自动在手机上安装一个,装后就接通了,我自己用的是互传,如下:

在这里插入图片描述

在这里插入图片描述

通过互传软件连通后的样子如下:

在这里插入图片描述

4.4 安装apk到Android手机端

上面步骤没问题后,在Android Studio界面会弹出以连接手机的型号,选择待部署的手机,如下:

在这里插入图片描述

点击run按钮,编译后会自动发送到手机进行安装:

在这里插入图片描述

4.4.1 打开APP

手机上安装好的样子如下:

在这里插入图片描述

打开yolov5ncnn,如下:

在这里插入图片描述

4.4.2 测试结果

点击选图后会跳转到自己手机相册里,随机选择一张图片,选用CPU或GPU识别,如下:

在这里插入图片描述

4.4.3 查看耗时

耗时情况,在电脑端Android Studio中日志里查看,如下,CPU耗时为586.91ms,GPU耗时为1522.50ms:

在这里插入图片描述

五、自己训练模型部署

自己训练YOLOv5模型的详细教程,参考我的另外一篇博文:YOLOv5训练自己数据集

5.1 Pytorch模型转onnx模型

在YOLOv5训练自己数据集这篇博文对应的Pytorch源码包中,models/export.py脚本,用于将YOLOv5Pytorch模型转为onnx模型。

5.1.2 参数修改

使用该脚本需要修改及转换结果见下:

在这里插入图片描述

5.1.3 转换代码

import argparse
import sys
import timesys.path.append('./')  # to run '$ python *.py' files in subdirectoriesimport torch
import torch.nn as nnimport models
from models.experimental import attempt_load
from utils.activations import Hardswish, SiLU
from utils.general import set_logging, check_img_size
from utils.torch_utils import select_deviceif __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument('--weights', type=str, default='./yolov5s.pt', help='weights path')  # from yolov5/models/parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='image size')  # height, widthparser.add_argument('--batch-size', type=int, default=1, help='batch size')parser.add_argument('--dynamic', action='store_true', help='dynamic ONNX axes')parser.add_argument('--grid', action='store_true', help='export Detect() layer grid')parser.add_argument('--device', default='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')opt = parser.parse_args()opt.img_size *= 2 if len(opt.img_size) == 1 else 1  # expandprint(opt)set_logging()t = time.time()# Load PyTorch modeldevice = select_device(opt.device)model = attempt_load(opt.weights, map_location=device)  # load FP32 modellabels = model.names# Checksgs = int(max(model.stride))  # grid size (max stride)opt.img_size = [check_img_size(x, gs) for x in opt.img_size]  # verify img_size are gs-multiples# Inputimg = torch.zeros(opt.batch_size, 3, *opt.img_size).to(device)  # image size(1,3,320,192) iDetection# Update modelfor k, m in model.named_modules():m._non_persistent_buffers_set = set()  # pytorch 1.6.0 compatibilityif isinstance(m, models.common.Conv):  # assign export-friendly activationsif isinstance(m.act, nn.Hardswish):m.act = Hardswish()elif isinstance(m.act, nn.SiLU):m.act = SiLU()# elif isinstance(m, models.yolo.Detect):#     m.forward = m.forward_export  # assign forward (optional)model.model[-1].export = not opt.grid  # set Detect() layer grid exporty = model(img)  # dry run# TorchScript exporttry:print('\nStarting TorchScript export with torch %s...' % torch.__version__)f = opt.weights.replace('.pt', '.torchscript.pt')  # filenamets = torch.jit.trace(model, img)ts.save(f)print('TorchScript export success, saved as %s' % f)except Exception as e:print('TorchScript export failure: %s' % e)# ONNX exporttry:import onnxprint('\nStarting ONNX export with onnx %s...' % onnx.__version__)f = opt.weights.replace('.pt', '.onnx')  # filenametorch.onnx.export(model, img, f, verbose=False, opset_version=12, input_names=['images'],output_names=['classes', 'boxes'] if y is None else ['output'],dynamic_axes={'images': {0: 'batch', 2: 'height', 3: 'width'},  # size(1,3,640,640)'output': {0: 'batch', 2: 'y', 3: 'x'}} if opt.dynamic else None)# Checksonnx_model = onnx.load(f)  # load onnx modelonnx.checker.check_model(onnx_model)  # check onnx model# print(onnx.helper.printable_graph(onnx_model.graph))  # print a human readable modelprint('ONNX export success, saved as %s' % f)except Exception as e:print('ONNX export failure: %s' % e)# CoreML exporttry:import coremltools as ctprint('\nStarting CoreML export with coremltools %s...' % ct.__version__)# convert model from torchscript and apply pixel scaling as per detect.pymodel = ct.convert(ts, inputs=[ct.ImageType(name='image', shape=img.shape, scale=1 / 255.0, bias=[0, 0, 0])])f = opt.weights.replace('.pt', '.mlmodel')  # filenamemodel.save(f)print('CoreML export success, saved as %s' % f)except Exception as e:print('CoreML export failure: %s' % e)# Finishprint('\nExport complete (%.2fs). Visualize with https://github.com/lutzroeder/netron.' % (time.time() - t))

5.1.4 可视化网络结构

netron官网:netron

在这里插入图片描述

将生成的onnx模型直接拖到netron网络打开,如下:

在这里插入图片描述

5.2 onnx模型转ncnn模型

关于onnx模型转ncnn模型有两种方法,比较复杂的方法参考我另外一篇博文:onnx模型转ncnn模型

5.2.1 ncnn模型在线转换工具

这里介绍比较简单的方法,其它大佬已经将转换过程封装在了网页端,链接为:ncnn模型在线转换工具

使用过程见下:

在这里插入图片描述

将上面生成的ncnn模型两个文件拷贝到yolov5_ncnn_Android/ncnn-android-yolov5-master/app/src/main/assets路径中,如下:

在这里插入图片描述

5.3 修改.param文件参数

将Reshape修改为动态尺寸,可以兼容不同分辨率的图片:

在这里插入图片描述

5.4 修改yolov5ncnn_jni.cpp

根据自己训练得到的ncnn模型中.param文件参数,对应修改下面参数:

在这里插入图片描述

下面是导入ncnn模型的两个文件入口:

在这里插入图片描述

下面根据自己训练是样本中标签的类别修改,标签中有哪些类就对应写上,这里我自己训练的样本中只有person一个类,如下:

在这里插入图片描述

5.5 安装apk到Android手机端

上面都修改好准备好后,剩下的步骤和前面4.4一样,安装apk到Android手机端后测试。

六、总结

以上就是部署官网YOLv5模型和训练自己YOLOv5模型转ncnn模型并部署到Android手机端的详细实现过程,希望能帮到你!

总结不易,多多支持,谢谢!

感谢您阅读到最后!关注公众号「视觉研坊」,获取干货教程、实战案例、技术解答、行业资讯!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/623952.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

27. 【Android教程】下拉选择框 Spinner

本节我们将学习 Android 提供的下拉选择框——Spinner&#xff0c;它也是 Adapter 的常客。不仅仅是在 Android 端&#xff0c;在 Windows 上我们也经常会看到 Spinner 类型的样式。通常它是以下拉的形式存在&#xff0c;Spinner 在下拉列表中包含很多可供用户选择的选项&#…

Docker+Uwsgi部署Django项目

在之前的文章中&#xff0c;已经给大家分享了在docker中使用django自带的命令部署项目&#xff0c;这篇文章主要讲解如何使用uwsgi部署。 1. 在Django项目的根目录下新建Dockerfile文件 #Dockerfile文件 # 使用 Python 3.9 作为基础镜像 FROM python:3.9# 设置工作目录 WORKDI…

Intel显卡驱动导致Qt opengl 渲染YUV时拉伸窗口内存泄漏

最近在使用QOpenGLWidget做YUV视频渲染&#xff0c;发现在拉伸窗口的时候内存暴涨&#xff0c;如果窗口不动则内存不变。 可以得出结论一定是resizeGL出了问题&#xff0c;但是其实这里代码很简单 glViewport(0, 0, w, h); 还有就是变换矩阵计算&#xff0c;根本没资源建立与释…

大模型微调的几种常见方法

在文章深入理解大语言模型微调技术中&#xff0c;我们详细了解大语言模型微调的概念和训练过程&#xff0c;本篇给大家介绍大模型微调常见的7种训练方法。 1、Adapter Tuning 2019年谷歌的研究人员首次在论文《Parameter-Efficient Transfer Learning for NLP》提出针对 BERT 的…

NIO学习

文章目录 前言一、主要模块二、使用步骤1.服务器端2.客户端 三、NIO零拷贝(推荐)四、NIO另一种copy总结 前言 NIO是JDK1.4版本带来的功能,区别于以往的BIO编程,同步非阻塞极大的节省资源开销&#xff0c;避免了线程切换和上下文切换带来的资源浪费。 一、主要模块 Selector&a…

ENSP-旁挂式AC

提醒&#xff1a;如果AC不能成功上线AP&#xff0c;一般问题不会出在AC上&#xff0c;优先关注AC-AP线路上的二层或三层组网的三层交换机 拓扑图 管理VLAN&#xff1a;99 | 业务VLAN&#xff1a;100 注意点&#xff1a; 1.连接AP的接口需要打上pvid为管理vlan的标签 2.AC和…

Vitis HLS 学习笔记--readVec2Stream 函数-探究

目录 1. 高效内存存取的背景 2. readVec2Stream() 参数 3. 函数实现 4. 总结 1. 高效内存存取的背景 在深入研究《Vitis HLS 学习笔记--scal 函数探究》一篇文章之后&#xff0c;我们对于scal()函数如何将Y alpha * X这种简单的乘法运算复杂化有了深刻的理解。本文将转向…

imgcat 工具

如果经常在远程服务器或嵌入式设备中操作图片&#xff0c;要查看图片效果&#xff0c;就要先把图片dump到本地&#xff0c;比较麻烦。可以使用这个工具&#xff0c;直接在终端上显示。类似于这种效果。 imgcat 是一个终端工具&#xff0c;使用 iTerm2 内置的特性&#xff0c;允…

FOR循环指令计算累加和(CODESYS ST+SMART梯形图代码)

1、SMART PLC FOR循环指令应用 SMART PLC FOR循环指令_smart plc可以调用多少次for循环-CSDN博客文章浏览阅读2.4k次&#xff0c;点赞2次&#xff0c;收藏6次。SMART PLC的FOR循环&#xff1a; PLC里写需要加上&#xff1a; NEXT指令_smart plc可以调用多少次for循环https://r…

2024 年10个最佳 Ruby 测试框架

QA一直在寻找最好的自动化测试框架&#xff0c;这些框架提供丰富的功能、简单的语法、更好的兼容性和更快的执行速度。如果您选择结合使用Ruby和Selenium进行Web测试&#xff0c;可能需要搜索基于Ruby的测试框架进行Web应用程序测试。 Ruby测试框架提供了广泛的功能&#xff0…

打一把王者的时间,学会web页面测试方法与测试用例编写

一、输入框 1、字符型输入框&#xff1a; &#xff08;1&#xff09;字符型输入框&#xff1a;英文全角、英文半角、数字、空或者空格、特殊字符“~&#xff01;#&#xffe5;%……&*&#xff1f;[]{}”特别要注意单引号和&符号。禁止直接输入特殊字符时&#xff0c;…

纯golang开发的mqtt server

Mochi-MQTT Server github地址&#xff1a;https://github.com/mochi-mqtt/server Mochi-MQTT 是一个完全兼容的、可嵌入的高性能 Go MQTT v5&#xff08;以及 v3.1.1&#xff09;中间件/服务器。 Mochi MQTT 是一个完全兼容 MQTT v5 的可嵌入的中间件/服务器&#xff0c;完…