Tensorflow lite for 移动端安卓开发(三)——移动端测试自己的模型

2024-05-30 05:58

本文主要是介绍Tensorflow lite for 移动端安卓开发(三)——移动端测试自己的模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Tensorflow-lite官方给的应用是一个摄像头demo,主要由ImageClassifier类和Camera2BasicFragment类构成,ImageClassifier类为一个抽象类,由浮点类和数字量化类两类继承,主要实现读取,模型和预测的功能。Camera2BasicFragment类为碎片类,主要实现摄像头的预览功能。基于项目需要,为了能够在移动端测试model的性能,在原demo的基础上开发了一个测试demo,从移动端本地读取测试集进行预测,将预测结果以txt保存在本地,同时计算每类的精确率和召回率在终端显示,先给出demo效果图。
这里写图片描述
这里写图片描述
第一个图展示的是float模型跑出来的结果,第二个图展示的是量化模型的结果Quant量化模型跑出来的结果精度下降很多。
demo的github代码如下:https://github.com/GeekLee95/TFlite_android_test/tree/master
代码主要由以下四个类构成
这里写图片描述
ImageClassifer类 为抽象类
ImageClassifierFloatInception为浮点型子类,对应的浮点模型为assets资源下的7_float.tflite
ImageClaaifierQuantizedMobileNet为量化型子类,对应的数字量化模型为assets资源下的7.tflite
Mainactivity为主活动,主要涉及读取文件,图片格式转化和模型预测等方法。
output_labels.txt为模型的标签文件。

下面介绍主活动的主要方法。

1). public static void verifyStoragePermissions(Activity activity)
该函数实现动态申请权限,android 6.0以后为了提高系统安全,必须要在程序中动态申请权限
首先在清单文件中配置需要申请的权限,

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.liuli.openfiles"><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEM"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

然后再动态申请

public static void verifyStoragePermissions(Activity activity){try{int permission= ActivityCompat.checkSelfPermission(activity,"android.permission.WRITE_EXTERNAL_STORAGE");if(permission!= PackageManager.PERMISSION_DENIED){ActivityCompat.requestPermissions(activity,PERMISSIONS_STORGE,REQUEST_EXTERNAL_STORAGE);}} catch (Exception e){e.printStackTrace();}}

2). private List getImagePath()从本地存储中获取测试图片路径,可以选择内部存储(外置SD卡)和扩展存储卡(TF卡)路径。

private List<String> getImagePath(){List<String> dirpath = getExtSDCardPathList();Log.d("sd_path",dirpath.get(0));Log.d("tf_path",dirpath.get(1));tfpath = dirpath.get(1);List<String> imagePathList = new ArrayList<String>();String filepath = tfpath+ File.separator+"DCIM"+File.separator+"TEST";//String filepath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();//Context context = getApplicationContext(); //获取当前上下文//String filepath = context.getExternalFilesDir("DCIM")+File.separator;//得到该路径文件夹下的所有文件Log.d("filepath",filepath);File fileAll = new File(filepath);boolean result = fileAll.exists();File[] files = fileAll.listFiles();for(int i = 0;i<files.length;i++){File file = files[i];if(checkIsImageFile(file.getPath())){imagePathList.add(file.getPath());}}return imagePathList;}

3). private Bitmap createImageThumbnail(String filePath,int newHeight,int newWidth) 将原始图片缩放成指定大小的bitmap格式,比如mobilenet模型的input_size: 224x224

private Bitmap createImageThumbnail(String filePath,int newHeight,int newWidth){Bitmap bm = BitmapFactory.decodeFile(filePath);float width = bm.getWidth();float height = bm.getHeight();Log.i("old_size:","宽度是"+width+",高度是"+height);Matrix matrix = new Matrix();//计算宽高缩放率float scaleWidth = ((float) newWidth)/width;float scaleHeight = ((float) newHeight)/height;//缩放图片动作matrix.postScale(scaleWidth,scaleHeight);Bitmap bitmap = Bitmap.createBitmap(bm,0,0,(int)width,(int)height,matrix,true);Log.i("new_size:","宽度是"+bitmap.getHeight()+",高度是"+bitmap.getWidth());return bitmap;}

4). private void classifyFrame(List Frames) 进行模型预测

    private void classifyFrame(List<String> Frames){int num = 0;int carlessnum = 0,carlessTP = 0,carlessFP = 0;int carnormalnum = 0,carnormalTP = 0,carnormalFP = 0;int carmorenum = 0,carmoreTP = 0,carmoreFP = 0;//显示待预测图片总数mShownum.setText(Integer.toString(Frames.size()));Log.d("mShownum",Integer.toString(Frames.size()));String resultfilepath = tfpath+ File.separator+"DCIM"+File.separator+"TESTRESULT"+File.separator;for(int i = 0;i<Frames.size();i++){String imagepath = Frames.get(i);Bitmap bitmap = createImageThumbnail(imagepath,classifier.getImageSizeX(),classifier.getImageSizeY());String result = classifier.classifyFrame(bitmap);Log.d("Predict_result"+Integer.toString(i),result);String imagename = imagepath.split("/")[imagepath.split("/").length-1];//将数据保存到本地String resultname = imagename.replace(".jpg",".txt");Log.d("resultname",resultname);writeTxtToFile(result,resultfilepath,resultname);String label = imagename.split("_")[0];Log.d("label"+Integer.toString(i),label);switch (label){case "0":carlessnum++;Log.d("carlessnum",Integer.toString(carlessnum));if(result == classifier.labelList.get(Integer.parseInt(label))){carlessTP++;Log.d("carlessTP",Integer.toString(carlessTP));}break;case "1":carnormalnum++;Log.d("carnormalnum",Integer.toString(carnormalnum));if(result == classifier.labelList.get(Integer.parseInt(label))){carnormalTP++;Log.d("carnormalTP",Integer.toString(carnormalTP));}break;case "2":carmorenum++;Log.d("carmorenum",Integer.toString(carmorenum));if(result == classifier.labelList.get(Integer.parseInt(label))){carmoreTP++;Log.d("carmoreTP",Integer.toString(carmoreTP));}break;}if(result != classifier.labelList.get(Integer.parseInt(label))){switch (result){case "类别1":carlessFP++;break;case "类别2":carnormalFP++;break;case "类别3":carmoreFP++;break;}}if(result == classifier.labelList.get(Integer.parseInt(label))){num++;} else{wrongFrames.add(imagepath+"predict:"+result);}Log.d("图片数:", Integer.toString(i+1));Log.d("正确数:", Integer.toString(num));}float result  = (float)num/(float)Frames.size();mShowResult.setText(Float.toString(result));// 计算每一类的精确率和召回率float carlessrec = (float)Math.round((float)carlessTP/(float)carlessnum*10000)/10000;float carlessacc = (float) Math.round((float)carlessTP/(float)(carlessTP+carlessFP)*10000)/10000;float carnormalrec = (float) Math.round((float)carnormalTP/(float)carnormalnum*10000)/10000;float carnormalacc = (float) Math.round((float)carnormalTP /(float)(carnormalTP+carnormalFP)*10000)/10000;float carmorerec = (float) Math.round((float) carmoreTP/(float)carmorenum*10000)/10000;float carmoreacc = (float) Math.round((float)carmoreTP/(float)(carmoreTP+carmoreFP)*10000)/10000;mShowcarlessacc.setText(Float.toString(carlessacc));mShowcarlessrec.setText(Float.toString(carlessrec));mShowcarlessnum.setText(Integer.toString(carlessnum));mShowcarnormacc.setText(Float.toString(carnormalacc));mShowcarnormrec.setText(Float.toString(carnormalrec));mShowcarnormnum.setText(Integer.toString(carnormalnum));mShowcarmoreacc.setText(Float.toString(carmoreacc));mShowcarmorerec.setText(Float.toString(carmorerec));mShowcarmorenum.setText(Integer.toString(carmorenum));}

后续将会对模型进行改进和完善。

这篇关于Tensorflow lite for 移动端安卓开发(三)——移动端测试自己的模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

基于Java开发一个极简版敏感词检测工具

《基于Java开发一个极简版敏感词检测工具》这篇文章主要为大家详细介绍了如何基于Java开发一个极简版敏感词检测工具,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录你是否还在为敏感词检测头疼一、极简版Java敏感词检测工具的3大核心优势1.1 优势1:DFA算法驱动,效率提升10

Python开发简易网络服务器的示例详解(新手入门)

《Python开发简易网络服务器的示例详解(新手入门)》网络服务器是互联网基础设施的核心组件,它本质上是一个持续运行的程序,负责监听特定端口,本文将使用Python开发一个简单的网络服务器,感兴趣的小... 目录网络服务器基础概念python内置服务器模块1. HTTP服务器模块2. Socket服务器模块

Java 与 LibreOffice 集成开发指南(环境搭建及代码示例)

《Java与LibreOffice集成开发指南(环境搭建及代码示例)》本文介绍Java与LibreOffice的集成方法,涵盖环境配置、API调用、文档转换、UNO桥接及REST接口等技术,提供... 目录1. 引言2. 环境搭建2.1 安装 LibreOffice2.2 配置 Java 开发环境2.3 配

基于Python Playwright进行前端性能测试的脚本实现

《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指

把Python列表中的元素移动到开头的三种方法

《把Python列表中的元素移动到开头的三种方法》在Python编程中,我们经常需要对列表(list)进行操作,有时,我们希望将列表中的某个元素移动到最前面,使其成为第一项,本文给大家介绍了把Pyth... 目录一、查找删除插入法1. 找到元素的索引2. 移除元素3. 插入到列表开头二、使用列表切片(Lis

Python38个游戏开发库整理汇总

《Python38个游戏开发库整理汇总》文章介绍了多种Python游戏开发库,涵盖2D/3D游戏开发、多人游戏框架及视觉小说引擎,适合不同需求的开发者入门,强调跨平台支持与易用性,并鼓励读者交流反馈以... 目录PyGameCocos2dPySoyPyOgrepygletPanda3DBlenderFife

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3