当前位置: 首页 > 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” 的每个元…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

Vue 3 + WebSocket 实战:公司通知实时推送功能详解

&#x1f4e2; Vue 3 WebSocket 实战&#xff1a;公司通知实时推送功能详解 &#x1f4cc; 收藏 点赞 关注&#xff0c;项目中要用到推送功能时就不怕找不到了&#xff01; 实时通知是企业系统中常见的功能&#xff0c;比如&#xff1a;管理员发布通知后&#xff0c;所有用户…...

鸿蒙HarmonyOS 5军旗小游戏实现指南

1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;采用DevEco Studio实现&#xff0c;包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...

Go爬虫开发学习记录

Go爬虫开发学习记录 基础篇&#xff1a;使用net/http库 Go的标准库net/http提供了完善的HTTP客户端功能&#xff0c;是构建爬虫的基石&#xff1a; package mainimport ("fmt""io""net/http" )func fetchPage(url string) string {// 创建自定…...