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






4.75/5 (4投票s)
在本文中,我们将向您展示如何设置一个适合加载和运行我们的.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();
实现量化
在初始化我们的输入和输出对象(例如TensorImage
或TensorBuffer
)时,我们需要将对象类型指定为DataType.UINT8
或DataType.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上撰写并分享呢?