在Android端使用TensorFlow

本篇文章中软件的下载需要科学上网支持。
主要参考资料为这篇文章,但是原文章涉及的TF版本已经过旧,有些小坑,例如android工程几个项目文件的修改,已经完全不同了。
TensorFlow的一个很突出的优势是跨平台,但是这方面的资料还比较少。
不过最近随着1.0版本的发布,文档的逐渐完善,在移动端的应用也越来越都多,并且官方增加了两个demo。其实应用在移动端还是比较容易的,只是因为官方的文档还是太省略,并且如果没有前两篇(12)的铺垫知识,看起来容易一头雾水。还有一个复杂的地方是,如果需要自定义app需要用到一些Android编程的知识,并且Google的Bazel编译工具也实在是太小众了。鉴于这些坑,将项目的心得分享记录于此,以供参考,节省大家的时间。
通过前两篇博客(12),我们通过重新训练获得了权重值文件(retrained_graph.pb)和标签文件(retrained_labels.txt),利用这两个文件和官方给的demo代码,就可以简单实现在移动端(因为我手上只有Android设备,因此仅针对Android)的实时识别。
编译Android端的app需要用到Android的SDKNDK,首先下载这两个工具集。不过我推荐先下载Android Studio,使用Android Studio管理SDK与NDK,这样下载,管理和升级比较方便,而且毕竟以后可能还要调整demo,要用到Android的开发IDE。下载过程就不详细描述了,Android开发者网站有很详细的步骤。
有了SDK与NDK后,就可以着手利用我们重训练的权重值文件与标签编译app了。首先,需要告诉TensorFlow SDK与NDK的路径。浏览至tensorflow目录,打开WORKSPACE文件,在文件第10行左右,会看到以下代码:

# Uncomment and update the paths in these entries to build the Android demo.
#android_sdk_repository(
#    name = "androidsdk",
#    api_level = 23,
#    build_tools_version = "23.0.1",
#    # Replace with path to Android SDK on your system
#    path = "",
#)
#
#android_ndk_repository(
#    name="androidndk",
#    path="",
#    api_level=21)

首先删除行首的井号取消注释,随后编辑””和””为你的SDK与NDK路径,同时注意修改SDK的api_level和build_tools_version与NDK的api_level为下载的版本。若使用Android Studioi下载SDK与NDK则在SDK Manager中可以看到对应的版本。若是单独下载的SDK与NDK,则文件名会有版本号体现。(目前分别是25,25.0.2,24,注意版本号可能会随时间改变),修改完是这样的:

# Uncomment and update the paths in these entries to build the Android demo.
android_sdk_repository(
    name = "androidsdk",
    api_level = 25,
    build_tools_version = "25.0.2",
    # Replace with path to Android SDK on your system
    path = "/home/hp/Android/Sdk",
)

android_ndk_repository(
    name="androidndk",
    path="/home/hp/Android/Sdk/ndk-bundle",
    api_level=24)

源码目录中,tensorflow/examples/android是我们重点关注的内容,这里存放了demo源代码。
接下来,编译对权重文件优化的优化工具,因为要在移动端使用,因此要优化权重值文件:

$ cd ~/tensorflow
$ bazel build tensorflow/python/tools:optimize_for_inference

随后,优化权重值文件:

$ bazel-bin/tensorflow/python/tools/optimize_for_inference \
--input=/home/hp/Downloads/flower/retrained_graph.pb \
--output=tensorflow/examples/android/assets/retrained_graph.pb \
--input_names=Mul \
--output_names=final_result

把标签文件也拷贝进来:

$ cp /home/hp/Downloads/flower/retrained_labels.txt /your_path/tensorflow/tensorflow/examples/android/assets/

由于我们使用自己的权重值文件,因此在编译过程中不需要再次下载Inception模型文件了(当然这步不做也可以,只不过编译过程会再次下载Inception模型),打开tensorflow/examples/android/BUILD文件,搜索inception,在67行左右,添加井号注释掉即可。
由于我们使用的权重值文件名称是自定的(retrained_graph.pb),因此需要修改demo代码:
打开/your_path/tensorflow/tensorflow/examples/android/src/org/tensorflow/demo/ClassifierActivity.java文件,文件开头import部分后,有注释,根据注释,我们修改源代码:

private static final int NUM_CLASSES = 1001;//类别+1
  private static final int INPUT_SIZE = 224;
  private static final int IMAGE_MEAN = 117;
  private static final float IMAGE_STD = 1;
  private static final String INPUT_NAME = "input:0";
  private static final String OUTPUT_NAME = "output:0";

  private static final String MODEL_FILE = "file:///android_asset/tensorflow_inception_graph.pb";//权重值文件名
  private static final String LABEL_FILE =
      "file:///android_asset/imagenet_comp_graph_label_strings.txt";//标签文件名

为:

private static final int NUM_CLASSES = 6;
  private static final int INPUT_SIZE = 299;
  private static final int IMAGE_MEAN = 128;
  private static final float IMAGE_STD = 128;
  private static final String INPUT_NAME = "Mul:0";
  private static final String OUTPUT_NAME = "final_result:0";

  private static final String MODEL_FILE = "file:///android_asset/retrained_graph.pb";
  private static final String LABEL_FILE =
      "file:///android_asset/retrained_labels.txt";

接下来就可以编译apk文件并安装啦!
首先安装adb工具集(其实SDK中有,但是为了方便使用,还是安装一下):

sudo apt-get install adb

打开手机的USB调试模式,连接电脑,用adb命令先查看手机是否成功连接:

$ sudo adb devices

若命令输出不为空,并且有xxxxxx device字样,则说明连接成功。
随后,编译apk文件并上传安装:

$ cd /your_path/tensorflow
$ bazel build //tensorflow/examples/android:tensorflow_demo
$ adb install -r -g bazel-bin/tensorflow/examples/android/tensorflow_demo.apk

在手机上打开应用即可。
在电脑屏幕上显示一张训练集图片,测试结果如图所示(单击音量下键显示详细信息):

可以看出,app给出了正确的分类,并且置信率很高。

如果您觉得作者的博客对您有用,不妨鼓励作者一下,作者将会更加努力写出高质量博客。

Leave a Reply

Your email address will not be published. Required fields are marked *