本教程将带你逐步掌握在 Android 移动设备上部署机器学习模型的全流程。我们将从模型训练入手,随后将其转换为 TensorFlow Lite 格式,最后构建一个完整的 Android 应用程序,实现实时图像分类与结果展示。无论你是刚接触移动端机器学习的新手,还是希望将现有模型迁移到手机上的资深工程师,都能从中获得清晰且实用的指导。
一、模型的训练与转换
我们以经典的 MobileNet 模型为例,在 ILSVRC-2012-CLS 图片数据集上进行训练。训练过程需要在性能较强的 Linux 机器上完成。
1. 克隆 TensorFlow 模型库
打开终端,运行以下命令获取源代码:
git clone https://github.com/tensorflow/models.git
2. 安装构建系统 Bazel
根据官方文档安装 Bazel:
https://docs.bazel.build/versions/master/install.html
3. 启动模型训练
执行以下命令开始训练,并生成 *.tflite 格式的模型文件:
bazel build -c opt mobilenet_v1_{eval,train}
./bazel-bin/mobilenet_v1_train --dataset_dir 图片集的路径
--checkpoint_dir 检查点的路径
注意: 如果你使用的是自定义 TensorFlow 模型,训练完成后需要使用 TensorFlow Lite 转换器 将其转换为 .tflite 格式。本例中 MobileNet 训练后直接生成该格式,因此不需要额外转换。
二、Android 应用程序开发
我们将构建一个包含以下核心功能的 App:
- 实时从摄像头捕获图像
- 使用 TensorFlow Lite 模型进行图像分类
- 在屏幕上显示分类结果
你可以从 GitHub 示例仓库 中的 “image_classification” 示例项目开始作为模板。
2.1 实时图像捕捉
利用 android.hardware.camera2 框架(Android 5.0 及以上版本可用)。通过 CameraManager 系统服务访问摄像头,并实现 OnImageAvailableListener 接口,在 onImageAvailable 方法中接收每一帧图像。
为了将摄像头画面显示在屏幕上,请在布局中添加一个 TextureView 组件,并将其与相机输出关联。注意在屏幕底部预留一小块区域,用于显示分类结果。
在 onImageAvailable 方法中:
- 调用
acquireLatestImage()获取最后一帧(跳过积压的旧帧,避免分类耗时导致画面卡顿)。 - 帧数据格式为 YUV420,需要转换为 ARGB8888 格式(使用
ImageUtils库的convertYUV420方法)。 - 最终将图像转换为范围 -1 到 1 的单精度浮点数数组,供模型输入。
2.2 图像分类
在应用启动时,需要从 assets 目录加载模型文件和标签文件。确保将训练阶段获得的 mobilenet_v1_1.0_224.tflite 和分类标签文件 label.txt 拷贝到 assets 目录下。
创建 TensorFlow Lite 解释器 对象,将模型文件作为构造函数参数传入:
Interpreter tflite = new Interpreter(loadModelFile());
分类时调用 tflite.run() 方法,第一个参数为预处理后的浮点数数组(即从摄像头获取的帧),第二个参数为输出数组(浮点数数组)。输出数组的每个元素代表对应类别的概率。
小提示: 如果设备性能较差,可以降低输入图片的分辨率(例如 224×224 改为 192×192),但需同步调整模型输入尺寸。
2.3 显示分类结果
从 label.txt 中预加载所有类别名称(默认英文,可按需修改为中文)。遍历输出概率数组,找到概率最高的类别,并将其名称显示在屏幕预留区域。
你也可以同时显示概率最高的 3~5 个 类别及其概率,帮助用户理解模型判断的置信度分布。
三、常见问题
- Q:训练好的模型文件很大,无法放入 assets 目录?
A:TensorFlow Lite 针对移动端进行了优化,MobileNet 等轻量模型通常只有几 MB。如果模型过大,可考虑使用模型量化(quantization)技术,将浮点权重转换为 8 位整数,显著减小体积并加速推理。 - Q:分类结果总是“unknown”或错误?
A:请检查label.txt中类别顺序是否与模型训练时一致,以及输入图像的预处理方式(归一化范围、尺寸)是否匹配模型要求。 - Q:实时预览画面卡顿或分类延迟很高?
A:确保在onImageAvailable中使用了acquireLatestImage()而非acquireNextImage(),避免积压帧。同时考虑在后台线程执行分类操作,避免阻塞主线程。
总结
通过以上步骤,你已经学会了如何训练一个 MobileNet 图像分类模型,并将其转换为 TensorFlow Lite 格式,最终在 Android 设备上构建具备实时摄像头分类能力的应用。TensorFlow Lite 不仅仅适用于 Android,其 C++ 接口还可让模型运行在嵌入式设备上,占用内存仅约 300 KB。现在你可以尝试更换自己的数据集,打造专属的移动端 AI 应用了!
