OGIMOノート

6歳の娘と、4歳の息子(脳性麻痺)を持った父親エンジニアの備忘録。自作の電子工作おもちゃ/リハビリ器具の製作記録、勉強記録を残していきます

【組込みDeep Learning】Movidius + raspberry pi+ROS環境構築

Movidius を使ってみる

f:id:motokiinfinity8:20180209212816j:plain

Caffe/Tensorflowに対応した組み込み向けVPUスティックデバイス Movidius。 Intelに買収される前から目をつけていたのですが、いつの間にやらここまで有名になるとは。
ラズパイの様なGPUを持たないマシンでもDeep Learningをエッジ側で使えるので、使いこなせれば非常に便利であろう。

自作ROSロボットで、子供の顔を認識させて追従させる様なロボットを作りたかったので、ここはDeep Learning環境の構築に前向きにトライしてみます!

まずは、SDKを立ち上げてみた。
ここのサイトを参考にました。

【Movidius™NCS&RaspberryPi】リアルタイム物体認識【TensorFlow】 - Qiita

Tensorflowのインストール

ARM用Tensorflowはビルドでトラブりがちなので、コンパイル済を取ってくる。

wget https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.3.1/ten
sorflow-1.3.1-cp35-none-linux_armv7l.whl
sudo pip3 install tensorflow-1.3.1-cp35-none-linux_armv7l.whl 
SDKのインストール

公式サイトにしたがってインストール。バージョンは1.11.00

git clone http://github.com/Movidius/ncsdk && cd ncsdk && make install && make examples

OpenCVもビルドしようとするがこれは失敗するはず。前投稿の手順にしたがって事前にインストールしておくこと。

サンプル動作をさせてみる

SDK内にCaffe,Tensorflowの学習済モデルをMovidius用graphファイルに変換したものが入っているので、これを利用する。とりあえず参考サイト通り、GoogleのInceptionV3モデルを使ってみた。

cd ncsdk/examples/tensorflow/inception_v3
python3 run.py

で実行。例えば、下記のルリコシボタンインコの写真の場合、認識結果は以下。
f:id:motokiinfinity8:20180209223407j:plain

                                                                                                          • -

91 lorikeet 0.52588
93 bee eater 0.11914
89 macaw 0.023178
12 goldfinch, Carduelis carduelis 0.0059319
137 European gallinule, Porphyrio porphyrio 0.0055695

                                                                                                            • -

lorikeet (インコ)なので正解!
なお、認識時間は 3200×2400の写真で 0.53秒。ざっくり計算でVGA(640×480)ならば30fpsは出そうな雰囲気(実際は画像処理のオーバーヘッドの方が大きそう) なかなか優秀だと思う。

なお、run.py のコードは以下

from mvnc import mvncapi as mvnc
import sys
import numpy
import cv2
import time

path_to_networks = './'
path_to_images = '../../data/images/'
graph_filename = 'graph'
image_filename = path_to_images + 'bird.jpg'

start = time.time()

#mvnc.SetGlobalOption(mvnc.GlobalOption.LOGLEVEL, 2)
devices = mvnc.EnumerateDevices()
if len(devices) == 0:
    print('No devices found')
    quit()

device = mvnc.Device(devices[0])
device.OpenDevice()

print("Open device : {0}".format(time.time()-start) + "[sec]")

#Load graph
with open(path_to_networks + graph_filename, mode='rb') as f:
    graphfile = f.read()

#Load preprocessing data
mean = 128
std = 1/128

#Load categories
categories = []
with open(path_to_networks + 'categories.txt', 'r') as f:
    for line in f:
        cat = line.split('\n')[0]
        if cat != 'classes':
            categories.append(cat)
    f.close()
    print('Number of categories:', len(categories))

#Load image size
with open(path_to_networks + 'inputsize.txt', 'r') as f:
    reqsize = int(f.readline().split('\n')[0])

graph = device.AllocateGraph(graphfile)

print("Open graph : {0}".format(time.time()-start) + "[sec]")

img = cv2.imread(image_filename).astype(numpy.float32)
dx,dy,dz= img.shape
delta=float(abs(dy-dx))
if dx > dy: #crop the x dimension
    img=img[int(0.5*delta):dx-int(0.5*delta),0:dy]
else:
    img=img[0:dx,int(0.5*delta):dy-int(0.5*delta)]
img = cv2.resize(img, (reqsize, reqsize))

img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

for i in range(3):
    img[:,:,i] = (img[:,:,i] - mean) * std

print('Start download to NCS...')
graph.LoadTensor(img.astype(numpy.float16), 'user object')
output, userobj = graph.GetResult()

print("get tensor result: {0}".format(time.time()-start) + "[sec]")

top_inds = output.argsort()[::-1][:5]

print(''.join(['*' for i in range(79)]))
print('inception-v3 on NCS')
print(''.join(['*' for i in range(79)]))
for i in range(5):
    print(top_inds[i], categories[top_inds[i]], output[top_inds[i]])

print(''.join(['*' for i in range(79)]))
graph.DeallocateGraph()
device.CloseDevice()
print('Finished')

MovidiusのROS対応

上記のMovidius SDKでは、Python3を使っていた。残念ながら、ROSは、Python2.7系がdefaultのため、Python3系を使うのはなかなかハードルが高そう。どうしようか悩んでいたところ、以下のサイトを発見。
github.com

どうやら、公式にROS対応している様だ。これはありがたい。

Install NCSDK v1.11.00
Install NC APP Zoo

が必要とのことで、GitHub - movidius/ncappzoo: Contains examples for the Movidius Neural Compute Stick.から NC APPをインストール

git clone https://github.com/movidius/ncappzoo
mv ncappzoo /opt/movidius/ncappzoo
ROSパッケージをインストール

参考サイトの手順にしたがって進める。

# Building
cd ~/catkin_ws/src
git clone https://github.com/intel/ros_intel_movidius_ncs.git
cd ros_intel_movidius_ncs
git checkout master
cd ~/catkin_ws
catkin_make
# Installation
catkin_make install
source install/setup.bash
# Copy label files from this project to the installation location of NCSDK
cp ~/catkin_ws/src/ros_intel_movidius_ncs/data/labels/* /opt/movidius/ncappzoo/data/ilsvrc12/

ただし、x86ベースのため、catkine_make時に sse4 エラーが発生する。そのため、
ros_intel_movidius_ncs/src/CMakeLists.txt にある下記コマンドオプションをコメントアウトしておく

  # Add x86 intrinsic compiler support
  #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
  #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mf16c")
  #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")

先ほどと同じ様に、、GoogleのInceptionV3モデルを使ってみる。

cd /opt/movidius/ncappzoo/tensorflow/inception_v3
make

RuntimeError: module compiled against API version 0xc but this version of numpy is 0xb
Segmentation fault (core dumped)
Makefile:41: recipe for target 'weights' failed
make: *** [weights] Error 139

でコケた。どうやら、numpyが1.13.0と1.11.0の2つが多重インストールされている様なので、pip3 uninstall numpy を2回かけた後、pip3 install numpy で 1.14.0をインストールしてみる。これで、ビルドが進んだ!

ちなみに、AlexNetを使ってみる場合は以下のコマンド。

cd /opt/movidius/ncappzoo/caffe/AlexNet
make

その後、USBカメラからの映像を確認する

roslaunch movidius_ncs_launch ncs_stream_classification_example.launch camera_topic:="/usb_cam/image_raw"

これで行けそうな見込み! と思いきや、

process[movidius_ncs_example_stream_classification-1]: started with pid [15135]

から動かず映像でず。解析はもう少しかかりそう。