快速在安卓端验证深度学习算法模型

2024-06-17 15:48

本文主要是介绍快速在安卓端验证深度学习算法模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

https://zhuanlan.zhihu.com/p/76909819

https://zhuanlan.zhihu.com/p/76909819

 

1、背景

​ 前段时间在知乎上溜达,看到 

糖心他爸

 大神的专栏-实战嵌入端的AI算法,进去一看,不得了,发现新大陆了,深度学习模型还能在安卓端这么玩的吗?

​ 一般对我们这种初级炼丹师,要验证算法在端上的能力以及实测效果。一般是这样的, 如图1(至于你们是不是这样我是不知道),中间验证过程又臭又长,中间有些环节还得看别人有没有空(只怪自己水平差)。

图1 验证流程

​ 那么看了大神的专栏,发现原来可以这么玩(嫌弃ing,说了半天还没告诉怎么玩)。

​ 以mnist分类为例,先贴下大神的部分代码,详细代码看大神github。

int main(void)
{std::string image_name = "./mnist_test.jpg";std::string model_name = "./mnist.mnn";int forward = MNN_FORWARD_CPU;// int forward = MNN_FORWARD_OPENCL;int precision  = 2;int power      = 0;int memory     = 0;int threads    = 1;int INPUT_SIZE = 28;cv::Mat raw_image    = cv::imread(image_name.c_str());int raw_image_height = raw_image.rows;int raw_image_width  = raw_image.cols; cv::Mat image;……auto net = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromBuffer(modelBuffer, bufferSize));……auto session = net->createSession(config);………………// run networknet->runSession(session);…………// post processing stepsauto scores_dataPtr  = tensor_scores_host.host<float>();// softmaxfloat exp_sum = 0.0f;for (int i = 0; i < 10; ++i){float val = scores_dataPtr[i];exp_sum += val;}// get result idxint  idx = 0;float max_prob = -10.0f;for (int i = 0; i < 10; ++i){float val  = scores_dataPtr[i];float prob = val / exp_sum;if (prob > max_prob){max_prob = prob;idx      = i;}}printf("the result is %d\n", idx);return 0;
}

​ 看下来直接在android端就能用C++完成模型效果以及性能测试了,感觉就不用去求爷爷求爸爸了,开森啊(这里面的MNN是阿里的端上inference框架,感兴趣可以去GitHub上看看,MNN可以参考MNN文档,当然还有nihui大佬的NCNN ):

2、怎么玩

​ 开森归开森,但是怎么玩呢?把大神的专栏翻了一遍,没看对应教程,大佬可能觉得这个so easy,大家都会,哭!!!

​ 怎么办?看看大神代码好像有mk文件,查查mk文件干啥的呢?发现是安卓上类似makefile文件,那就查查如何用mk编译可执行文件吧,通过问问度娘以及谷歌爸爸,发现是可以实现的,那么大体方向是没错。

​ 那么怎么编译?怎么把对应的文件传到android上?怎么在android上执行呢?(怒问自己,垃圾,你咋这么多不会呢!!!)

​ 这个时候果断去抱安卓同学的大腿了!

​ 大腿开始教我怎么玩啦!!!

2.1 ndk编译

​ 这里先git clone 一下大神的github代码,前面opencv动态库,MNN动态库,mk文件大神都给你们弄好了,下下来改改或者直接用就行了。

​ 再下载android的NDK(我是mac电脑,如果你们是其它系统,行不行我不知道,我只管挖不管埋)。

​ 可以发现ndk下面有个ndk-build文件(安卓大腿说用着玩意编译)。

# 先设置环境
PATH=$PATH:<ndk-build所在的文件目录>
# 这里我们就以大神里面的mnist为例
cd MNN-APPLICATIONS/applications/mnist/jni
ndk-build
# 这里可以发现直接在mnist创建了libs目录
# 运行结果
[arm64-v8a] Install        : libMNN.so => libs/arm64-v8a/libMNN.so
[arm64-v8a] Install        : libMNN_CL.so => libs/arm64-v8a/libMNN_CL.so
[arm64-v8a] Install        : libMNN_Vulkan.so => libs/arm64-v8a/libMNN_Vulkan.so
[arm64-v8a] Install        : onnx_mnist => libs/arm64-v8a/onnx_mnist

​ 到这里基本编译结束了,那么怎么把它导到android端呢?

2.2 文件传输

​ 下面这个得用adb工具,至于这玩意怎么安装,是什么玩意,自己百度。

​ 搞了个rk3399,连上电脑。

# 先来条命令
adb devices#运行结果如下,可以看到我下面有个设备了,设备号CBI9SLBNWK
List of devices attached
CBI9SLBNWK  device# 切换一下root权限
adb root
# 运行结果
”adbd is already running as root“

​ 这样子我们待会进入adb shell就有root权限了,就可以为所欲为了。

正式push数据上去:

# 传输编译好的文件,我这边比较懒把整个目录都push上去
adb push MNN-APPLICATIONS /data

2.3 运行可执行文件

# 下面进入adb shell环境
adb shell
# 下面就跟我们在linux的操作差不多了
# 先查看我们上传的文件在不
ls /data
# 发现文件是在的
cd /data
cd /data/temp/MNN-APPLICATIONS/applications/mnist/onnx/libs/arm64-v8a
# 可以发现有个编译好的可执行文件 onnx_mnist
# 把 onnx_minist拷出来,拷到有图片的目录,这里可以不拷贝,只是跟cpp代码中模型文件跟测试文件相对路径保持一致就行
cp onnx_mnist ../../jni
cd ../../jni# 看下大神的onnx_mnist.cpp文件,发现在该目录下需要mnist_test.jpg以及mnist.mnn两个文件
# 把该目录test.jpg文件名改成对应名字
mv test.jpg mnist_test.jpg
# 把graph中,MNN转换的mnist.mnn拷出来
cp ./graphs/minist.mnn ./

​ 激动人心的时候到啦,终于可以运行了!(集齐七颗龙珠了,可以召唤神龙了)

./onnx_mnist
# 我去,出错啦
CANNOT LINK EXECUTABLE "./onnx_mnist": library "libMNN.so" not found

​ 难道是编译目录不对?折腾了半天,把动态库移来移去,移到当前木来,看了mk文件,发现在对应的位置也有对应的动态库。

OpenCV_BASE = ../../../../libraries/opencv-4.1
MNN_BASE    = ../../../../libraries/mnn

​ 搞了半天没办法了,加上 

糖心他爸

 大神微信,求大神指点。

​ 大神直接贴了一行代码:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<对应动态库路径>

​ 我去,原来没有指定对应动态库路径,,补上:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../libs/arm64-v8a

运行结果:

Invalide device for support vulkan
Invalide device for support vulkan
the result is 5

​ 感动,终于有运行结果了!

这篇关于快速在安卓端验证深度学习算法模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069865

相关文章

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

五大特性引领创新! 深度操作系统 deepin 25 Preview预览版发布

《五大特性引领创新!深度操作系统deepin25Preview预览版发布》今日,深度操作系统正式推出deepin25Preview版本,该版本集成了五大核心特性:磐石系统、全新DDE、Tr... 深度操作系统今日发布了 deepin 25 Preview,新版本囊括五大特性:磐石系统、全新 DDE、Tree

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用