65.9K
CodeProject 正在变化。 阅读更多。
Home

将 AI 风格迁移 TensorFlow Lite 模型添加到 Android 应用

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (4投票s)

2021年7月28日

CPOL

4分钟阅读

viewsIcon

9161

在本文中,我们将向您展示如何设置一个适合加载和运行我们的.tflite模型的Android Studio环境。

引言

在本系列文章中,我们将介绍一个基于Cycle-Consistent Adversarial Networks (CycleGAN)的移动图像到图像翻译系统。我们将构建一个可以执行非配对图像到图像翻译的CycleGAN,并向您展示一些有趣但学术性很深的例子。我们还将讨论如何将使用TensorFlow和Keras构建的训练好的网络转换为TensorFlow Lite并在移动设备上用作应用程序。

我们假设您熟悉深度学习的概念,以及Jupyter Notebooks和TensorFlow。欢迎您下载项目代码。

在上一篇文章中,我们保存并加载了TensorFlow Lite(.tflite)模型。在本文中,我们将将其加载到Android Studio中,并选择合适的TensorFlow Lite Android支持库来运行推理。

准备Android Studio环境

构建Android应用的第一步是下载Android Studio。下载完成后,我们将通过将我们的.tflite模型导入Android Studio文件来开始所谓的“机器学习(ML)和模块依赖绑定”。

要将模型导入Android Studio,请右键单击要使用TFLite模型的模块,或选择文件 > 新建 > 其他 > TensorFlow Lite 模型

然后,选择您的TFLite文件的位置。请注意,该工具将代表您配置模块与ML Model绑定的依赖关系,并将所有依赖项自动插入您的Android模块的build.gradle文件中。

之后,单击完成

选择TensorFlow Lite解释器和Android支持库

为了解释模型输出,我们必须将TensorFlow Lite Android支持库集成到我们的应用程序中。这将提供高级API,帮助转换和预处理原始输入数据,以适应模型期望的大小和格式。

此解释器库支持常见的输入和输出数据格式,包括图像和数组。此外,该库还包含一些预处理功能,例如图像缩放和裁剪。

导入Gradle依赖项和其他设置

要导入Gradle依赖项,我们首先将.tflite模型文件复制到模型将运行的Android模块的assets目录中。我们指定文件不应被压缩,并将TensorFlow Lite库添加到模块build.gradle文件中。

dependencies {
    // Other dependencies

    // Import tflite dependencies
    implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly-SNAPSHOT'
    // The GPU delegate library is optional. If needed, select the second checkbox for importing TensorFlow GPU if you want to use GPU acceleration.
    implementation 'org.tensorflow:tensorflow-lite-gpu:0.0.0-nightly-SNAPSHOT'
    implementation 'org.tensorflow:tensorflow-lite-support:0.0.0-nightly-SNAPSHOT'
}

在Android上部署模型

此时,我们有一个存储在文件tflite_model.tflite中的神经网络。如果我们想使用它,我们需要创建一个新项目(例如,命名为CycleGAN_App),使用Android Studio,并将我们的模型文件放在CycleGAN_App/app/src/main/assets文件夹中。由于Android Studio默认会出于性能原因压缩资源文件,因此我们还需要通过在gradle文件中添加以下行来明确告诉它不要压缩神经网络:

aaptOptions {
    noCompress "tflite" 
}

其次,我们需要添加所需的依赖项:使用以下行更新gradle文件

implementation 'org.tensorflow:tensorflow-lite:1.13.1'

为了演示移动图像到图像翻译,我们创建了一个简单的Android应用,其中包含一个按钮,用于上传图像,通过我们的TensorFlow Lite模型运行它,并显示翻译后的图像。

您可以下载项目代码来查看它的实际运行效果!尽管对应用程序代码的全面讨论超出了本文的范围,但我们将在接下来的部分中探讨其最重要的部分。

导入基本的图像处理和转换方法

在将图像输入模型之前,我们必须将其转换为模型可以处理的大小和格式。

为了使用Tensorflow Lite的图像处理和转换方法,我们必须创建一个ImagePreprocessor并添加所需的操作。为了将图像转换为TensorFlow Lite解释器所需的张量格式,请创建一个TensorImage用作输入。

import org.tensorflow.lite.support.image.ImageProcessor;
import org.tensorflow.lite.support.image.TensorImage;
import org.tensorflow.lite.support.image.ops.ResizeOp;

// Initialization code
// Create an ImageProcessor with all ops required. For more ops,
// refer to the ImageProcessor Architecture section in this README.
ImageProcessor imageProcessor =
    new ImageProcessor.Builder()
        .add(new ResizeOp(224, 224, ResizeOp.ResizeMethod.BILINEAR))
        .build();

// Create a TensorImage object. This creates the tensor of the corresponding
// tensor type (uint8 in this case) that the TensorFlow Lite interpreter needs.
TensorImage tImage = new TensorImage(DataType.UINT8);

// Analyse code for every frame
// Preprocess the image
tImage.load(bitmap);
tImage = imageProcessor.process(tImage);

创建输出对象并运行模型

为了运行我们的模型,我们需要创建将用于存储结果的容器对象(TensorBuffer)。

import org.tensorflow.lite.support.tensorbuffer.TensorBuffer;

// Create a container for the result and specify that this is a quantized model
// Hence, the 'DataType' is defined as UINT8 (8-bit unsigned integer)
TensorBuffer probabilityBuffer =
    TensorBuffer.createFixedSize(new int[]{1, 1001}, DataType.UINT8);

加载模型并运行推理

import org.tensorflow.lite.support.model.Model;

// Initialise the model
try{
    MappedByteBuffer tfliteModel
        = FileUtil.loadMappedFile(activity,
            "mobilenet_v1_1.0_224_quant.tflite");
    Interpreter tflite = new Interpreter(tfliteModel)
} catch (IOException e){
    Log.e("tfliteSupport", "Error reading model", e);
}

// Run inference
if(null != tflite) {
    tflite.run(tImage.getBuffer(), probabilityBuffer.getBuffer());
}

开发ImageProcessor架构

如上所述,ImageProcessor支持一些基本的图像处理方法,即裁剪、缩放和旋转。

int width = bitmap.getWidth();
int height = bitmap.getHeight();

int size = height > width ? width : height;

ImageProcessor imageProcessor =
    new ImageProcessor.Builder()
        // Center crop the image to the largest square possible
        .add(new ResizeWithCropOrPadOp(size, size))
        // Resize using Bilinear or Nearest neighbour
        .add(new ResizeOp(224, 224, ResizeOp.ResizeMethod.BILINEAR));
        // Rotate counter-clockwise in 90 degree increments
        .add(new Rot90Op(rotateDegrees / 90))
        .add(new NormalizeOp(127.5, 127.5))
        .add(new QuantizeOp(128.0, 1/128.0))
        .build();

实现量化

在初始化我们的输入和输出对象(例如TensorImageTensorBuffer)时,我们需要将对象类型指定为DataType.UINT8DataType.FLOAT32

TensorImage tImage = new TensorImage(DataType.UINT8);
TensorBuffer probabilityBuffer =
    TensorBuffer.createFixedSize(new int[]{1, 1001}, DataType.UINT8);

TensorProcessor用于量化输入张量或反量化输出张量。

import org.tensorflow.lite.support.common.TensorProcessor;

// Post-processor that dequantizes the result
TensorProcessor probabilityProcessor =
    new TensorProcessor.Builder().add(new DequantizeOp(0, 1/255.0)).build();
TensorBuffer dequantizedBuffer = probabilityProcessor.process(probabilityBuffer);

最终结果:一个利用图像到图像翻译将驴子变成斑马的Android应用!

结论

我们已经完成了这个系列。我们希望阅读它能帮助您实现自己的图像到图像翻译应用程序。如果您喜欢本系列中的内容,请永远记住您可以改进它!为什么不利用您新学的技能,创造一些伟大的东西,然后在CodeProject上撰写并分享呢?

© . All rights reserved.