Ubuntu Mate 20.04 on Raspberry Pi 4 Model BにOpenVINOを導入してNeural Compute Stick 2の動作確認をする

## 用意した物

1. Raspberry Pi 4 Model B (メモリ4GB)
1. インターネット接続設定とUbuntu 20.04 ServerにMateを導入済みのmicroSDカード(https://qiita.com/yohama/items/0c291e31c80850c8c112
)
1. Intel Neural Compute Stick 2

まだ、Neural Compute Stick 2は、Raspberry Piには接続しません。

# 前準備

システムアップデートとビルドに必要なツール一式は、入っていなければ入れておきます。

```bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential cmake
sudo apt install -y git python3-pip
```

必須ではありませんが、make installでインストールされるものを名前付きで管理するために、porgを入れておきます。

```bash
sudo apt install -y porg
```

# OpenVINOのインストール

執筆時点では、OpenVINOのバージョン2021.2以降は、ビルドに失敗するので、2021.2をgit cloneしてきて、必要な依存モジュールをアップデートしておきます。

```bash
cd ~
git clone https://github.com/openvinotoolkit/openvino.git -b 2021.2 --depth 1
cd ~/openvino/inference-engine
git submodule update --init --recursive
cd ~/openvino
sh ./install_build_dependencies.sh
```

なお、OpenVINOのバージョン2020.3以降は、NCS1がサポートされなくなってしまっています。

https://raspberrypi.stackexchange.com/questions/120951/runtimeerror-can-not-init-myriad-device-nc-error-on-raspberrypi-3-with-ncs-ver

もしNCS1を使用したい場合には、2021.2ではなく、2020.2を導入する必要があります。

Pythonで依存するライブラリを、インストールしておきます。

```bash
pip3 install cython numpy
```

ビルド用ディレクトリを作成して、ビルドします。

```bash
cd ~/openvino
mkdir build && cd $_
cmake -DCMAKE_INSTALL_PREFIX=/opt/openvino -DCMAKE_BUILD_TYPE=Release -DENABLE_OPENCV=OFF -DENABLE_PYTHON=ON -DNGRAPH_PYTHON_BUILD_ENABLE=ON -DNGRAPH_ONNX_IMPORT_ENABLE=ON -DPYTHON_EXECUTABLE=/usr/bin/python3.8 -DPYTHON_LIBRARY=/usr/lib/python3.8/config-3.8-aarch64-linux-gnu/libpython3.8.so -DPYTHON_INCLUDE_DIR=/usr/include/python3.8 ..
make -j4
```

ビルドには1時間半かかりました。

ここで、何もせずにmake installすると、"inference-engine/src/inference_engine/cmake_install.cmake"で、"openvino/inference-engine/temp/tbb_yocto/LICENSE"が見つからないとエラーが出てしまい、先に進むことができませんでした。

LICENSEファイル自体は、再配布する場合以外は気にする必要はないと考えて、ここでは該当する行をコメントアウトします（逆に再配布する場合には、気をつける必要があるかもしれません）。

```bash
sed -i -e '/tbb_yocto\/LICENSE/s/^/# /g' ./inference-engine/src/inference_engine/cmake_install.cmake
```

porgの管理対象に入れつつ、make installします。

```bash
sudo porg -l -p openvino make install
```

Pythonのライブラリと共有ライブラリのパスを通すために、OpenVINO関連のライブラリがインストールされた場所を指すように、環境変数を設定します。

```bash
echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/openvino/lib' >> ~/.bashrc
echo 'export PYTHONPATH=$PYTHONPATH:~/openvino/build' >> ~/.bashrc
echo 'source /opt/openvino/bin/setupvars.sh' >> ~/.bashrc
source ~/.bashrc
```

Neural Compute Stick 2をOSに認識させるために、udevに設定を追加するスクリプトを実行します。

```bash
sudo -E bash /opt/openvino/install_dependencies/install_NCS_udev_rules.sh
```

Neural Compute Stick2は"users"グループにパーミッションが与えられているので、現在のユーザのサブグループに"users"グループを追加します。

```bash
sudo usermod -aG users "$(whoami)"
```

ここで、一旦OSを再起動して、ここまでの設定を反映するようにしておきます。

```bash
sudo reboot
```

再起動が完了したら、ログイン後に、Neural Compute Stick 2を、Raspberry Piに接続します。

次に、以下のコマンドで、USB接続されている機器の一覧を表示します。

```bash
lsusb
```

この結果、"ID 03e7:2485 Intel Movidius MyriadX"という項目が存在していれば、デバイスがOSに認識されていることになります。

# Open Model Zooのインストール

Intelが公開している学習済みのモデルを利用できるようにするために、Open Model Zooをインストールします。

まずは、Pythonの依存ライブラリをインストールしておきます。

```bash
pip3 install networkx defusedxml protobuf test-generator==0.1.1
```

OpenVINOのバージョンに合わせたOpen Model Zooを、git cloneしておきます。

```bash
cd ~
git clone https://github.com/openvinotoolkit/open_model_zoo.git -b 2021.2 --depth 1
```

まだ学習済みモデルはダウンロードされていない状態なので、動作確認用にAlexnetをダウンロードしてきます。

```bash
cd ./open_model_zoo/tools/downloader
./downloader.py --name alexnet --precisions=FP16
```

ダウンロードしたモデルを、Neural Compute Stickで実行できる形式に変換します。

```bash
./converter.py --name alexnet --precisions=FP16
```

# Neural Compute Stick2による画像認識の動作確認

動作確認用の画像を用意します。

ここでは、[PDClipart.org](https://www.pdclipart.org/)から、Public Domainの[レモンの画像](https://www.pdclipart.org/albums/Food__D-M/lemon_3.png)をダウンロードするものとします。

```bash
cd ~
wget https://www.pdclipart.org/albums/Food__D-M/lemon_3.png
```

OpenVINOに同梱されている画像認識用のPythonサンプルコードでは、OpenCVを使用するので、必要なPythonライブラリをインストールしておきます。

```bash
pip3 install opencv-python
```

画像認識用のPythonサンプルコードを、Neural Compute Stickを計算デバイス(-dオプション)とし、学習済みモデルAlexnetを使用(-mオプション)に、先程ダウンロードしたレモンの画像を入力(-iオプション)して、実行します。

```bash
cd ~
python3 ~/openvino/inference-engine/ie_bridges/python/sample/classification_sample_async/classification_sample_async.py -m ~/open_model_zoo/tools/downloader/public/alexnet/FP16/alexnet.xml -i ~/lemon_3.png -d MYRIAD
```

以下のように上位10個の認識結果が、数秒程度かけて得られます。

```
[ INFO ] Creating Inference Engine
[ INFO ] Loading network:
        ~/open_model_zoo/tools/downloader/public/alexnet/FP16/alexnet.xml
[ INFO ] Preparing input blobs
[ WARNING ] Image ~/lemon_3.png is resized from (122, 159) to (227, 227)
[ INFO ] Batch size is 1
[ INFO ] Loading model to the plugin
[ INFO ] Start inference (10 Asynchronous executions)
[ INFO ] Completed 1 Async request execution
[ INFO ] Completed 2 Async request execution
[ INFO ] Completed 3 Async request execution
[ INFO ] Completed 4 Async request execution
[ INFO ] Completed 5 Async request execution
[ INFO ] Completed 6 Async request execution
[ INFO ] Completed 7 Async request execution
[ INFO ] Completed 8 Async request execution
[ INFO ] Completed 9 Async request execution
[ INFO ] Completed 10 Async request execution
[ INFO ] Processing output blob
[ INFO ] Top 10 results:
Image ~/lemon_3.png

classid probability
------- -----------
  951     0.7602539
  940    0.1222534
  522    0.1079102
  952    0.0023651
  950    0.0021343
  948    0.0016289
  852    0.0012283
  641    0.0008454
  574    0.0005541
  722    0.0005450


[ INFO ] This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool
```

この例では、classid=951である確率が0.76である、という結果になっています。

このclassidは、Alexnetが学習しているImagenetのIDに相当していて、classid=951を調べると、たしかに"lemon"であることがわかります。

https://gist.github.com/yrevar/942d3a0ac09ec9e5eb3a

動作確認は、以上です。

# 参考サイト

https://qiita.com/bigface00/items/12474f4c60df4b70e51f

https://qiita.com/k-koh/items/38dc86be2b55a9228b50