TensorFlow Lite for Android示例

一、TensorFlow  Lite

TensorFlow Lite 是用于移动设备和嵌入式设备的轻量级解决方案。TensorFlow Lite 支持 Android、iOS 甚至树莓派等多种平台。

二、tflite格式

TensorFlow 生成的模型是无法直接给移动端使用的,需要离线转换成.tflite文件格式。

tflite 存储格式是 flatbuffers。

FlatBuffers 是由Google开源的一个免费软件库,用于实现序列化格式。它类似于Protocol Buffers、Thrift、Apache Avro。

因此,如果要给移动端使用的话,必须把 TensorFlow 训练好的 protobuf 模型文件转换成 FlatBuffers 格式。官方提供了 toco 来实现模型格式的转换。

三、API

TensorFlow Lite 提供了 C ++ 和 Java 两种类型的 API。无论哪种 API 都需要加载模型和运行模型。

而 TensorFlow Lite 的 Java API 使用了 Interpreter 类(解释器)来完成加载模型和运行模型的任务。后面的例子会看到如何使用 Interpreter。

四、TensorFlow Lite实现手写数字识别

下面的 demo 中已经包含了 mnist.tflite 模型文件。(如果没有的话,需要自己训练保存成pb文件,再转换成tflite 格式)

对于一个识别类,首先需要初始化 TensorFlow Lite 解释器,以及输入、输出。

    // The tensorflow lite file
    private lateinit var tflite: Interpreter

    // Input byte buffer
    private lateinit var inputBuffer: ByteBuffer

    // Output array [batch_size, 10]
    private lateinit var mnistOutput: Array<FloatArray>

    init {

        try {
            tflite = Interpreter(loadModelFile(activity))

            inputBuffer = ByteBuffer.allocateDirect(
                    BYTE_SIZE_OF_FLOAT * DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE)
            inputBuffer.order(ByteOrder.nativeOrder())
            mnistOutput = Array(DIM_BATCH_SIZE) { FloatArray(NUMBER_LENGTH) }
            Log.d(TAG, "Created a Tensorflow Lite MNIST Classifier.")
        } catch (e: IOException) {
            Log.e(TAG, "IOException loading the tflite file failed.")
        }

    }

从 asserts 文件中加载 mnist.tflite 模型:

    /**
     * Load the model file from the assets folder
     */
    @Throws(IOException::class)
    private fun loadModelFile(activity: Activity): MappedByteBuffer {

        val fileDescriptor = activity.assets.openFd(MODEL_PATH)
        val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
        val fileChannel = inputStream.channel
        val startOffset = fileDescriptor.startOffset
        val declaredLength = fileDescriptor.declaredLength
        return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
    }

真正识别手写数字是在 classify() 方法:

val digit = mnistClassifier.classify(Bitmap.createScaledBitmap(paintView.bitmap, PIXEL_WIDTH, PIXEL_WIDTH, false))

classify() 方法包含了预处理用于初始化 inputBuffer、运行 mnist 模型、识别出数字。

    /**
     * Classifies the number with the mnist model.
     *
     * @param bitmap
     * @return the identified number
     */
    fun classify(bitmap: Bitmap): Int {

        if (tflite == null) {
            Log.e(TAG, "Image classifier has not been initialized; Skipped.")
        }

        preProcess(bitmap)
        runModel()
        return postProcess()
    }

    /**
     * Converts it into the Byte Buffer to feed into the model
     *
     * @param bitmap
     */
    private fun preProcess(bitmap: Bitmap?) {

        if (bitmap == null || inputBuffer == null) {
            return
        }

        // Reset the image data
        inputBuffer.rewind()

        val width = bitmap.width
        val height = bitmap.height

        // The bitmap shape should be 28 x 28
        val pixels = IntArray(width * height)
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height)

        for (i in pixels.indices) {
            // Set 0 for white and 255 for black pixels
            val pixel = pixels[i]
            // The color of the input is black so the blue channel will be 0xFF.
            val channel = pixel and 0xff
            inputBuffer.putFloat((0xff - channel).toFloat())
        }
    }

    /**
     * Run the TFLite model
     */
    private fun runModel() = tflite.run(inputBuffer, mnistOutput)

    /**
     * Go through the output and find the number that was identified.
     *
     * @return the number that was identified (returns -1 if one wasn‘t found)
     */
    private fun postProcess(): Int {

        for (i in 0 until mnistOutput[0].size) {
            val value = mnistOutput[0][i]
            if (value == 1f) {
                return i
            }
        }

        return -1
    }

对于 Android 有一个地方需要注意,必须在 app 模块的 build.gradle 中添加如下的语句,否则无法加载模型。

android {
    ......
    aaptOptions {
        noCompress "tflite"
    }
}

效果:

五、总结

本文 demo 的 github 地址:https://github.com/fengzhizi715/TFLite-MnistDemo

当然,也可以跑一下官方的例子:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/examples/android/app

虽然准确度都不咋地。。。

更多有趣的TensorFlow Lite示例:https://www.tensorflow.org/lite/examples/

参考链接:https://www.jianshu.com/p/e96f80c80e43

原文地址:https://www.cnblogs.com/lfri/p/11767265.html

时间: 2024-08-30 11:55:33

TensorFlow Lite for Android示例的相关文章

移动端目标识别(3)——使用TensorFlow Lite将tensorflow模型部署到移动端(ssd)之Running on mobile with TensorFlow Lite (写的很乱,回头更新一个简洁的版本)

承接移动端目标识别(2) 使用TensorFlow Lite在移动设备上运行         在本节中,我们将向您展示如何使用TensorFlow Lite获得更小的模型,并允许您利用针对移动设备优化的操作. TensorFlow Lite是TensorFlow针对移动和嵌入式设备的轻量级解决方案.它支持端上的机器学习推理,具有低延迟和小二进制模型大小. TensorFlow Lite使用了许多技术,例如允许更小和更快(定点数学)模型的量化内核. 对于本节,您需要从源代码构建TensorFlow

AoE 搭档 TensorFlow Lite ,让终端侧 AI 开发变得更加简单。

AoE( AI on Edge , https://github.com/didi/AoE ) 是滴滴近期开源的终端侧 AI 集成运行时环境 ( IRE ). 随着人工智能技术快速发展,近几年涌现出了许多运行在终端的高性能推理框架,例如 TensorFlow Lite,在实时性.安全性上给开发者带来更多支持和选择,极大的优化了用户的使用体验,但当我们想要在终端侧落地一些具体的 AI 业务时,会发现有些不得不面对的问题: 除了要做推理框架选型,还需要关注数据预 / 后处理逻辑的稳定性,模型分发使用

ArcGIS for Android示例解析之离线地图-----LocalTiledLayer

转自:http://blog.csdn.net/wozaifeiyang0/article/details/7327423 LocalTiledLayer 看到这个标题是否是很激动,如题,该示例就是添加一个离线地图,这应该是很多开发人员期盼已久的功能了吧,正式版一处这个应该是一个很大的亮点,原来操作离线地图如此简单,下面来看一下代码: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSta

Tensorflow Lite tflite模型的生成与导入

假如想要在ARM板上用tensorflow lite,那么意味着必须要把PC上的模型生成tflite文件,然后在ARM上导入这个tflite文件,通过解析这个文件来进行计算. 根据前面所说,tensorflow的所有计算都会在内部生成一个图,包括变量的初始化,输入定义等,那么即便不是经过训练的神经网络模型,只是简单的三角函数计算,也可以生成一个tflite模型用于在tensorflow lite上导入.所以,这里我就只做了简单的sin()计算来跑一编这个流程. 生成tflite模型 这部分主要是

ArcGIS for Android示例解析之空间查询-----QueryTask

转自:http://blog.csdn.net/wozaifeiyang0/article/details/7331450 QueryTask 查询功能在GIS中是一个不可或缺的重要功能,示例中提供了一个属性查询的Demo,下面来看一下在Android中我们怎样实现一个查询功能, 1.              我们在布局文件中添加了一个按钮,并且在代码中添加了这个按钮的点击事件监听: 2.              自定义一个 AsyncTask的扩展类,在此类中我们实现了查询功能. 3.  

Lite Your Android English

https://litesuits.com/ 一些话 简约的背后,往往是复杂 还原面向对象应有的体验,让应对繁多业务所增加的,并未增加. 展开设计理念 Lite每个项目仅几十KB,这相当于你项目中一张小图片,如此迷你. 展开用户评论 我的开源项目 LiteGo 代号: let it go LiteGo 是一款基于Java语言的异步并发类库,它的核心是一枚「迷你」并发器. LiteGo 可以自由地设置同一时段的最大并发数量,等待排队线程数量,还可以设置排队策略和超载策略. 它的核心组件是 「Sma

ArcGIS for Android示例解析之高亮要素-----HighlightFeatures

转自:http://blog.csdn.net/wozaifeiyang0/article/details/7323606 HighlightFeatures 要素高亮化功能,相信有其他gis开发经营的开发人员都有过相应的实现经验,对于高亮要素,简单说起来就是我们查询的或识别出来的要素进行渲染,让其突出显示而已,这个例子中涉及后面要介绍的识别的内容,我们只简单介绍相关的知识,主要介绍要素对象的渲染(也就是所谓的高亮),来看代码: mapView.setOnLongPressListener(ne

Android示例程序剖析之记事本(一)

Android SDK提供了很多示例程序,从这些示例代码的阅读和试验中能够学习到很多知识.本系列就是要剖析Android记事本示例程序,用意就是一步步跟着实例进行动手操作,在实践中体会和学习Android开发.该系列共有四篇文章,本文是第一篇. 前期准备 搭建开发环境,尝试编写"Hello World”,了解Android的基本概念,熟悉Android的API(官方文档中都有,不赘述). 记事本程序运行界面 先来简单了解下程序运行的效果: 程序入口点 类似于win32程序里的WinMain函数,

如何使用TensorFlow Hub和代码示例

任何深度学习框架,为了获得成功,必须提供一系列最先进的模型,以及在流行和广泛接受的数据集上训练的权重,即与训练模型. TensorFlow现在已经提出了一个更好的框架,称为TensorFlow Hub,它非常易于使用且组织良好.使用TensorFlow Hub,您可以通过几行代码导入大型和流行的模型,自信地执行广泛使用的传输学习活动.TensorFlow Hub非常灵活,可以托管您的模型以供其他用户使用.TensorFlow Hub中的这些模型称为模块.在本文中,让我们看看如何使用TensorF