Raspberry Pi 3のセットアップとTensorFlowの学習モデルによる画像認識

Raspberry Pi 上でリアルタイム画像認識」をやってみたいと思います。やる前の気持ちは「ほんとに動くんだろうか…」です。

# Raspberry Pi って？

そもそも「ラズパイ」って何？っていうと、こちらですね。
![DSC_4496.JPG](https://qiita-image-store.s3.amazonaws.com/0/137365/e3320218-0f26-f03a-cda2-ccb246c964c8.jpeg)

約5,000円くらいで買える超小型のコンピュータです。ARMプロセッサーという処理系がのっかったいわゆるシングルボードコンピュータというものになります。なんと64bitのクアッドコアCPUです。最初にリリースされたのが2012年で、昨年発売されたRaspberry Pi 3 Model B で３世代目になります。下の表（ http://www.lifehacker.jp/2016/03/160312raspberry_pi.html より）にあるように、CPU性能もかなり向上していますが、２世代目と比較して最も大きい違いはWi-FiとBluetoothが搭載された点でしょう。
![スクリーンショット 2017-02-01 0.52.45.png](https://qiita-image-store.s3.amazonaws.com/0/137365/c0c0f6a7-8f10-30c7-223b-319a05f99b48.png)

上の写真でいうと奥側にプログラムで制御できるGPIOピンというものがあり、ここには5V電源をとる端子やマイナス端子側になるGND(グランド)があります。ここからジャンパーピンやワイヤーでブレッドボードなどに接続して温度センサや抵抗などをアキバの秋月で購入して…とやっていくとどんどん楽しくなってきます。

# OSのインストール

なにはともあれ、まずはラズパイへのOSのインストールです。ラズパイ用のLinuxである「Laspbian」を入れます。これにはラズパイ専用のOSインストーラー「NOOBS」を利用するのが便利です。
https://www.raspberrypi.org/downloads/noobs/

ここからダウンロードしますが、「Offline and network install」と「Network install only」の２種類あります。今回はmicro SDの余裕もあったり後々デュアルブートする予定なので前者を選択してZIPでダウンロードします。Raspbian以外のOSのインストールにはネットワークが必要になります。LAN端子がラズパイ本体についていて、ラズパイ２までは有線しかなかったですが３からは無線LANが使えるようになったのでとても便利。
![スクリーンショット 2017-01-31 23.50.37.png](https://qiita-image-store.s3.amazonaws.com/0/137365/2ea513a5-2900-f32b-b013-664b3e40dbf9.png)

ダウンロードできたら中身を解凍して、それらをすべてSDに移します。こんな感じになればOK。
<img width="1429" alt="raspberry_pi_dir.png" src="https://qiita-image-store.s3.amazonaws.com/0/137365/fbabd1d9-a0f5-ce4e-7186-1b1ee4d9820e.png">

このmicro SDをラズパイへ挿し、HDMIケーブル、マウス、キーボードを接続しACアダプタをつなげるとインストール画面がでると思います。この時点でネットにつなぐ必要があります。
![DSC_4505.JPG](https://qiita-image-store.s3.amazonaws.com/0/137365/217f357e-d0a1-214e-3875-23535ab2df10.jpeg)

![DSC_4504.JPG](https://qiita-image-store.s3.amazonaws.com/0/137365/c53d3d1f-10d7-0533-62ac-d70050228d80.jpeg)

Raspbianにチェックを入れインストールを開始します。しばらくかかるのでハンドドリップでコーヒーでも淹れましょう。終わったら再起動すると、こんなデスクトップが現れます。
![DSC_4507.JPG](https://qiita-image-store.s3.amazonaws.com/0/137365/4443504f-be9b-7998-fbc5-3981e9dba66f.jpeg)

早速アップデートと日本語環境を整えます。

```
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install jfbterm
sudo apt-get install ibus-anthy
```

これでひとまず最初のセットアップを完了とします。

# TensorFlowのビルド

ここからはこちらに従っていきます。
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/pi_examples/

まずは以下にそってstatic libraryの生成を行います。
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/makefile
g++などをインストールし、protobufをビルドします。とても時間がかかるので他の作業をしていましょう。

```
tensorflow/contrib/makefile/download_dependencies.sh
sudo apt-get install -y autoconf automake libtool gcc-4.8 g++-4.8
cd tensorflow/contrib/makefile/downloads/protobuf/
./autogen.sh
./configure
make
sudo make install
sudo ldconfig  # refresh shared library cache
cd ../../../../..
```
これが終わったらラズパイをターゲットにビルドすることができます。

```
make -f tensorflow/contrib/makefile/Makefile HOST_OS=PI TARGET=PI OPTFLAGS="-Os" CXX=g++-4.8
```

# サンプルアプリのビルド

上で作ったライブラリを使って、画像認識のサンプルアプリのビルドを行っていきます。
まずは画像が読めるようにlibjpegをいれます。

```
sudo apt-get install -y libjpeg-dev
```
次に、画像認識のモデル(Googleのinception)をダウンロードして適切なディレクトリに配置します。

```
curl https://storage.googleapis.com/download.tensorflow.org/models/inception_dec_2015_stripped.zip \
-o /tmp/inception_dec_2015_stripped.zip
unzip /tmp/inception_dec_2015_stripped.zip \
-d tensorflow/contrib/pi_examples/label_image/data/
```

続いて、TensorFlowソースツリーのルートで以下を実行しビルドしましょう。これで1枚の画像に対する画像認識を行うアプリが出来上がります。

```
make -f tensorflow/contrib/pi_examples/label_image/Makefile
```
こうしてできあがったアプリは以下のコマンドで実行できます。

```
tensorflow/contrib/pi_examples/label_image/gen/bin/label_image
```
実行すると、imageディレクトリにある画像（COBOLを開発したグレース・ホッパーさん）に対しての認識結果がコンソールに表示されます。
<img src='https://s3.g.cookpad.com/files/upload/20170131152702_grace_hopper.jpg' />

```
I tensorflow/contrib/pi_examples/label_image/label_image.cc:384] Running model succeeded!
I tensorflow/contrib/pi_examples/label_image/label_image.cc:284] military uniform (866): 0.624293
I tensorflow/contrib/pi_examples/label_image/label_image.cc:284] suit (794): 0.0473981
I tensorflow/contrib/pi_examples/label_image/label_image.cc:284] academic gown (896): 0.0280926
I tensorflow/contrib/pi_examples/label_image/label_image.cc:284] bolo tie (940): 0.0156956
I tensorflow/contrib/pi_examples/label_image/label_image.cc:284] bearskin (849): 0.0143348
```
実行時に以下のオプションをつけることで任意の画像に変更したり、独自の学習モデルを利用できるようです。

```
--image=your_image.jpg
--graph=your_graph.pb --input=Mul:0 --output=final_result:0
```

# カメラ画像認識
最後にWebカメラの画像に対して認識をするアプリも入っているのでビルドしてみましょう。Video4Linuxがいるようなのでインストールします。

```
sudo bash -c "echo 'bcm2835-v4l2' >> /etc/modules"
sudo apt-get install libv4l-dev
```
インストールできたらアプリをビルドします。これでUSB接続のWebカメラをつなぎ、実行します。実行した様子が以下です。

```
make -f tensorflow/contrib/pi_examples/camera/Makefile
tensorflow/contrib/pi_examples/camera/gen/bin/camera
```
<img src='https://s3.g.cookpad.com/files/upload/20170131153548_raspberry_pi_real_time.jpg' />

左手にWebカメラを持って写しているので、"laptop"や"monitor"と認識できていることがわかります！リアルタイムとはいったものの、実際には5,6秒おきの認識です。
全然リアルタイムではないわけですが（笑）、ラズパイのCPUでも動くのにはちょっと感動しました。

# まとめ

Raspberry Pi のセットアップから、Webカメラ画像のリアルタイム（5,6秒おき）認識までを書いてみました。こんな小さなボードでも動かすことができるところまでは来ているので、数秒おきの認識結果（ある程度のタイムスタンプ）でよければ監視カメラ画像の解析をしてその結果をどんどんクラウドにあげていく、といった用途でも使えるかもしれません。