Python
機械学習
TensorFlow

TensorFlowの学習モデルによるモバイル端末でのリアルタイム画像認識

More than 1 year has passed since last update.

タイトルは論文っぽく書いていますが、要はTensorFlowのページにAndroid / iOS で動かせるぜーとあったのでどんなものかやってみた、という話です。

やってみると、確かにAndroid、iOS両方でビルドすることができたので、その手順などを書きたいと思います。


Android

まずはAndroid版から。

https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android

基本的にはこちらに従います。ビルドできると、GoogleのInceptionモデルを使ったTF Classify, Scalable Object Detection using Deep Neural Networks をベースにしたTF Detectが作られます。

さらににスタイル変換するTF Stylizeまで実装されていたらしい…ので改めて以下の環境でビルドし直してみました。

- Android Studio 2.2.3

- Android 6.0.1 (Xperia Z3)


TensorFlowのビルド

まずは最新版をクローンしてきます。いまTensorFlowはr0.12だったような。

git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git

次にビルドツールbazelをインストールします。

brew install bazel

C/C++コードをコンパイルするためにNDKが必要です。

https://developer.android.com/ndk/guides/index.html

によると、Preferencesからsdkで検索して SDK Tools タブを開きます。ここで


  • CMake

  • LLDB

  • NDK

にチェックを入れてApplyすればインストールできます。SDKについてはとなりの SDK Platforms からインストールできて、Android 5.0以上はすべてインストールしておきました。

new_screen_shot.png

続いて、 /tensorflow/WORKSPACE ファイルを編集します。コメントアウトされている部分を自分の設定に直します。

 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 = "<PATH_TO_SDK>",
-#)
-#
-#android_ndk_repository(
-# name="androidndk",
-# path="<PATH_TO_NDK>",
-# api_level=21)

+android_sdk_repository(
+ name = "androidsdk",
+ api_level = 25,
+ build_tools_version = "25.0.2",
+ # Replace with path to Android SDK on your system
+ path = "/Users/user-name/Library/Android/sdk/",
+)
+
+android_ndk_repository(
+ name="androidndk",
+ path="/Users/user-name/Library/Android/sdk/ndk-bundle/",
+ api_level=21)

以下でTensorFlowの学習モデルを落として適切な場所に配置します。モデルはassetsディレクトリに置けばよいことがわかります。学習モデルであるグラフ: tensorflow_inception_graph.pb は53.9MBでした。またdetectionのモデルグラフ: multibox_model.pb は18.6MBのようです。

$ 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

$ unzip /tmp/inception5h.zip -d tensorflow/examples/android/assets/
$ unzip /tmp/mobile_multibox_v1.zip -d tensorflow/examples/android/assets/

これでビルドする準備が整ったのでルートディレクトリ(WORKSPACEが置いてあるところ)でbazel buildします。

$ bazel build -c opt //tensorflow/examples/android:tensorflow_demo

20分くらいかかるので、エスプレッソでも抽出してましょう。無事通ったら、実際に端末にインストールして動かしてみます。

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

以下のようなエラーがさっき出たらupdateしろとのことなので、従うとちゃんとビルドできました。

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

It appears you do not have 'Android SDK Platform-tools' installed.
Use the 'android' tool to install them:
android update sdk --no-ui --filter 'platform-tools'

new_screen_shot.png

先週は割にぬるぬる動いた印象だったのにビルドし直したらちょいと重くなったような印象が…気のせいかもしれませんが。Scalable Object Detectionのアプリケーションもインストールされているはずです。そしてスタイル変換はとてもよくできていて、画面下に絵画のサンプルがあって、それをどのくらいスタイルとして用いるかを選べるUIになっていました。解像度が32〜1024まで選べるようになっていて、さすがに192くらいからはリアルタイムではまわりませんが、画像生成できていました。

new_screen_shot.png

ソースコードのコミットを見ると、わずか1週間の間で StylizeActivity.javaTensorFlowYoloDetector.java が増えていた…びっくり。


iOS

続いてiOSです。基本的には

https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/ios_examples

にある TensorFlow iOS Examples に従います。Xcode 7.3以降が必要とあって、iOSをあげてしまっていたのもあってXcodeをアップデートして、以下の環境でビルドできました。


  • Xcode 8.2.1

  • iOS 10.1.1 (iPhone SE)


TensorFlowのビルド

まずは

https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/makefile

のiOSの項に従ってTensorFlowをビルドせよとあるのでやります。

xcode-select --install

brew install automake
brew install libtool

をインストール。次のシェルで1発でビルドできるようです。

tensorflow/contrib/makefile/build_all_ios.sh

これによって tensorflow/contrib/makefile/gen/lib/libtensorflow-core.a が生成されるようです。これをXcode Projectでリンクしてあげればよいらしい。20分近くかかるのでコーヒーでも淹れましょう。このシェルではなく1つ1つ生成しようとすると、まずはdependenciesをダウンロード。

tensorflow/contrib/makefile/download_dependencies.sh

次に、iOS向けにprotobufをコンパイル。

tensorflow/contrib/makefile/compile_ios_protobuf.sh 

そしてiOSをターゲットにmake。

make -f tensorflow/contrib/makefile/Makefile \

TARGET=IOS \
IOS_ARCH=ARM64


Inceptionモデルのダウンロードとプロジェクトの実行

TensorFlowディレクトリのルートで、以下を実行するか、リンクからInception v1のモデルをダウンロードして解凍します。

mkdir -p ~/graphs

curl -o ~/graphs/inception5h.zip \
https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip \
&& unzip ~/graphs/inception5h.zip -d ~/graphs/inception5h
cp ~/graphs/inception5h/* tensorflow/contrib/ios_examples/benchmark/data/
cp ~/graphs/inception5h/* tensorflow/contrib/ios_examples/camera/data/
cp ~/graphs/inception5h/* tensorflow/contrib/ios_examples/simple/data/

これを見ると、アプリのサンプルは benchmark , camera , simple の3つあることがわかります。画像認識をするのはもちろん camera です。inceptionのモデルはそれぞれのアプリのdataディレクトリ配下に置けばよさそうです。これが終わったら、あとはディレクトリの中にあるcamera_example.xcodeprojファイルを開いてrunするだけです。

IMG_0155.PNG

Android版とはちがって、画面下に画像取得を止められる機能がついていました。手持ちのiPhone SEでぬるぬる動きます。

http://qiita.com/shu223/items/ce190ea6669b2636a8a7

の記事によると、iPhone6で数秒の遅延があるということだったので、モデル自体がそのときと比べて小さくなったのか、記事で言及されているGPU Acceleratedをサポートしたのか、iOS 10 で Accelerate.framework に追加された BNNSが実装されたのか(issueがcloseしてないのでまだっぽい…)

逆に実装されてなくてこの速さなら、iPhone 6s以降であればもっとfpsをあげられなくもなさそう。


まとめ

TensorFlowの学習モデルをモバイルで動かすサンプルをビルドしてみました。Android/iOSどちらでも結構ぬるぬる動いていて、どれくらい重たいモデルまでいけるのかが気になるところ。