お手軽にrealtime画像認識をAndroid/iOSで動かす

#お手軽にrealtime画像認識をAndroid/iOSで動かす

こちらは[TensorFlow Advent Calendar 2016](http://qiita.com/advent-calendar/2016/tensorflow)の5日目です。
この記事はこれからTensorflow始めてみようというAndroidエンジニア、iOSエンジニア向けです。

- 開発環境: Mac
- Tensorflow: r0.12
- 検証端末: Galaxy S6
- 検証端末: iPhone 6

##理論はともかく動かしてみよう！

機械学習って自分には関係ないって思ってませんか？**TensorflowはAndroid/iOSローカルで動きます！リアルタイムです！**
公式のチュートリアルでは、Bazelっていうビルドツールが必要なのですが、独自色が強く、Android/iOSエンジニアには敷居が高いです。そんなBazelのインストールから説明していきたいと思います。

##Bazelのインストール

参考: https://www.tensorflow.org/versions/r0.12/get_started/os_setup.html

```
brew install bazel
```

JDK8のダウンロード(jdk-8u111-macosx-x64.dmgを手動でインストール)
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

環境変数を設定

```
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home
```

##Tensorflowのダウンロード

```
git clone https://github.com/tensorflow/
cd tensorflow
git checkout r0.12
```

##Android版

参考: https://github.com/tensorflow/tensorflow/tree/r0.12/tensorflow/contrib/makefile#android

Android NDKのインストール

```
brew install android-ndk
export NDK_ROOT=/usr/local/Cellar/android-ndk/r13b/
```

Bazelの設定ファイルにAndroid SDKとNDKのパス指定

```
vim WORKSPACE
```

git diff

```
-#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 = 23,
+    build_tools_version = "23.0.1",
+    # Replace with path to Android SDK on your system
+    path = "/usr/local/Cellar/android-sdk/24.4.1_1",
+)
+
+android_ndk_repository(
+    name="androidndk",
+    path="/usr/local/Cellar/android-ndk/r13b",
+    api_level=21)
```

訓練済みモデルのダウンロード

```
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/
```

Androidのビルドとapkのインストール

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

https://www.youtube.com/watch?v=Z7XcoigrEbA
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/Z7XcoigrEbA/0.jpg)](http://www.youtube.com/watch?v=Z7XcoigrEbA)

##Androidスタンドアローン版

```
git clone https://github.com/mainyaa/TensorFlowAndroidDemo
cd jni-build
make
make install
```

あとはAndroidStudioでプロジェクトを開いてビルドするだけです。

## iOS版

参考: https://github.com/tensorflow/tensorflow/tree/r0.12/tensorflow/contrib/makefile#ios
参考：[TensorFlowにiOSサポートが追加されたそうなので試してみた](http://qiita.com/shu223/items/ce190ea6669b2636a8a7)

依存関係のインストール

```
xcode-select --install
brew install automake
brew install libtool
```

依存関係とTensorflowをビルド
**macOS Sierraの人**は[こちら](https://gist.github.com/mainyaa/367cd40d40801c1d8de507e07fa9bb2e
)を参考に.shファイルを編集してから実行してください

```
cd tensorflow
tensorflow/contrib/makefile/download_dependencies.sh
tensorflow/contrib/makefile/build_all_ios.sh
```

訓練済みモデルのダウンロード

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

あとはxCodeでtensorflow/contrib/ios_examples/cameraを開いてビルドするだけです。

https://www.youtube.com/watch?v=Sl8MPeWVi2I
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/Sl8MPeWVi2I/0.jpg)](http://www.youtube.com/watch?v=Sl8MPeWVi2I)


## 日本語化

英語のままだとわかりにくいのでリソースを日本語化しました。
imagenet_comp_graph_label_strings.txt を置き換えるだけで認識結果を日本語化出来ます。

Android日本語化

```
curl -o tensorflow/examples/android/assets/imagenet_comp_graph_label_strings.txt https://raw.githubusercontent.com/mainyaa/TensorFlowAndroidDemo/master/app/src/main/assets/imagenet_comp_graph_label_strings.txt
```

で置き換えることで、認識結果を日本語化出来ます。


iOS日本語化

```
curl -o tensorflow/contrib/ios_examples/camera/data/imagenet_comp_graph_label_strings.txt https://raw.githubusercontent.com/mainyaa/TensorFlowAndroidDemo/master/app/src/main/assets/imagenet_comp_graph_label_strings.txt
```

XcodeでCameraExampleViewController.mmを開く

```
-          NSString *labelObject = [NSString stringWithCString:label.c_str()];
+          NSString *labelObject = [NSString stringWithCString:label.c_str() encoding:NSUTF8StringEncoding];
```

で置き換えることで、認識結果を日本語化出来ます。

## 色々認識してみよう！

機械学習というと、文字とグラフとにらめっこなイメージがありますが、手元の端末にまで落ちてきて、それがリアルタイムで動くと『おおっ！』という感動があります。
今回のデモでは、1000クラスの分類が出来ます。そのうち200クラスぐらいが犬種です。犬検出器です。
僕の端末（Galaxy S6）では、1frame 300msで処理できていました。皆さんの端末ではどうですか？
https://www.youtube.com/watch?v=XK7EuHrkUU4
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/XK7EuHrkUU4/0.jpg)](http://www.youtube.com/watch?v=XK7EuHrkUU4)

##職業プログラマーは如何に機械学習に立ち向かうのか

機械学習やってみたいけど、数学苦手って方もいらっしゃるかと思います。それなら、コードからボトムアップで理解してみるのは如何でしょうか。
[tensorflow/example/tutorial](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/tutorials)には豊富なチュートリアルがあります。
[tensorflow/models](https://github.com/tensorflow/models/)では、色んな機械学習がコードが教師データ付きで公開されています。
最近は論文とともに、教師データ+学習プログラム+デモという形でgithub上に公開してくれている研究者がたくさんいます。
http://www.gitxiv.com/ このサイトでは論文のabstract＋githubのreadmeを一対として表示してくれるニュースサイトです。
ここを見ながら、興味深いテーマをgithubからcloneしてきて自分で学習させて、デモプログラムを走らせてみると面白いと思います。 "論文名 tensorflow" でgithub上で検索すると、tensorflow版の実装が簡単に出てきます。
機械学習のプログラムは多くがPythonです。機械学習の理論は非常に複雑ですが、Pythonの関数レベルまで落としこんであれば、入力と出力がわかっているブラックボックス関数として扱うことで、中身を知ることがなく使うことが出来ます。
慣れてくると1時間もあればFlaskを使ってAPIサーバー化して、Hubot経由でSlackから使えるようにも出来ます。

今週末にでもTensorflowに入門してみませんか？