RaspberryPI3でMovidius NCSのサンプルを少し真面目に動かしてみた


※注意・・・寝不足でうつらうつらしながら書いたので支離滅裂な部分あるかも・・・明日直す。

# はじめに
前回は世界で一番はじめにMovidius NCSの記事を書くがために、取り急ぎって感じでサンプルだけ動かしました。実は幾つか問題点がありまして、その修正とサンプルのもう少し細かな動作確認までしようと思います。

## 前回の課題

下記２つが挙げられます。

- ネットワークのコンパイルをラズパイ上で行っている
- ```setup.sh```しているだけで、何をやっているか見えない

本来はサーバマシンなどでネットワークをコンパイルしてからラズパイに送るのが筋となっています。何故ならば、ネットワークのコンパイルにはそれなりのメモリが必要で、ラズパイ上だとAlexNetがコンパイルできません。前回はGoogLeNetのみ確認しましたが、今回はAlexNetも動かします。また、```setup.sh```で何をインストールしているかが不明だったので、今回は手動でDocker内のUbuntu環境に各モジュールをインストールしていこうと思います。

## 今回の構成

ネットワークコンパイルのために、RasberryPI以外の少し性能の良いPCを用意します。MacでもWinでもDockerが動けば何でもOKです。ちなみに、[公式の動画](https://www.youtube.com/watch?v=4xud1T9DaFY)ではコンパイルでもMovidius NCSが必要っぽく書いてありますが、実際は不要でした。従って、ネットワークの準備はDockerが動けば、どのPCでも大丈夫です。

![Kobito.s2Z7B4.png](https://qiita-image-store.s3.amazonaws.com/0/146529/5e6adc82-ad05-6313-f91c-6937c825bb2c.png "Kobito.s2Z7B4.png")

# Dockerの入ったPC上での作業

## Dockerイメージの作成

まずはmovidiusの環境が入ったDockerイメージを作成します。[下記リポジトリ](https://github.com/peisuke/MovidiusNCS-setup.git)のDockerfileを適当なディレクトリに入れて（今回は```/path/to/movidius```とします）ビルドします。

```
$ cd /path/to/movidius
$ docker build -t movidius .
```

Dockerファイルの中身としては、OpenCVとcaffe環境、およびMovidius NCSのライブラリをインストールします。ここで重要なのは、numpyは必ずapt-getでインストールする事です。というのも、MovidiusのSDKが```python3-numpy```に依存しているため、pip等でnumpyを入れてしまうと、MovidiusのSDKがインストール出来ないからです。また、次にコンパイルするネットワークはホストからも扱うので、扱いやすさのためユーザーモードを作成しておきます。

## ネットワークのコンパイル

ここからは、caffeのモデルをコンパイルしていきます。コンパイル用のファイルは用意済みなので、caffeのprototxtとcaffemodelファイルを準備し、コンパイルのプログラムを実行するだけとなります。今回は既存のモデル(GoogLeNetとAlexNet)をコンパイルするだけですが、ここで好きなファイルをコンパイルすることも勿論できます。

まずは、先程作ったDockerイメージを立ち上げます。なお、後でコンパイルしたモデルをラズパイに送るため、ホスト上の適当なフォルダ（ここでは```/path/to/data```）を共有フォルダにしておきます。下記のように立ち上げることで、Docker内で```/home/ubuntu/data```にデータを保存しておけばホストでもそのデータを扱うことができます。

```
docker run -it --rm -v /path/to/data:/home/ubuntu/data movidius:latest /bin/bash
```

ここからはDocker内での作業となります。まずは、ネットからcaffeのモデルをダウンロードしましょう。

```AlexNet
mkdir -p data/AlexNet && cd data/AlexNet
wget http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel
wget https://raw.githubusercontent.com/BVLC/caffe/master/models/bvlc_alexnet/deploy.prototxt
```

```GoogLeNet
mkdir -p data/GoogLeNet && cd data/GoogLeNet
wget http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel
wget https://raw.githubusercontent.com/BVLC/caffe/master/models/bvlc_googlenet/deploy.prototxt
```

また、両方のdeploy.prototxtの最初を修正し、入力画像枚数を1に変更しておきます。

```deploy.prototxt
- input_param { shape: { dim: 10 dim: 3 dim: 224 dim: 224 } }
+ input_param { shape: { dim: 1 dim: 3 dim: 224 dim: 224 } }
```

続いてコンパイルです。ラズパイ上では起きていたメモリエラーがPCで実行することで消えました。

```AlexNet
cd data/AlexNet
python3 ../../bin/mvNCCompile.pyc ./deploy.prototxt -w ./bvlc_alexnet.caffemodel -o graph
```

```GoogLeNet
cd data/GoogLeNet
python3 ../../bin/mvNCCompile.pyc ./deploy.prototxt -w ./bvlc_googlenet.caffemodel -o graph
```

これで作成された両方のgraphファイルがMovidius NCSで利用されます。

# ラズパイ上での作業

まずは、ラズパイ上に環境を構築します。具体的な構築手順は[前回の記事](http://qiita.com/peisuke/items/87210d55a5195e24c9bc)と同様にsetup.shを実施すれば良いです。setup.shの内容は上記で説明したとおりなので、ここでは説明は省略します。

はじめに、先程作成したネットワークをコピーします。コピーのみホストマシンから行います。

```
$ scp /path/to/GoogLeNet/graph ubuntu@ubuntu.local:~/ncapi/network/GoogLeNet/
```

続いて、ラズパイ上にsshで入り、前回同様サンプルをビルドします。

```
$ ssh ubuntu@ubuntu.local
$ cd ncapi/c_examples/
$ make
```


実行します。

```
./ncs-fullcheck -c1 ../networks/GoogLeNet ../images/cat.jpg
```

![Kobito.TL3zw9.png](https://qiita-image-store.s3.amazonaws.com/0/146529/0dbbd7b8-7e84-9b4c-22c5-12c20436d709.png "Kobito.TL3zw9.png")

```
ubuntu@ubuntu:~/ncapi/c_examples$ ./ncs-fullcheck -c1 ../networks/GoogLeNet ../images/cat.jpg
OpenDevice 1.5 succeeded
Graph allocated
Persian cat (46.17%) Egyptian cat (17.80%) tabby, tabby cat (7.54%) lynx, catamount (7.19%) Arctic fox, white fox, Alopex lagopus (5.78%)
...
```

AlexNetについても同じ操作方法で動かすことができます。サンプルの詳細は次回以降に見ていきます。