Pepperチュートリアル (7)：画像認識

#このチュートリアルの内容

このチュートリアルでは、Pepperによる画像認識について、その仕様や挙動を、サンプルを通じて説明します。

1. 画像関係の仕様
2. Choregrapheによる画像の確認方法
3. 基本的な顔の処理
4. 顔の学習と判別
5. 画像の学習と判別

なお、 **画像認識についてはバーチャルロボットでは動作確認手段はなく、Pepper実機が必要になります。** アルデバラン・アトリエ秋葉原などでPepper実機を使って実験などおこなってみていただければと思います。 (予約URL：http://pepper.doorkeeper.jp/events)

#各種センサー仕様

Pepperの画像処理にかかわる仕様としては、以下のようなものがあります。

1. 2Dカメラ×2 (額 **[A]**, 口 **[B]**) ... 出力1920×1080, 15fps
2. 3Dカメラ (赤外線照射: **[C]**, 赤外線検出: **[D]**) ... ASUS Xtion 3Dセンサー, 出力320×240, 20fps

![cameras.png](https://qiita-image-store.s3.amazonaws.com/0/54394/4b736376-9b43-0118-08fa-cd491c465825.png)


Pepperはこれらのカメラを利用して人や物体の認識をおこないます。

#Choregrapheによる画像の確認方法

Pepperのカメラによる画像の情報はChoregrapheで確認することができます。

##ビデオモニターパネルによる確認

Pepperの画像にかかわる操作には、ビデオモニターパネルを利用します。
ビデオモニターパネルは通常ポーズ ライブラリと同じ領域に配置されており、[ビデオモニター]タブを選択することで確認できます。見つからない場合は[表示]メニューから[ビデオモニター]を選択してください。

![video-monitor.png](https://qiita-image-store.s3.amazonaws.com/0/54394/e0409643-3e1b-c8c3-0154-f5a95848961f.png)

ビデオモニターパネルは、Pepperのカメラによる画像を確認する機能のほか、後述する視覚認識データベースの管理機能を提供します。

1. カメラ画像 ... Pepperのカメラの内容を確認できます
2. 再生/一時停止ボタン ... 再生すると、現在のカメラ画像をリアルタイムに確認できます。一時停止でこれを停止することができます
3. 学習モードボタン ... 画像の学習モードに切り替えます。使用方法は 画像の学習 チュートリアルで説明します
4. インポートボタン ... 視覚認識データベースをローカルファイルからChoregrapheにインポートします
5. エクスポートボタン ... 視覚認識データベースをChoregrapheからローカルファイルへとエクスポートします
6. 消去ボタン ... 現在の視覚認識データベースを消去します
7. 送信ボタン ... 現在のChoregrapheに保持されている視覚認識データベースをPepperに送信します

##Monitorによる確認

Choregrapheとあわせてインストールされる Monitor アプリケーションを使うこともできます。
Monitorアプリケーションは以下のように起動します。

1. Choregrapheと一緒にインストールされる **Monitor** アプリケーションを起動します。
    ![monitor-icon.png](https://qiita-image-store.s3.amazonaws.com/0/54394/74fa0eb6-c6b1-9586-c122-31ece21f8ee5.png)

2. Monitorアプリケーションの起動メニューで **Camera** をクリックします
    ![monitor-top.png](https://qiita-image-store.s3.amazonaws.com/0/54394/bd62555d-b4a4-e230-3bcb-4f4964299a4a.png)

3. 接続先のPepperを問い合わせるダイアログが開くので、自分が利用しているPepperを選択します
    ![connect-dialog.png](https://qiita-image-store.s3.amazonaws.com/0/54394/488ab051-1822-e098-ac88-203e85a1e76f.png)

4. Monitorのウィンドウが開くので、 **再生ボタン** をクリックします 
    ![monitor-window.png](https://qiita-image-store.s3.amazonaws.com/0/54394/b011ead1-732a-d61c-a49c-38b71acf12ba.png)

5. Pepperのカメラによる画像を確認することができます
    ![monitor-window-playing.png](https://qiita-image-store.s3.amazonaws.com/0/54394/45c60814-e83c-3875-9336-1c5b4d653e24.png)
    **一時停止ボタン** で再生を停止することができます

6. 画像以外にも、画像認識関係の情報を確認することができます。**face detectionをチェック [A]** することで、Pepperの**顔認識の状況を確認 [B]** することができます
    ![monitor-face.png](https://qiita-image-store.s3.amazonaws.com/0/54394/4d6a443f-f7fa-ddeb-d171-e44f779d4467.png)

6. 3Dカメラの内容を確認したい場合は、 **[Load Plugin]メニューの[3dsensormonitor]を選択** します
    ![monitor-menu.png](https://qiita-image-store.s3.amazonaws.com/0/54394/e930b7cf-7718-0b4f-5138-fd3398826d25.png)

7. 2Dカメラと同じ要領で、**再生ボタン** をクリックすると、デプスマップを確認することができます
    ![monitor-depthmap.png](https://qiita-image-store.s3.amazonaws.com/0/54394/8d709bf9-0725-c515-592b-e0e11f754333.png)
    **一時停止ボタン** で再生を停止することができます

このMonitorアプリケーションによって、Pepperの認識している画像の内容を詳細に確認していくことができます。


#基本的な顔認識

##顔認識

標準ボックスとして提供されているFace Detectionボックスを利用することで、現在Pepperが認識している顔の数を取得することができます。ここでは、これまで何度か使用したSay Textボックスを組み合わせて、**Pepperが認識している顔の数をしゃべらせてみる** ことをやってみます。

###つくってみる

1. 利用するボックスの準備
    * standardボックスライブラリ
        * Vision > Face Detection ... 顔検出をおこない、検出した顔の数を出力する
    * advancedボックスライブラリ ... ボックスライブラリの[advanced]タブを選択
        * Audio > Voice > Say Text ... 入力された文字列をしゃべる
2. ボックスをつなぐ
    ![face-detection-flow.png](https://qiita-image-store.s3.amazonaws.com/0/54394/5e577a74-8c2f-bdd5-ccde-5cccb3da598e.png)
    
    Face DetectionボックスのnumberOfFaces(オレンジ, タイプ:数)を、Say TextボックスのonStart(青, タイプ:文字列)を接続することで、Face Detectionボックスが出力するnumberOfFacesの値をPepperにしゃべらせることができます。
    ![facedetection-saytext.png](https://qiita-image-store.s3.amazonaws.com/0/54394/6614ed22-52b6-6cc7-d8d9-b59e294f4e3f.png)


これでアプリケーションは完成です。顔を認識するとFace DetectionボックスがnumberOfFacesを出力するので、この出力を受けてPepperがしゃべります。

###動作確認

Pepperに接続し、再生してみてください。
Pepperに顔を見せると、Pepperは「いち」「に」のように、視界に入っている顔の数をしゃべります。

なお、ロボットビューでは、Pepperが認識している顔の位置なども知ることができます。

![robotview-face.png](https://qiita-image-store.s3.amazonaws.com/0/54394/4dc22643-70b8-3f27-39d5-8687420357f3.png)

たとえば上のように、Pepperが顔を認識している状態では、ロボットビュー中に顔マークがあらわれます。これは、Pepperが認識している顔の位置を示しています。

###(補足)Say Textボックスのカスタマイズ

今回のサンプルは「いち」「に」など数字を言うだけの単純なものです。Face Detectionボックスの動きを確認するには十分ですが、なにをしているのかわかりにくいアプリケーションになってしまっています。

ここでは例として、**検出された顔の数が 1 ならば、「私の前に人が1人います」としゃべる** ように変更してみましょう。

Say TextボックスはPythonボックスであり、しゃべりに関するAPI **ALTextToSpeech API** を利用しています。Say TextボックスからALTextToSpeechに渡す文字列を操作することができれば、しゃべる内容を変えることができます。

今回はSay Textボックス内で文字列の操作をおこなってみることにします。
Say TextボックスをダブルクリックするとPythonコードが開きますので、このコード中の `onInput_onStart(self, p)` 関数を探してください。以下のような行があることがわかります。

```py
            sentence = "\RSPD="+ str( self.getParameter("Speed (%)") ) + "\ "
            sentence += "\VCT="+ str( self.getParameter("Voice shaping (%)") ) + "\ "
            sentence += str(p)
            sentence +=  "\RST\ "
            id = self.tts.post.say(str(sentence))
            self.ids.append(id)
            self.tts.wait(id, 0)
```

pにはSay Textボックスに入力された値が格納されており、 `sentence += str(p)` のところでALTextToSpeech APIに与える文字列を組み立てています。
そのため、この部分を `sentence += "ぼくの前に人が" + str(p) + "人います"` などと変更すると、「いち」ではなく、「ぼくのまえにひとがひとりいます」(「1人」は「ひとり」と話します)としゃべるようになります。


##顔追跡

[音声と同様](http://qiita.com/Atelier-Akihabara/items/52e086e7c47d85b9ed3d#1-5) に、Pepperに顔のある方向を追跡させることが可能です。
音声の例では、首の角度のみを移動していましたが、ここでは、Face Trackerボックスを使って、**顔のある方向に向かって進む** ということをやってみます。

###つくってみる

1. 利用するボックスの準備(standardボックスライブラリ)
    * Trackers > Face Tracker ... 顔の追跡をおこなう
2. ボックスをつなぐ
    ![face-tracker-flow.png](https://qiita-image-store.s3.amazonaws.com/0/54394/dadf630f-7c2c-6e89-ef91-3bf77b9e7d5e.png)

    Face Trackerボックスを開始するだけで顔追跡をおこなうことができます。

3. パラメータを設定する
    Face TrackerのパラメータのMode変数を **Move** に設定します。
    ![face-tracker-params.png](https://qiita-image-store.s3.amazonaws.com/0/54394/7954acdc-8ea4-01ee-d8ee-0acbf8f595cb.png)


これでアプリケーションは完成です。Face Trackerボックスに、「顔を識別し、その方向へ向けて移動する」という大きな機能が実装されているので、フローとしてはこのような単純なもので実現することが可能です。

###動作確認

Pepperに接続し、再生してみてください。
人間が近くにいるときは、首を曲げることで認識した顔を追跡しようとしますが、顔を向けたまま徐々に離れていくと、顔の方向に向かってPepperが移動します。
なお、有線でPepperに接続している場合は、予期しない方向に移動していかないように注意してください。

慣れないうちは、Pepperから凝視されながら追いかけられる感じで少し怖いですが、そのうち上目づかいがかわいいと思えてくる、かもしれません・・・！

#顔の学習と判別

先の例では、ただ単純に「顔」を数えたり、追いかけたりしてみました。
ここでは、誰の顔なのかを覚えさせる 学習 についてみてみます。

##顔の学習

Learn Faceボックスを利用することで、Pepperに顔と学習させることができます。
ここでは、 **再生後5秒後にPepperが見た顔を「たろう」という名称で記憶させる** ことをやってみます。

###つくってみる

1. 利用するボックスの準備(standardボックスライブラリ)
    * Data Edit > Text Edit ... 任意の文字列を出力する
    * Vision > Learn Face ... 顔と名称の対応を記憶する
2. ボックスをつなぐ
    ![learn-face-flow-1.png](https://qiita-image-store.s3.amazonaws.com/0/54394/39e04567-4e3c-a188-8f7f-b1e5f368a3cf.png)

3. 文字列を設定する
    ![learn-face-flow-2.png](https://qiita-image-store.s3.amazonaws.com/0/54394/bde5743d-c70e-2427-cb4d-4930fdce90cb.png)

これで、Learn Faceによって、Pepperの見た顔が「たろう」として学習されるようなアプリケーションを実現することができます。

###動作確認

Pepperに接続し再生後、Pepperのカメラの範囲内に顔が入るようにします。再生後5秒後、**正常に顔が学習できた場合はPepperの目が緑色** に、**失敗した場合は赤色** になります。

なお、 **Unlearn All Facesボックス** を実行することで、学習した顔データを消去することができます。

> ####![info.png](https://qiita-image-store.s3.amazonaws.com/0/54394/ed7863bd-4c2e-7710-58db-0e38a4f26959.png) [参考]Learn Faceの中身
> Learn Faceボックスの「5秒待つ」や「目が緑色に点灯」などはどのように実現しているのか、Learn Faceボックスをダブルクリックするとわかります。
> ![inside-learn-face.png](https://qiita-image-store.s3.amazonaws.com/0/54394/cb7d12d5-88e3-d343-b513-af45fb9248a3.png)
> Learn Faceボックスはフローダイアグラムボックスであり、Waitなどのより単純なボックスの集まりとして表現されていることがわかります。このように、ボックスの中身を覗くことで、ボックスの使い方を考える際の参考にすることができます。


##顔の判別

顔を学習させたら、その学習データに基づいて、**今Pepperが認識している顔が誰の顔なのかを判別し、その名前をしゃべらせる** ことをやってみます。

###つくってみる

1. 利用するボックスの準備
    * standardボックスライブラリ
         * Vision > Face Reco. ... 顔の識別をおこなう
    * advancedボックスライブラリ
         * Audio > Voice > Say Text ... 前段のBoxから入力された文字列をしゃべる

2. ボックスをつなぐ
    ![face-reco-flow.png](https://qiita-image-store.s3.amazonaws.com/0/54394/9f19d421-2c12-d068-b494-d78088ad7d98.png)
    非常に単純で、Face Reco.ボックスの出力(青, 文字列)をSay Textボックスに与えているだけです。

###動作確認

Pepperに接続、再生します。Pepperに顔を見せた場合に、「たろう」などと、学習した名前をしゃべれば成功です。
複数の顔をLearn Faceして、きちんとPepperが識別できるか、確かめてみてください。

#画像の学習と判別

Choregrapheには視覚認識データベースの操作機能があり、これを利用することで、人の顔以外のものをPepperに学習させることができます。

##画像の学習

画像を学習するためには、Choregrapheのビデオモニター パネルを利用します。ここでは、アトリエにある **NAO** を学習させてみます。

1. Pepperに接続し、ビデオモニターに対象物が映った状態で、**学習ボタン** をクリックします
    ![nao-start-recog.png](https://qiita-image-store.s3.amazonaws.com/0/54394/53b0baa7-2252-47bb-4e56-89320ee7d9c9.png)

2. **対象物の境界** でマウスの左ボタンをクリックします
    ![nao-recog-point-1.png](https://qiita-image-store.s3.amazonaws.com/0/54394/bdb717a8-97fe-c176-142f-d1f541eb57dc.png)

3. 直線を描く感覚で、頂点を左ボタンクリックして作成していきます
    ![nao-recog-point-2.png](https://qiita-image-store.s3.amazonaws.com/0/54394/8c4cae6d-874b-ad4c-b1a4-3d0d18b61df1.png)

4. 対象物を囲むように頂点を設定していき、最後に、開始点を左クリックします
    ![nao-recog-point-3.png](https://qiita-image-store.s3.amazonaws.com/0/54394/5b2f7a1a-9997-4ee7-9a06-86294c5dab63.png)

5. 対象物の領域が識別され、情報入力を求めるダイアログが開くので、適当な情報を入力します
    ![nao-recog-finished.png](https://qiita-image-store.s3.amazonaws.com/0/54394/32069067-ec20-df00-8d81-415f2603f8d6.png)
    
    ここでは NAO と入力します。
    ![recog-register.png](https://qiita-image-store.s3.amazonaws.com/0/54394/e30f7d97-ed33-ae07-e0b3-12aefe59276b.png)
    
6. Choregrapheの視覚認識データベースに登録された情報を、 **[現在の視覚認識データベースをロボットに送信]ボタンをクリック** してPepperに送信します
    ![send-recog-db.png](https://qiita-image-store.s3.amazonaws.com/0/54394/f43c72d8-4080-219e-194e-d0f1f4342744.png)

これで、PepperにNAOの画像的な特徴に対して、「NAO」という文字列を関連させることができました。

##画像の判別

顔の判別と同様、**学習させた視覚認識データベースの内容に基づいて、今見ているものが何なのかをしゃべらせる** ことをやってみます。

###つくってみる

Vision Reco.ボックスを利用することで、現在Pepperが見ている内容と視覚認識データベースを照合し、オブジェクトの名前を得ることができます。

1. 利用するボックスの準備
    * standardボックスライブラリ
         * Vision > Vision Reco. ... 視覚認識データベースを照合する
    * advancedボックスライブラリ
         * Audio > Voice > Say Text ... 前段のBoxから入力された文字列をしゃべる

2. ボックスをつなぐ(1)
    ![vision-reco-flow-1.png](https://qiita-image-store.s3.amazonaws.com/0/54394/0d24e719-8781-c233-856f-46bfdbe58b8d.png)
    まず、顔の判別と同様、Vision Reco.ボックスのonPictureLabel出力(青, 文字列)をSay Textボックスに与えます。

3. ボックスをつなぐ(2)
    このサンプルでは、認識後しゃべっている間にVision Reco.ボックスの動作を停止するため(理由は後述)、Vision Reco.ボックスの**onPictureLabel出力**と**onStop入力**を接続します。
    ![vision-reco-flow-2.png](https://qiita-image-store.s3.amazonaws.com/0/54394/fe2d2f5c-d62b-d5db-aaf5-bb5e4fdfde9b.png)
    しゃべり終わったあと、Vision Reco.ボックスの動作を再開するため、Say Textボックスの **onStopped出力** をVision Reco.ボックスの **onStart入力**に接続します。
    ![vision-reco-flow-3.png](https://qiita-image-store.s3.amazonaws.com/0/54394/1913b738-129e-9de9-400e-f3df7ddc9a39.png)

    > ####![info.png](https://qiita-image-store.s3.amazonaws.com/0/54394/ed7863bd-4c2e-7710-58db-0e38a4f26959.png) [Tips]Vision Reco.ボックスの明示的な停止
    > Vision Reco.ボックスは画像を認識すると、認識している状況に変化がなくても定期的に出力をおこないます。
    > また、先に見たSay TextボックスからALTextToSpeech APIへの要求においては、Say Textボックスがすでに動作している場合でも、新たに入力された文字列は破棄されず次に処理できるよう蓄積されるようになっています。
    > 
    > そのため、2.の接続だけだと、NAOを見せている間ずっと「NAO」「NAO」「NAO」としゃべり続けてしまうだけでなく、NAOをPepperの視界から外してもこれがしばらく続いてしまうことになります。
    > このような問題を防ぐため、Vision Reco.ボックスが認識結果を出力したのち、Vision Reco.ボックスをいったん停止、Say Textボックスが終わってからVision Reco.の動作を再開するということをおこなっています。


###動作確認

Pepperに接続し、作成したアプリケーションを再生してみてください。
NAOを見せたときに「NAO」と言えば成功です。

このように、Pepperには画像認識のためのさまざまな機能が用意されています。視覚から得た情報でPepperをコントロールすることで、制御の幅が広がります。ぜひ色々、試してみてください。