RasPi : Movidius ニューラル・コンピュート・スティックで遊ぶ♬～Picameraで物体検出～ 

[前回は、難解なインストール・シークエンスを乗り越えて、同梱のExampleを動かした](https://qiita.com/MuAuan/items/aeacb2faffb8a388d7d2)が、今回は、以下のサイトにある物体検出アプリMobileNetを動かし、Picameraを使った物体検出アプリを作成した。
※これはかなりすんなりできました！
　つまり、インストールさえ乗り越えれば簡単に使えそうです。

###今回やったこと
1．Exampleサイトから必要なものを一式ダウンロード
2．コンパイル
3．実行
4．改変してPicamera入力＆物体検出
###1．Exampleサイトから必要なものを一式ダウンロード
[ncappzoo / caffe / SSD_MobileNet / ](https://github.com/movidius/ncappzoo/tree/master/caffe/SSD_MobileNet)
から、すべてのファイルをダウンロードする。

###2．コンパイル
/caffe/SSD_MobileNet $ sudo makeを実行する
※今回は、全部で2－3分で終了しています。
なお、Makefileは以下の通りです。
[ncappzoo / caffe / SSD_MobileNet / Makefile ](https://github.com/movidius/ncappzoo/blob/master/caffe/SSD_MobileNet/Makefile)

これを見ればわかりますが、実際の出力から何をやっているか逐次的に見ていこうと思います。

```
/caffe/SSD_MobileNet $ sudo make
making prereqs
making prototxt
Downloading Prototxt file
--2018-06-03 09:24:48--  https://raw.githubusercontent.com/chuanqi305/MobileNet-SSD/master/MobileNetSSD_deploy.prototxt
raw.githubusercontent.com (raw.githubusercontent.com) をDNSに問いあわせています... 151.101.72.133
raw.githubusercontent.com (raw.githubusercontent.com)|151.101.72.133|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 29353 (29K) [text/plain]
`MobileNetSSD_deploy.prototxt' に保存中
bileNetSSD_deploy.p 100%[===================>]  28.67K  --.-KB/s    in 0.04s   
2018-06-03 09:24:54 (704 KB/s) - `MobileNetSSD_deploy.prototxt' へ保存完了 [29353/29353]
prototxt file downloaded.
patching prototxt.
patching file patched_MobileNetSSD_deploy.prototxt (read from MobileNetSSD_deploy.prototxt)
```
Prototxtを上記サイトからダウンロードして、`MobileNetSSD_deploy.prototxt' に保存しています。ほとんど時間がかかっていません。

```
making caffemodel
Attempting download of caffemodel file from this url: 
https://drive.google.com/open?id=0B3gersZ2cHIxRm5PMWRoTkdHdHc
--2018-06-03 09:24:54--  https://docs.google.com/uc?export=download&confirm=.*/%5C1%5Cn/p')&id=0B3gersZ2cHIxRm5PMWRoTkdHdHc
docs.google.com (docs.google.com) をDNSに問いあわせています... 216.58.199.238, 2404:6800:4004:80f::200e
docs.google.com (docs.google.com)|216.58.199.238|:443 に接続しています... 接続しました。
。。。中略
doc-0g-bs-docs.googleusercontent.com (doc-0g-bs-docs.googleusercontent.com)|216.58.197.225|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 特定できません [application/octet-stream]
`MobileNetSSD_deploy.caffemodel' に保存中
MobileNetSSD_deploy     [           <=>      ]  22.08M   874KB/s    in 27s     
2018-06-03 09:25:29 (843 KB/s) - `MobileNetSSD_deploy.caffemodel' へ保存終了 [23147564]
```
次にCaffemodelをダウンロードして、`MobileNetSSD_deploy.caffemodel' に保存しました。途中、接続しなおしましたが、無事ダウンロードできました。

```
making compile
mvNCCompile v02.00, Copyright @ Movidius Ltd 2016
/usr/local/bin/ncsdk/Controllers/FileIO.py:52: UserWarning: You are using a large type. Consider reducing your data sizes for best performance
  "Consider reducing your data sizes for best performance\033[0m")
```
そして、mvNCCompile v02.00, Copyright @ Movidius Ltd 2016でコンパイルするんですね。なんか文句言われていますが、。。

###3．実行
さて、コンパイルされた資材を動かします。
単に、```python3 run.py```するだけです。

```
pi@raspberrypi:~/workspace/ncsdk/examples/caffe/SSD_MobileNet $ python3 run.py
total num boxes: 1
box at index: 0 : ClassID: chair  Confidence: 100.0%  Top Left: (226, 107)  Bottom Right: (573, 679)

** (SSD MobileNet - hit any key to exit:5339): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files
```
※5339が文句言われてるみたいですね。。。でも、これでちゃんと終了できます。
結果は、以下の画像なので椅子ですね。しかし、100.0％ってのが胡散臭い（笑）
位置も正しく四角で囲われています。

###4．改変してPicamera入力＆物体検出
以下のように、Picameraの撮影画像（ほぼ動画）を物体検出するように改変しました。
元のアプリとの違いを簡単に説明します。

```python
#! /usr/bin/env python3
# Copyright(c) 2017 Intel Corporation. 
# License: MIT See LICENSE file in root directory.

from mvnc import mvncapi as mvnc
import numpy
import cv2
import sys
import subprocess
```
このアプリは# License: MIT になっています。先のものはガチなCopyrightでしたが、。。。

```python
dim=(300,300)
EXAMPLES_BASE_DIR='../../'
IMAGES_DIR = EXAMPLES_BASE_DIR + 'data/images/'
#IMAGE_FULL_PATH = IMAGES_DIR + 'nps_chair.png'
```
元は、'nps_chair.png'を読み込んでいました。

```python
args = ['raspistill','-w','480','-h','360','-o', "../../data/images/img.jpg", '-t', '1']
subprocess.Popen(args)
#photo = open('img.jpg', 'rb')
IMAGE_FULL_PATH = IMAGES_DIR + 'img.jpg'
```
上記のようにPicameraで撮影して、img.jpgとして保存し、さらに下記で読み込ためのPathを指定しています。
ここでは、Picameraの撮影画像を表示していますが、以下ではうるさいので表示なしにしています。

```python
LABELS = ('background',
          'aeroplane', 'bicycle', 'bird', 'boat',
          'bottle', 'bus', 'car', 'cat', 'chair',
          'cow', 'diningtable', 'dog', 'horse',
          'motorbike', 'person', 'pottedplant',
          'sheep', 'sofa', 'train', 'tvmonitor')
```
上記はカテゴリのLABELSですが、これは[The PASCAL VOC projectのVOC2007](http://host.robots.ox.ac.uk/pascal/VOC/)などのものです。

```python
    # Get a list of ALL the sticks that are plugged in
    # we need at least one
    devices = mvnc.EnumerateDevices()
    if len(devices) == 0:
        print('No devices found')
        quit()

    # Pick the first stick to run the network
    device = mvnc.Device(devices[0])

    # Open the NCS
    device.OpenDevice()
```
ここで、mvnc（MOVIDIUS　NCS）を探しています。そして、デバイスをオープンします。

```python
    while True:
        args = ['raspistill','-w','480','-h','360','-o', "../../data/images/img.jpg", '-t', '1','-n']
        subprocess.Popen(args) 	
    # read the image to run an inference on from the disk
        infer_image = cv2.imread(IMAGE_FULL_PATH)
```
今回改変した部分です。
Picameraで読み込んでいます。
ここでは、いらないので'-n'を指定して撮影画像を表示OFFにしました。
※Picameraの機能は以下のおまけの通りです

```python
    # run a single inference on the image and overwrite the
    # boxes and labels
        run_inference(infer_image, graph)
    # display the results and wait for user to hit a key
        cv2.imshow(cv_window_name, infer_image)
        if cv2.waitKey(1000)>0:
              break
    # Clean up the graph and the device
    graph.DeallocateGraph()
    device.CloseDevice()
```
一応、どれかキーを押すとWhileから脱出するようにしました。
終了時、Graphを消して、NCSデバイスをクローズしています。

###まとめ
・MOVIDIUSのGitHubサイトの物体検出アプリをダウンロードして使ってみた
・Picameraを使って実際に撮影した画像（ほぼ動画）の物体検出を実施した

Flask化して監視システム作ろう
。。。鳥検出できそう
。。。鳥いたら画像保存とかとか。。。、

###おまけ
Picameraも機能盛りだくさんです。

```
$ raspistill --help
Runs camera for specific time, and take JPG capture at end if requested

usage: raspistill [options]

Image parameter commands

-?, --help	: This help information
-w, --width	: Set image width <size>
-h, --height	: Set image height <size>
-q, --quality	: Set jpeg quality <0 to 100>
-r, --raw	: Add raw bayer data to jpeg metadata
-o, --output	: Output filename <filename> (to write to stdout, use '-o -'). If not specified, no file is saved
-l, --latest	: Link latest complete image to filename <filename>
-v, --verbose	: Output verbose information during run
-t, --timeout	: Time (in ms) before takes picture and shuts down (if not specified, set to 5s)
-th, --thumb	: Set thumbnail parameters (x:y:quality) or none
-d, --demo	: Run a demo mode (cycle through range of camera options, no capture)
-e, --encoding	: Encoding to use for output file (jpg, bmp, gif, png)
-x, --exif	: EXIF tag to apply to captures (format as 'key=value') or none
-tl, --timelapse	: Timelapse mode. Takes a picture every <t>ms. %d == frame number (Try: -o img_%04d.jpg)
-fp, --fullpreview	: Run the preview using the still capture resolution (may reduce preview fps)
-k, --keypress	: Wait between captures for a ENTER, X then ENTER to exit
-s, --signal	: Wait between captures for a SIGUSR1 or SIGUSR2 from another process
-g, --gl	: Draw preview to texture instead of using video render component
-gc, --glcapture	: Capture the GL frame-buffer instead of the camera image
-set, --settings	: Retrieve camera settings and write to stdout
-cs, --camselect	: Select camera <number>. Default 0
-bm, --burst	: Enable 'burst capture mode'
-md, --mode	: Force sensor mode. 0=auto. See docs for other modes available
-dt, --datetime	: Replace output pattern (%d) with DateTime (MonthDayHourMinSec)
-ts, --timestamp	: Replace output pattern (%d) with unix timestamp (seconds since 1970)
-fs, --framestart	: Starting frame number in output pattern(%d)
-rs, --restart	: JPEG Restart interval (default of 0 for none)

Preview parameter commands

-p, --preview	: Preview window settings <'x,y,w,h'>
-f, --fullscreen	: Fullscreen preview mode
-op, --opacity	: Preview window opacity (0-255)
-n, --nopreview	: Do not display a preview window

Image parameter commands

-sh, --sharpness	: Set image sharpness (-100 to 100)
-co, --contrast	: Set image contrast (-100 to 100)
-br, --brightness	: Set image brightness (0 to 100)
-sa, --saturation	: Set image saturation (-100 to 100)
-ISO, --ISO	: Set capture ISO
-vs, --vstab	: Turn on video stabilisation
-ev, --ev	: Set EV compensation - steps of 1/6 stop
-ex, --exposure	: Set exposure mode (see Notes)
-awb, --awb	: Set AWB mode (see Notes)
-ifx, --imxfx	: Set image effect (see Notes)
-cfx, --colfx	: Set colour effect (U:V)
-mm, --metering	: Set metering mode (see Notes)
-rot, --rotation	: Set image rotation (0-359)
-hf, --hflip	: Set horizontal flip
-vf, --vflip	: Set vertical flip
-roi, --roi	: Set region of interest (x,y,w,d as normalised coordinates [0.0-1.0])
-ss, --shutter	: Set shutter speed in microseconds
-awbg, --awbgains	: Set AWB gains - AWB mode must be off
-drc, --drc	: Set DRC Level (see Notes)
-st, --stats	: Force recomputation of statistics on stills capture pass
-a, --annotate	: Enable/Set annotate flags or text
-3d, --stereo	: Select stereoscopic mode
-dec, --decimate	: Half width/height of stereo image
-3dswap, --3dswap	: Swap camera order for stereoscopic
-ae, --annotateex	: Set extra annotation parameters (text size, text colour(hex YUV), bg colour(hex YUV))


Notes

Exposure mode options :
off,auto,night,nightpreview,backlight,spotlight,sports,snow,beach,verylong,fixedfps,antishake,fireworks

AWB mode options :
off,auto,sun,cloud,shade,tungsten,fluorescent,incandescent,flash,horizon

Image Effect mode options :
none,negative,solarise,sketch,denoise,emboss,oilpaint,hatch,gpen,pastel,watercolour,film,blur,saturation,colourswap,washedout,posterise,colourpoint,colourbalance,cartoon

Metering Mode options :
average,spot,backlit,matrix

Dynamic Range Compression (DRC) options :
off,low,med,high

Preview parameter commands

-gs, --glscene	: GL scene square,teapot,mirror,yuv,sobel,vcsm_square
-gw, --glwin	: GL window settings <'x,y,w,h'>
```