Raspberry Pi3でMovidius(NCSDK2)の動作環境をDockerで構築してみる


はじめに

ラズパイを扱う上で悩ましい点の1つが環境の切り替えかなと思います。使用するライブラリの種類やバージョン違い等、様々な環境を使い分けるため、SDカードの入れ替え大会が行われ、最後にはどのSDカードがどの環境か分からなくなることも多々あります。

そんなわけでDockerを使って環境を切り分けられるようにしてみようと考えました。

今回は、Dockerコンテナ内で物体検出などディープラーニング系の処理を実行する基礎環境を構築してみます。
ここで作成するDockerイメージは必要最低限なものだけを導入し、ここから作成したコンテナ内で環境を育て、それを基にさらにDockerイメージを作る、というスパイラル的な使い方を想定しています。

今回のDockerコンテナでは以下を実行できるようにしてみます。

環境

以下の環境を使用しました。

デバイス等 バージョン 備考
Raspberry Pi3 B+ Pi3BでもOKです
RASPBIAN STRETCH WITH DESKTOP April 2018 コンテナもこのバージョンで作成
Movidius Neural Compute Stick
Logicool HD Webcam C270
Docker 18.05.0-ce
Python 3.5.3 Dockerコンテナ内
OpenCV 3.4.1 Dockerコンテナ内
Movidius Neural Compute SDK V2.04.00 2018-05-04 Dockerコンテナ内
Neural Compute Application Zoo (NC App Zoo) Dockerコンテナ内

作業するディレクトリ構成

今回は以下のようなディレクトリの構成で作業します(ホスト側)。

任意のディレクトリ/
 ├ Dockerfile
 ├ ncsdk /
 ├ コンテナにコピーする任意のファイル

任意のディレクトリを作成し、その配下で作業します。

  • Dockerfileは今回作成するDockerイメージの定義ファイルです。
  • ncsdkディレクトリはMoviusのSDKのディレクトリです。今回ダウンロードします。
  • コンテナ内で使いたいファイルがあれば、このディレクトリに格納しておきます。

ラズパイのスワップサイズの変更

いよいよ環境構築を始めます。

通常通りSDカードにRaspbian Stretchをインストールした後、まずはスワップサイズを増やします。増やさないと各種ビルドに時間がかかる、メモリ不足で落ちる、など問題が発生します。

スワップ領域は"/etc/dphys-swapfile"ファイルの"CONF_SWAPSIZE"に記述します。
ここでは2048MB(2GB)を確保しておきます。

/etc/dphys-swapfile
# スワップサイズ(MB)
CONF_SWAPSIZE=2048

変更したらサービスを再起動して設定を反映します。

$ sudo systemctl stop dphys-swapfile
$ sudo systemctl start dphys-swapfile

free -hコマンドで確認します。

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           875M        218M        222M         18M        434M        581M
Swap:          2.0G          0B        2.0G

Dockerのインストール

続いてDockerをインストールします。通常ユーザでも実行できるようにdockerグループを割り当てます。

なお、通常ユーザにdockerグループを割り当てるとパスワードなしで実行できてしまうため、セキュリティ上のリスクが伴うことにご留意下さい。

$ curl -sSL https://get.docker.com | sh
$ sudo usermod -aG docker pi
$ sudo reboot

MovidiusのSDKのダウンロードと設定変更

MovidiusのSDKであるNCSDK2をホスト側でダウンロードします。
ダウンロード後、設定ファイルを編集します。

まずはダウンロードです。

$ git clone -b ncsdk2 https://github.com/movidius/ncsdk.git

ダウンロードしたncsdkディレクトリ直下の"requirements_apt_raspbian.txt"ファイルに、"python3-setuptools python-setuptools"を追加します。

追加した結果、以下のようになります(実際は改行無し)。

requirements_apt_raspbian.txt
python3-markdown python3-h5py python3-lxml python3-matplotlib python3-protobuf
python3-dateutil python3-scipy python3-six python3-networkx make wget python3-dev
python3-pip python-pip python3-setuptools python-setuptools

Dockerfileの作成

今回使用するDockerfileは以下の内容となります。

Dockerfile
FROM raspbian/stretch

################################################################
# 各種ライブラリをインストールする。
# 主にDockerコンテナ内で使用するツール、Python3、OpenCV、
# GUIアプリケーションを使うために必要なライブラリである。
################################################################
RUN apt-get update && apt-get install -y \
libraspberrypi-bin pkg-config lsb-release build-essential usbutils udev dirmngr \
sed sudo tar wget vim cmake git unzip \
x11-apps guvcview gpicview \
python3-pip python3-dev \
python-setuptools python3-decorator \
libjasper-dev \
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
libqtgui4 libqt4-test \
&& apt-get clean

################################################################
# ncsdkのインストール途中でcythonが必要となるためインストールしておく。
################################################################
RUN pip3 install cython

################################################################
# 環境変数の設定、主にコンテナ内でGUIアプリを使用するための設定。
################################################################
ENV LD_LIBRARY_PATH=/vc/lib:/usr/lib:$LD_LIBRARY_PATH
ENV DISPLAY=:0.0
ENV QT_X11_NO_MITSHM=1

################################################################
# コンテナ内にncsdkを格納する。作業ディレクトリは/_workとする。
# コンテナ内で使用したい任意のディレクトリ、ファイルを格納する。
################################################################
RUN mkdir /_work
ADD ncsdk /_work/ncsdk
ADD [任意のファイル、ディレクトリ] [コンテナ内の格納先]

################################################################
# Movidiusのncsdkをインストールする。
################################################################
WORKDIR "/_work/ncsdk"
RUN make install

################################################################
# OpenCVをPythonで使用するためのライブラリをインストールする。
################################################################
RUN pip3 install opencv-python

################################################################
# コンテナ内の作業ディレクトリを/_workとする。
################################################################
WORKDIR "/_work"

################################################################
# コンテナで実行する処理を記載する。
# 今回は開発環境を作りたいため、/bin/bashとしておく。
################################################################
CMD ["/bin/bash"]

Dockerイメージのビルド

いよいよDockerイメージをビルドします。この作業は時間がかかります。
Raspberry Pi3 B+で2時間30分ほどかかりました。

作成したDockerfileと同じディレクトリで以下を実行します。

$ docker build -t [任意のイメージ名] -f ./Dockerfile .

Dockerコンテナの作成

作成したイメージからコンテナを作成します。

ホストとコンテナ間でデバイスやX11のソケットを共有しています。

$ docker run -ti \
--name [任意のコンテナ名] \
--privileged \
--net=host \
-v /dev:/dev \
-v /tmp/.X11-unix/:/tmp/.X11-unix \
-e DISPLAY=$DISPLAY \
-v $HOME/.Xauthority:/root/.Xauthority:rw
[作成したイメージ名]

コンテナの実行や接続

Dockerの基本的な使い方ですが、、、

停止中のコンテナを実行するのは以下の通りです。
--interactiveを指定すると、コンテナに接続してコマンドを実行できる状態となります。

$ docker start --interactive [コンテナ名] 

実行中のコンテナに接続するには以下の通りです。

$ docker exec -ti --privileged [コンテナ名] /bin/bash

動作確認

作成したコンテナ内でUSBカメラを使って動画を映してみます。
ここではPythonでOpenCVを使ってUSBカメラの映像を表示させてみます。

camera.py
import cv2

capture = cv2.VideoCapture(0)

capture.set(3,320) # width
capture.set(4,240) # height
capture.set(5,30)  # FPS

while(capture.isOpened() is False):
  capture = cv2.VideoCapture(0)

while True:
  ret, frame = capture.read()
  cv2.imshow("camera",frame)
  if cv2.waitKey(10) > 0:
    break

capture.release()
cv2.destroyAllWindows()

以下のように実行します。

# python3 camera.py

ホスト側のデスクトップにUSBカメラの映像のウィンドウが表示されれば成功です。
何かキーを押すと終了します。

Movidiusを使ってみる

最後にMovidiusをDocker上で使用してみます。

ここではNeural Compute Application Zoo (NC App Zoo)のアプリケーションを実行してみます。

NC App ZooのリポジトリにはMovidius用のアプリケーションが多く登録されています。

まずはコンテナ内でダウンロードします。
今回はNCSDK V2を使用しているため、NC App Zooもncsdk2ブランチを使用します。

# git clone -b ncsdk2 https://github.com/movidius/ncappzoo.git

ダウンロードが完了すると"ncappzoo"ディレクトリが出来ており、その下の"apps"ディレクトリに各種アプリケーションが格納されています。

ここでは"classifier-gui"を試してみます。

ビルドして実行してみます。

# cd ncappzoo/apps/classifier-gui
# make all
# make run

以下のように表示されます。

このアプリはMovidiusを使って、GoogleNet、AlexNet、SqueezeNetの3つのネットワークで画像を分類するサンプルアプリとなっています。

他にもNC App Zooには興味深いアプリがあるため、試してみると面白いと思います。

おしまい

これで一通り、ラズパイ上のDockerでMovidiusやUSBカメラ、GUIアプリの実行環境が整うと思います。
Dockerイメージのビルドには時間がかかるのが難点ですが、一度作ってしまえば簡単にコンテナを用意でき、そこからさらに新たなバージョンのイメージを作るなど、環境の切り分けや管理が楽になるかと思います。
イメージやコンテナを作りすぎるとSDカードの容量が減ってしまうので注意が必要です・・・。