Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移

转载: http://mp.weixin.qq.com/s/ZUaxGPgqAGrN9itwRnSL2A

详解如何将TensorFlow训练的模型移植到安卓手机

http://mp.weixin.qq.com/s/yBGoANoWh4Grk-PS3qxmfg


最近上Github,发现 Tensor flow的 Android demo又更新了,除了基本的修改以外,又增加了一个图像风格迁移的安卓demo,而且还增加了Android Studio 的编译支持,迫不及待的移植到手机上试了一下。

本文是TensorFlow官网教程:将 TensorFlow 深度学习模型,移植到安卓手机,进行物体识别、行人检测和图像风格迁移的一个具体实现过程。(教程主页见: TensorFlow Mobile)

该教程一共实现了三个简单的深度学习模型移植:

1、TensorFlow Classify: 实时物体分类 
2、TensorFlow Detect: 实时行人检测 
3、TensorFlow Stylize: 实时图像风格迁移

具体使用的模型和算法可以参考上面的官方链接,我这里只谈移植过程,算法就不讲啦。

该教程提供了 Android、IOS、Raspberry Pi三种手机操作系统的支持。我只实现了Android移植,所以本文以Android移植为例。

先来看一下结果演示吧,增加点做下去的动力~ Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第1张图片

1、实时物体分类

该程序的主要功能是对现实生活中的物体进行实时分类。打开移植好的程序,手机屏幕对准物体,这时上方会实时显示识别结果。算法的实时性很强,基本没有延迟。

如下图是对一支笔进行识别,识别结果会按照置信度进行分类,下图中识别为ballpen的置信度最高,大概0.16,奇怪的是竟然还有0.1的置信度为锤子(hammer)。由于训练集中的分类有限,现实生活中的不少物体不能得到准确的结果。比如我桌子上的地球仪就被识别为bubble,很可能训练集中就没有地球仪这个单词吧。


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第2张图片

2、实时行人识别

这个主要是对现实生活中的行人进行识别。可以支持同时对多人进行识别。算法实时性不错,没有延时。屏幕会实时框出检测到的人员,如下图。图中开启了配置模式,屏幕上蓝色的点表示特征点,该算法可以跟踪特征点的光流。

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第3张图片

屏幕的下方显示的是神经网络的信息。后面那个蜡笔小新不管远近都无法识别,可能是身体比例太不协调了吧。

3、实时风格化迁移

将手机对准屏幕,软件可以实时的将摄像头拍摄到的内容转换为艺术图片风格。如下图,对地球仪和矿泉水瓶的风格化迁移结果。还是蛮有艺术风的。

这个demo的功能还是挺强大的。下方是配置选项。512是分辨率设置,点击可以实时选择要显示的分辨率,最大1024。后面好几排是各种不同的风格。点击就可以进行实时风格的切换。更强大的是,它可以实时混合不同的风格,下图中高亮的四部分就是我当前选择的几种风格,按照比例进行混合,用手指拖动可以实时调整不同风格的占比。这一点真心强大。


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第4张图片


挺好玩的吧,下面手把手讲授具体操作方法。


我的电脑环境

笔记本:ThinkPad T450 X86_64 
显卡:主显 Intel HD Graphics 5500 ; 独显 NVIDIA GT 940M 
系统环境:Ubuntu14.04 64位、Windows7 64位 双系统 
CUDA 版本: 8.0 
cudnn 版本: v5.1 
TensorFlow版本: master 
Bazel版本: 0.4.3 
安卓手机: 联想 PB2-690N


一、下载 TensorFlow 项目源码

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第5张图片

如果想实现将TensorFlow训练的模型移植到安卓手机,首先需要下载tensorflow的项目源码。

TensorFlow项目源码下载地址

注意!!

TensorFlow的源码 r0.12版本中只包含 TF-Classify一个模型的实现,需下载master版本才能包含全部的三个模型实现。

在项目中,android demo的源码位置是

//tensorflow/examples/android


二、安装Bazel

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第6张图片

电脑还需要安装Bazel,这个我在源码安装TensorFlow的时候就已经装好,还没装的同学可以参考我的另一篇文章,文中前半部分有写如何安装Bazel。

Ubuntu14.04 源代码安装 TensorFlow r0.12 详细教程


三、安装 SDK

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第7张图片

1、下载SDK,并将其解压到从github下载的tensorflow源代码根目录下 
(注:其实可以安装在任意目录下,我这里以安装在tensorflow目录为例。)

$ wget https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz

$ tar xvzf android-sdk_r24.4.1-linux.tgz -C ~/tensorflow

2、 更新SDK和安装 SDK build tools

$ cd  ~/tensorflow/android-sdk-linux

$ sudo  tools/android  update  sdk --no-ui

(注:不加sudo 会报错,提示failed to fetch URL)


四、安装 NDK

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第8张图片

下载 NDK,解压到tensorflow根目录下 
(注:其实可以安装在任意目录下,我这里以安装在tensorflow目录为例。)

$ wget https://dl.google.com/android/repositor/android-ndk-r12b-linux-x86_64.zip

$ unzip android-ndk-r12b-linux-x86_64.zip -d ~/tensorflow


五、修改 WORKSPACE 文件

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第9张图片

在tensorflow的根目录下,找到WORKSPACE文件。打开文件, 上方有两段包含 android_sdk_repository和 android_ndk_repository的内容(该段内容已经加了#被注释掉了),将这两段内容在文件中复制一遍,并将复制后的内容反注释掉。然后:

a) 分别将sdk path和 ndk path更改为自己安装的SDK和NDK路径(例如我的是tensorflow根目录下的相对路径)

b) 将sdk api level更改为自己电脑中安装的最高版本

c) 将sdk的build_tools_version更改为自己安装的版本

其他保持不变


六、下载模型 (可选)

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第10张图片

andriod demo源码是不包含训练好的tensorflow模型的,但是在编译时需要模型。模型一共有三个,分别对应物体识别、行人检测和图像风格迁移。

在Bazel编译时,可以不用手动下载模型,因为在文件//tensorflow/examples/android/BUILD中设定了自动下载模型的操作。

但是如果使用Android Studio等其他方式编译,则不会运行BUILD文件中的自动下载操作。

手动下载模型zip文件:

$ curl -L https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip -o /tmp/inception5h.zip

$ curl -L https://storage.googleapis.com/download.tensorflow.org/models/mobile_multibox_v1.zip -o /tmp/mobile_multibox_v1.zip

$ curl -L https://storage.googleapis.com/download.tensorflow.org/models/mobile_multibox_v1.zip -o /tmp/stylize_v1.zip

将上述三个zip文件分别解压到文件夹: 
//tensorflow/examples/android/assets

解压完毕后,打开//tensoeflow/examples/android/BUILD文件,找到以 android_binary 开头的那段代码片,将 assets = [ ] 内以@开头的三句代码用#号 注释掉,如下图黄色部分所示


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第11张图片

如果不注释掉该段内容,即使手动将模型放在assets文件中,使用bazel编译时也会重新下载模型。

七、连接安卓手机

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第12张图片

1、安装 adb$ sudo  apt-get  install android-tools-adb

2、 将手机设置为debug模式

打开安卓手机,找到 usb debugging 按钮,我的手机是:

setting-general-developer options-enable USB debugging 
(每个手机可能具体的不太一样)

然后手机通过USB数据线连接电脑,此时手机屏幕会提示: 
allow USB debugging?

勾选 always allow from this computer,然后点击ok。(之后再连接则不会提示)

3、 从电脑端检查 手机是否连接成功

$adb devices

则会输出连接的设备

List of devices

xxxx, device

我遇到的问题是,List of devices 输出显示:xxx, offline。 
这样是不行的,往下执行编译会不通过。瞎捣鼓了一通,最后按如下的方式解决了问题:

cd 切换到sdk安装路径下的 build_tools文件夹,运行

$ adb kill-server$ sudo adb start-server

(网上说的原因是 要以root权限启动 adb)

然后运行$ adb devices,就ok啦。如下图所示


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第13张图片

八、编译并安装 apk文件

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第14张图片

1、编译生成 apk文件

$ cd ~/tensorflow$ bazel build //tensorflow/examples/android:tensorflow_demo

成功之后会看到提示生成了如下三个文件

bazel-bin/tensorflow/examples/android/tensorflow_demo_deploy.jar

bazel-bin/tensorflow/examples/android/tensorflow_demo_unsigned.apk

bazel-bin/tensorflow/examples/android/tensorflow_demo.apk

然后在 bazel-bin/tensorflow/examples/android/目录下你会找到生成的三个文件

2、向安卓手机安装apk文件

$ adb install -r -g bazel-bin/tensorflow/examples/android/tensorflow_demo.apk

安装的过程中,手机屏幕会弹出提示 是否安装该软件?是否允许访问摄像头之类的等等。如下图所示


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第15张图片

安装完毕后,就可以在手机桌面看到两个黄色的图标,名字分别是TF Classify、TF Detect和TF 。如下图所示。

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第16张图片

点击相应软件,就可以运行啦。大功告成~


先说两句题外话吧,TensorFlow(后面简称TF) 前两天热热闹闹的发布了正式版r1.0,可感觉自己才刚刚上手 r0.12,这个时代发展的太快,脚步是一刻也不能停啊~


但是不得不吐槽 TensorFlow的向下兼容做的实在不太友好,每次更新完版本,以前的代码就跑不动,各种提示您使用的函数已经不存在。。。


代码积攒的越来越多,全部针对新版本翻改一遍,工程真是浩大。但是喜新厌旧,手贱如我,每次都忍不住点了更新。不过这次忍的还算不错,到目前还没更新,继续忍住


在之前的文章中,我介绍了如何实现 TensorFlow官网的Mobile教程: 
【将Tensorflow移植到安卓手机,实现物体识别、行人检测和图像风格迁移】。 


但在那个教程中,TensorFlow提供了完整的、已经构建好的Android项目,我们需要做的总结下来只有3步:

1、搭建环境;2、编译;3、安装到手机


这当然还不够,我们的最终目的是要为我所用。所以怎样才能移植自己训练好的TF模型到安卓手机呢?换句话说,怎样将训练好的模型放入Android项目中并进行成功编译?又或者怎样创建自己的Android Tensorflow项目?


PS: 
之前没有安卓开发的经验,纯粹是为了实现将TF模型移植到手机才开始上手,目前属于入门级小白,如有错误之处,欢迎批评指正!


手机调用TF模型的过程简介


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第17张图片

1、 保存训练完毕的TF模型 
2、 在Android项目中导入TF模型、导入Android平台调用TF模型需要的jar包和so文件 (它们负责TF模型的解析和运算) 
3、定义变量、存储数据,通过jar包提供的接口进行模型的调用


环境


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第18张图片

TensorFlow版本: r0.12 
Python 版本:2.7 
Python IDE:  Spyder 
Android IDE :  Android Studio


移植过程详解


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第19张图片

我们以mnist数据集上自己训练的一个图像识别模型为例,进行讲解


一、 在使用python代码编写的TF模型定义中为模型的输入层和输出层Tensor Variable分别指定名字(通过形参 ‘name’)


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第20张图片


名字可以随便起,以方便好记为主,后面还会反复用到。我起的是input和output。

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第21张图片

二、 将使用TensorFlow训练好的模型保存为.pb文件


在模型训练结束后的代码位置,添加下述两句代码,可将模型保存为.pb文件


output_graph_def = tf.graph_until.convert_variables_to_constants(session, session.graph_def, output_node_names=[‘output’])
//形参output_node_names用于指定输出的节点名称


贴一个说明文档,帮助大家进一步了解这个函数

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第22张图片

with tf.gfile.FastGFile(model\mnist.pb, mode = ’wb’) as f:

      f.write(output_graph_def.SerializeToString())


第一个参数用于指定输出的文件存放路径、文件名及格式。我把它放在与代码同级目录的model文件下,取名为mnist.pb


第二个参数 mode用于指定文件操作的模式,’wb’中w代表写文件,b代表将数据以二进制方式写入文件。


如果不指明‘b’,则默认会以文本txt方式写入文件。现在TF还不支持对文本格式.pb文件的解析,在调用时会出现报错。


注: 
1)、不能使用 tf.train.write_graph()保存模型,因为它只是保存了模型的结构,并不保存训练完毕的参数值 
2)、不能使用 tf.train.saver()保存模型,因为它只是保存了网络中的参数值,并不保存模型的结构。 


很显然,我们需要的是既保存模型的结构,又保存模型中每个参数的值。以上两者皆不符合。


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第23张图片

三、生成在Android平台上调用tensorflow 模型需要的jar包和so文件


1) 从github下载TensorFlow的项目源码

2) 安装Bazel 

3) 参考如下图的官方教程,生成Android上调用TF模型需要的so文件和jar包


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第24张图片

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第25张图片

四、安装Android Studio,创建Android 项目

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第26张图片

五、添加资源到项目


1) 将(二)步生成的.pb文件放入项目中 
打开 Project view ,app/src/main/assets。 
若不存在assets目录,右键main->new->folder->Assets Folder


2) 添加(三)步生成的jar包 
打开Project view,将jar包拷贝到app->libs下 
选中jar文件,右键 add as library


3) 添加(三)生成的so文件 
打开 Project view,将.so文件拷贝到 app/src/main/jniLibs下(jniLibs文件夹若没有则新建)

如果我讲的不太明白的话,可自行谷歌搜索“如何在 Android studio中添加引用 jar文件和so文件”


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第27张图片

六、创建接口,实现调用


1) 导入jar包和so文件 
在需要调用模型的.Java文件中,导入jar包:

import org.tensorflow.contrib.android.TensorFlowInferenceInterface11


在该java类定义的首行,导入so文件:

{
   System.loadLibrara(“tensorflow_inference”)
}


2)定义变量及对象

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第28张图片

2)Tensorflow 接口初始化

Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第29张图片

在完成上述两步之后,就可以反复调用模型。 
在每次调用前,先将待输入的数据按顺序存放进 inputs 变量中,然后执行下述三个语句。


3)TF模型的调用


Android手机移植TensorFlow,实现物体识别、行人检测、图像风格迁移_第30张图片

为了便于大家理解,我写的代码比较面向过程。当然放在java环境下,还是要多多从面向对象的角度出发


到此就完成整个移植过程啦!



你可能感兴趣的:(深度学习DL,tensorflow)