Movidius を使ってみる
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
で実行。例えば、下記のルリコシボタンインコの写真の場合、認識結果は以下。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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]
から動かず映像でず。解析はもう少しかかりそう。