当前位置: 首页 > news >正文

Android 中集成 TensorFlow Lite图片识别

c5494e0d0040a885c764744a2cc414f6.png

在上图通过手机的相机拍摄到的物体识别出具体的名称,这个需要通过TensorFlow 训练的模型引用到项目中;以下就是详细地集成 TensorFlow步骤,请按照以下步骤进行操作:

  1. 在项目的根目录下的 build.gradle 文件中添加 TensorFlow 的 Maven 仓库。在 repositories 部分添加以下行:

allprojects {repositories {// 其他仓库...maven {url 'https://google.bintray.com/tensorflow'}}
}
  1. 在应用的 build.gradle 文件中添加 TensorFlow Lite 的依赖。在 dependencies 部分添加以下行:

implementation 'org.tensorflow:tensorflow-lite:2.5.0'
  1. 将 TensorFlow Lite 模型文件添加到你的 Android 项目中。将模型文件(.tflite)复制到 app/src/main/assets 目录下。如果 assets 目录不存在,可以手动创建。

  2. 创建一个 TFLiteObjectDetectionAPIModel类,用于加载和运行 TensorFlow Lite 模型。以下是一个示例代码:

import org.tensorflow.lite.Interpreter;
public class TFLiteObjectDetectionAPIModel implements Classifier {private static final Logger LOGGER = new Logger();// Only return this many results.private static final int NUM_DETECTIONS = 10;// Float modelprivate static final float IMAGE_MEAN = 128.0f;private static final float IMAGE_STD = 128.0f;// Number of threads in the java appprivate static final int NUM_THREADS = 4;private boolean isModelQuantized;// Config values.private int inputSize;// Pre-allocated buffers.private Vector<String> labels = new Vector<String>();private int[] intValues;// outputLocations: array of shape [Batchsize, NUM_DETECTIONS,4]// contains the location of detected boxesprivate float[][][] outputLocations;// outputClasses: array of shape [Batchsize, NUM_DETECTIONS]// contains the classes of detected boxesprivate float[][] outputClasses;// outputScores: array of shape [Batchsize, NUM_DETECTIONS]// contains the scores of detected boxesprivate float[][] outputScores;// numDetections: array of shape [Batchsize]// contains the number of detected boxesprivate float[] numDetections;private ByteBuffer imgData;private Interpreter tfLite;private TFLiteObjectDetectionAPIModel() {}/** Memory-map the model file in Assets. */private static MappedByteBuffer loadModelFile(AssetManager assets, String modelFilename)throws IOException {AssetFileDescriptor fileDescriptor = assets.openFd(modelFilename);FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());FileChannel fileChannel = inputStream.getChannel();long startOffset = fileDescriptor.getStartOffset();long declaredLength = fileDescriptor.getDeclaredLength();return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);}/*** Initializes a native TensorFlow session for classifying images.** @param assetManager The asset manager to be used to load assets.* @param modelFilename The filepath of the model GraphDef protocol buffer.* @param labelFilename The filepath of label file for classes.* @param inputSize The size of image input* @param isQuantized Boolean representing model is quantized or not*/public static Classifier create(final AssetManager assetManager,final String modelFilename,final String labelFilename,final int inputSize,final boolean isQuantized)throws IOException {final TFLiteObjectDetectionAPIModel d = new TFLiteObjectDetectionAPIModel();InputStream labelsInput = null;String actualFilename = labelFilename.split("file:///android_asset/")[1];labelsInput = assetManager.open(actualFilename);BufferedReader br = null;br = new BufferedReader(new InputStreamReader(labelsInput));String line;while ((line = br.readLine()) != null) {LOGGER.w(line);d.labels.add(line);}br.close();d.inputSize = inputSize;try {d.tfLite = new Interpreter(loadModelFile(assetManager, modelFilename));} catch (Exception e) {throw new RuntimeException(e);}d.isModelQuantized = isQuantized;// Pre-allocate buffers.int numBytesPerChannel;if (isQuantized) {numBytesPerChannel = 1; // Quantized} else {numBytesPerChannel = 4; // Floating point}d.imgData = ByteBuffer.allocateDirect(1 * d.inputSize * d.inputSize * 3 * numBytesPerChannel);d.imgData.order(ByteOrder.nativeOrder());d.intValues = new int[d.inputSize * d.inputSize];d.tfLite.setNumThreads(NUM_THREADS);d.outputLocations = new float[1][NUM_DETECTIONS][4];d.outputClasses = new float[1][NUM_DETECTIONS];d.outputScores = new float[1][NUM_DETECTIONS];d.numDetections = new float[1];return d;}@Overridepublic List<Recognition> recognizeImage(final Bitmap bitmap) {// Log this method so that it can be analyzed with systrace.Trace.beginSection("recognizeImage");Trace.beginSection("preprocessBitmap");// Preprocess the image data from 0-255 int to normalized float based// on the provided parameters.bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());imgData.rewind();for (int i = 0; i < inputSize; ++i) {for (int j = 0; j < inputSize; ++j) {int pixelValue = intValues[i * inputSize + j];if (isModelQuantized) {// Quantized modelimgData.put((byte) ((pixelValue >> 16) & 0xFF));imgData.put((byte) ((pixelValue >> 8) & 0xFF));imgData.put((byte) (pixelValue & 0xFF));} else { // Float modelimgData.putFloat((((pixelValue >> 16) & 0xFF) - IMAGE_MEAN) / IMAGE_STD);imgData.putFloat((((pixelValue >> 8) & 0xFF) - IMAGE_MEAN) / IMAGE_STD);imgData.putFloat(((pixelValue & 0xFF) - IMAGE_MEAN) / IMAGE_STD);}}}Trace.endSection(); // preprocessBitmap// Copy the input data into TensorFlow.Trace.beginSection("feed");outputLocations = new float[1][NUM_DETECTIONS][4];outputClasses = new float[1][NUM_DETECTIONS];outputScores = new float[1][NUM_DETECTIONS];numDetections = new float[1];Object[] inputArray = {imgData};Map<Integer, Object> outputMap = new HashMap<>();outputMap.put(0, outputLocations);outputMap.put(1, outputClasses);outputMap.put(2, outputScores);outputMap.put(3, numDetections);Trace.endSection();// Run the inference call.Trace.beginSection("run");tfLite.runForMultipleInputsOutputs(inputArray, outputMap);Trace.endSection();// Show the best detections.// after scaling them back to the input size.final ArrayList<Recognition> recognitions = new ArrayList<>(NUM_DETECTIONS);for (int i = 0; i < NUM_DETECTIONS; ++i) {final RectF detection =new RectF(outputLocations[0][i][1] * inputSize,outputLocations[0][i][0] * inputSize,outputLocations[0][i][3] * inputSize,outputLocations[0][i][2] * inputSize);// SSD Mobilenet V1 Model assumes class 0 is background class// in label file and class labels start from 1 to number_of_classes+1,// while outputClasses correspond to class index from 0 to number_of_classesint labelOffset = 1;recognitions.add(new Recognition("" + i,labels.get((int) outputClasses[0][i] + labelOffset),outputScores[0][i],detection));}Trace.endSection(); // "recognizeImage"return recognitions;}@Overridepublic void enableStatLogging(final boolean logStats) {}@Overridepublic String getStatString() {return "";}@Overridepublic void close() {}public void setNumThreads(int num_threads) {if (tfLite != null) tfLite.setNumThreads(num_threads);}@Overridepublic void setUseNNAPI(boolean isChecked) {if (tfLite != null) tfLite.setUseNNAPI(isChecked);}
}

确保替换 modelPath 参数为你的模型文件在 assets 目录中的路径。

  1. 在你的应用程序中使用 TFLiteObjectDetectionAPIModel 类进行推理。以下是一个简单的示例:

@Override
public void onPreviewSizeChosen(final Size size, final int rotation) {final float textSizePx =TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP, getResources().getDisplayMetrics());borderedText = new BorderedText(textSizePx);borderedText.setTypeface(Typeface.MONOSPACE);tracker = new MultiBoxTracker(this);int cropSize = TF_OD_API_INPUT_SIZE;try {detector =TFLiteObjectDetectionAPIModel.create(getAssets(),TF_OD_API_MODEL_FILE,TF_OD_API_LABELS_FILE,TF_OD_API_INPUT_SIZE,TF_OD_API_IS_QUANTIZED);cropSize = TF_OD_API_INPUT_SIZE;} catch (final IOException e) {e.printStackTrace();LOGGER.e(e, "Exception initializing classifier!");Toast toast =Toast.makeText(getApplicationContext(), "Classifier could not be initialized", Toast.LENGTH_SHORT);toast.show();finish();}
// 解析输出数据
// ...

根据你的模型和任务,你可能需要根据模型的规范和文档来解析输出数据。

cc8d5bde50aea06a58a14a2b5b0820b9.png

输出解析文本数据

需要项目源码私聊

相关文章:

Android 中集成 TensorFlow Lite图片识别

在上图通过手机的相机拍摄到的物体识别出具体的名称&#xff0c;这个需要通过TensorFlow 训练的模型引用到项目中&#xff1b;以下就是详细地集成 TensorFlow步骤&#xff0c;请按照以下步骤进行操作&#xff1a; 在项目的根目录下的 build.gradle 文件中添加 TensorFlow 的 Ma…...

NSSCTF之Misc篇刷题记录(16)

NSSCTF之Misc篇刷题记录&#xff08;16&#xff09; [黑盾杯 2020]encrypt[UTCTF 2020]Spectre[UTCTF 2020]Observe closely NSSCTF平台&#xff1a;https://www.nssctf.cn/ PS&#xff1a;所有FLAG改为NSSCTF [黑盾杯 2020]encrypt UTAxSlUwTkRWRVo3Um1GclpWOWxibU55ZVhCMGFX…...

域名解析--nslookup和dig

dig (Domain Information Groper) dig 是一个功能强大且更灵活的 DNS 查询工具&#xff0c;通常在 Linux 和 macOS 等 Unix-like 操作系统上使用。以下是 dig 的一些常见用法和区别&#xff1a; 查询域名信息 dig example.com这将返回与指定域名相关的 DNS 记录&#xff0c;…...

EXCEL如何把一个单元格内的文本和数字分开?例如:龚龚15565 = 龚龚 15565

使用工具&#xff1a;WPS 举例&#xff1a; EXCEL如何把一个单元格内的文本和数字批量分开&#xff1f;不使用数据分列。 第一步、将第二行数据冻结 第二步、在B1、C1单元格输入需要分开的示例 第三步、点击选中B1单元格&#xff0c;输入快捷键【CTRLE】进行填充。B2单元格也是…...

uniapp抽取组件绑定事件中箭头函数含花括号无法解析

版本: "dcloudio/uni-ui": "^1.4.27", "vue": "> 2.6.14 < 2.7"... 箭头函数后含有花括号的时候, getData就拿不到val参数 , 解决办法就是去除花括号 // 错误代码: <SearchComp change"(val) > { getData({ val …...

猫头虎博主第四期赠书活动:《精通Go语言:(第2版) 》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

【学习总结】EasyExcel合并同列不同行,表格数据相同的行

实体类 Data HeadRowHeight(50) ContentStyle(horizontalAlignment HorizontalAlignmentEnum.CENTER, verticalAlignment VerticalAlignmentEnum.CENTER, wrapped BooleanEnum.TRUE) public class CriterionDataExportDTO {ColumnWidth(15)ExcelProperty(value "所属…...

Tokenview X-ray功能:深入探索EVM系列浏览器的全新视角

Tokenview作为一家领先的多链区块浏览器&#xff0c;为了进一步优化区块链用户的使用体验&#xff0c;我们推出了X-ray&#xff08;余额透视&#xff09;功能。该功能将帮助您深入了解EVM系列浏览器上每个地址的交易过程&#xff0c;以一种直观、简洁的方式呈现地址的进出账情况…...

【洛谷 P1364】医院设置 题解(图论+深度优先搜索)

医院设置 题目描述 设有一棵二叉树&#xff0c;如图&#xff1a; 其中&#xff0c;圈中的数字表示结点中居民的人口。圈边上数字表示结点编号&#xff0c;现在要求在某个结点上建立一个医院&#xff0c;使所有居民所走的路程之和为最小&#xff0c;同时约定&#xff0c;相邻接…...

【Java基础】- RMI原理和使用详解

【Java基础】- RMI原理和使用详解 文章目录 【Java基础】- RMI原理和使用详解一、什么RMI二、RMI原理2.1 工作原理图2.2 工作原理 三、RMI远程调用步骤3.1 RMI远程调用运行流程图3.2 RMI 远程调用步骤 四、JAVA RMI简单实现4.1 如何实现一个RMI程序4.2 JAVA实现RMI程序 一、什么…...

无水印免费4K视频素材网站 可商用-Free Stock Video

Free Stock Video是一个在线无水印免费4K视频素材网站&#xff0c;提供各种类型的4k、1080p的视频素材共免费下载&#xff0c;包括美食、水、自然、冬季、无人机、云朵、慢动作、夕阳、动态背景、缩时摄影、旅游和烟火&#xff0c;也可通过关键词搜索方式找到相关视频素材内容&…...

kubesphere中间件部署

微服务部署前中间件部署 一、MySQL部署 1.1 使用Docker实现MySQL主从复制 docker run -p 3307:3306 --name mysql-master \ -v /mydata/mysql/master/log:/var/log/mysql \ -v /mydata/mysql/master/data:/var/lib/mysql \ -v /mydata/mysql/master/conf:/etc/mysql \ -e My…...

使用 AWS S3 SDK 访问 COS-腾讯云国际站代充

腾讯云国际站对象存储&#xff08;Cloud Object Storage&#xff0c;COS&#xff09;提供了 AWS S3 兼容的 API&#xff0c;因此当用户的数据从 S3 迁移到 COS 之后&#xff0c;只需要进行简单的配置修改&#xff0c;即可让客户端应用轻松兼容 COS 服务。下面unirech小编主要介…...

c语言每日一练(15)

前言&#xff1a;每日一练系列&#xff0c;每一期都包含5道选择题&#xff0c;2道编程题&#xff0c;博主会尽可能详细地进行讲解&#xff0c;令初学者也能听的清晰。每日一练系列会持续更新&#xff0c;上学期间将看学业情况更新。 五道选择题&#xff1a; 1、程序运行的结果…...

如何利用软文推广进行SEO优化(打造优质软文,提升网站排名)

在当今的互联网时代&#xff0c;SEO优化成为了网站推广的关键。而软文推广作为一种有效的推广方式&#xff0c;其优点不仅仅局限于SEO&#xff0c;还可以带来更多的曝光和用户流量。本文将深入探讨如何做好软文推广&#xff0c;从而提升网站排名和流量。 了解目标受众群体 内容…...

Java线程池ExecutorService和Executors应用(Spring Boot微服务)

记录&#xff1a;476 场景&#xff1a;在Spring Boot微服务中使用ExecutorService管理Java线程池。使用Executors创建线程池。使用Runnable接口实现类提交线程任务到线程池执行。 版本&#xff1a;JDK 1.8,Spring Boot 2.6.3。 1.线程和线程池基础 JDK自带线程和线程池包位…...

机器学习笔记之最优化理论与方法(八)无约束优化问题——常用求解方法(中)

机器学习笔记之最优化理论与方法——基于无约束优化问题的常用求解方法[中] 引言回顾&#xff1a;最速下降算法的缺陷经典牛顿法基本介绍经典牛顿法的问题经典牛顿法的优点与缺陷经典牛顿法示例 修正牛顿法介绍拟牛顿法拟牛顿法的算法过程 矩阵 B k 1 \mathcal B_{k1} Bk1​的…...

Django系列:Django简介与MTV架构体系概述

Django系列 Django简介与MTV架构体系概述 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/132890054 【介…...

锐捷交换机WEB管理系统EXCU_SHELL密码信息泄漏漏洞

一、漏洞简介 锐捷交换机 WEB 管理系统 EXCU_SHELL存在密码信息泄露漏洞&#xff0c;攻击者可从漏洞获取到管理员账号密码&#xff0c;从而以管理员权限登录。 二、影响版本 锐捷交换机 WEB 管理系统 三、资产测绘 hunterweb.body"img/free_login_ge.gif"&&…...

线性代数(六) 线性变换

前言 《线性空间》定义了空间&#xff0c;这章节来研究空间与空间的关联性 函数 函数是一个规则或映射&#xff0c;将一个集合中的每个元素&#xff08;称为自变量&#xff09;映射到另一个集合中的唯一元素&#xff08;称为因变量&#xff09;。 一般函数从 “A” 的每个元…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...