新宿ラーニングセンターのPepperにAmazon Rekognitionで顔の分析をしてもらいました
※当記事はソフトバンクロボティクスのPepperを活用し、自社が独自に実施しているものです。
※当記事は2018年7月時点の内容です。現在、トレノケート新宿ラーニングセンターにPepperはありません。
こんにちは。ラーニングサービス本部 テクニカルトレーニング第1部の山下です。
弊社新宿ラーニングセンターのPepperが撮影した写真を、AWSのディープラーニングベースの視覚分析サービスのAmazon Rekognitionで分析してその結果をPepperにしゃべってもらうというデモをしました。
新宿ラーニングセンターのPepper
弊社新宿ラーニングセンター(20F)には受付にPepperがいます。
ちなみに私よりも先輩です。
※ソフトバンクロボティクスのPepperを活用し、自社が独自に実施しているものです。
Pepperは27種のセンサーを持っていて、非常に多彩なアクションを行うことが出来ます。
せっかくなので、Pepperに顔を見て分析した結果を話ディープラーニングしてもらうことにしました。
そのためにPepperとAWSのディープラーニングベースの視覚分析サービスAmazon Rekognitionをつなげます。
Pepperにやってもらったこと
※ソフトバンクロボティクスのPepperを活用し、自社が独自に実施しているものです。
Pepperに「顔を見て」と言うと追いかけてきて写真を取られます。
その写真はAmazon API Gatewayを経由してAWS LambdaによりAmazon S3にアップロードされます。
Amazono S3の写真に対してAmazon Rekognitionが顔を分析した結果はAWS LambdaよりAmazon API Gatewayを経由してレスポンスとして返されます。
顔の分析結果をPepperが受け取って、Python Scriptによって文章を整形して教えてくれます。
例
「あなたは24歳~32歳の女性でメガネをしていて笑っています。幸せ78% , 驚いている22%です。間違いない!」
「あなたは32歳~38歳の男性でひげをはやしています。悲しそう83%, 怒っている17%です。間違いない!」
AWS側の開発/設定
AWS側には下記が必要ですのでAPI GatewayとLambdaで実装します。
(1) Pepperから送信される画像をS3に格納する
(2) S3の画像をAmazon Rekognitionで分析する
LambdaのランタイムはPython3系です。
撮影した写真をS3に格納する
s3 = boto3.resource('s3')
bucket = s3.Bucket(bucekt_name)
image_body = base64.b64decode(event['body-json'])
n = 10
key = ''.join([random.choice(string.ascii_letters + string.digits) for i in range(n)])
bucket.put_object(
Body=image_body,
Key=key
)
* バイナリデータをb64decodeでデコード
* S3オブジェクトキーをrandomで生成
* buckt.put_objectでS3に画像ファイルをアップロード
API Gatewayの設定
バイナリメディアタイプ
[設定] – [バイナリメディアタイプ]
* [設定] – [バイナリメディアタイプ]に、image/jpg を設定
* 他は任意で追加
本文マッピングテンプレート
[リソース] – [統合リクエスト] – [本文マッピングテンプレート]
* Content-Typeに image/jpg を追加。
* テンプレートの生成は「メソッドリクエストのパススルー」を設定。
* 他のContent-Typeは任意で追加。
画像を解析する
client = boto3.client('rekognition')response = client.detect_faces( Image={ 'S3Object': { 'Bucket': bucekt_name, 'Name': key } }, Attributes=['ALL'])return response
* 引数のバケット名、オブジェクトキー対象の画像を分析
* バージョニングしているS3の場合はバージョンIDを指定することも可能
Rekognition 顔分析(detect_faces)のレスポンス
FaceDetailsのに画像の中の人数分の結果が配列になって戻されます。
key
|
内容
|
値の例
|
AgeRange.Low
|
年齢幅の下 |
26
|
AgeRange.High
|
年齢幅の上
|
43
|
Smile.Value
|
笑顔か
|
true or false
|
Smile.Confidence
|
笑顔の可能性
|
88.67390441894531
|
Eyeglasses.Value
|
眼鏡をしているか
|
true or false
|
Eyeglasses.Confidence
|
眼鏡をしている可能性
|
99.99993133544922
|
Sunglasses.Value
|
サングラスをしているか
|
true or false
|
Sunglasses.Confidence
|
サングラスをしている可能性
|
99.99896240234375
|
Gender.Value
|
性別
|
Male or Female
|
Gender.Confidence
|
性別の可能性
|
52.36514663696289
|
Beard.Value
|
髭が生えているか
|
true or false
|
Beard.Confidence
|
髭の可能性
|
99.86187744140625
|
Mustache.Value
|
口ひげが生えているか
|
true or false
|
Mustache.Confidence
|
口ひげの可能性
|
99.57250213623047
|
EyesOpen.Value
|
目が空いているか
|
true or false
|
EyesOpen.Confidence
|
目が空いている可能性
|
99.9950942993164
|
MouthOpen.Value
|
口が空いているか
|
true or false
|
MouthOpen.Confidence
|
口が空いている可能性
|
98.92902374267578
|
Emotions.Type
|
感情
|
HAPPY,SAD,ANGRY
|
Emotions.Confidence
|
感情の精度
|
98.92902374267578
|
※Emotionsは配列です。
※Emotionsの値にはHAPPY,SAD,ANGRY,CONFUSED,DISGUSTED,SURPRISED,CALM,UNKNOWNがあります。
AWS側は以上です。
続いてPepper側の開発/設定を行います。
Pepper側の開発/設定
PepperのSDKであるChoregrapheを使いました。
ChoregraheにはボックスというPepperを動かすためのコンポーネントが多数あらかじめ用意されています。
そのボックスを選んでつなぐことでPepperを簡単に動かすことが出来ます。
それでは今回選んでつないだボックスが、それぞれ何をしているかを以下に書きます。
Set Language
まず最初にこのプログラムが実行されたときにPepperが扱う言語を設定します。
今回は日本語を扱いたいのでJapaneseにします。
OnReadyから次のボックスのSpeech Recoへつなぎます。
Speech Reco
Pepperに話しかけた言葉をトリガーとしたいので、Speech Recoのボックスを使います。
今回は「かおをみて」と言うと次の動作に遷移します。
WordListにはセミコロン ; 区切りで複数の言葉を登録することも出来ます。
wordRecognizedから次にボックスへ文字列を渡してつなぎます。
今回はこの文字列の再利用はしませんが、複数のWordListに対して聞き取った言葉の分岐を行うなどSwitchCaseと組み合わせて使用することが出来ます。
次はFace Trackerのボックスへつなぎます。
Face Tracker
話しかけたあと、顔を追いかけてほしいので、Face Trackerを使います。
Face Trackerが実行されるとPepperが両手をふりあげて顔を追いかけてきます。
ModeをHeadにすると頭だけを動かしますが、今回はおおげさに動かしたかったのでMoveにしました。
Efectは右腕左腕のどちらかでも両腕でも選択することが出来ます。
これも派手にしたかったので両腕にしました。
顔が見つかったとPepperが判断すると、TargetReachedのイベントが発生します。
TargetReacheから次のボックスのTake Pictureにつなぎます。
Take Picture
Pepperが顔を見つけたらその顔の写真をとりたいので、Take Pictureボックスを利用します。
撮影した写真はPepperローカルに image.jpgというファイル名で保存されます。
これをタブレットに表示したいので、このあとOnStoppedイベントから次のShow Imageボックスへつなぎます。
このへんの設定はこちらの
Pepperで画像を撮影してタブレットに画像表示
を参考にさせていただきました。
ボックスはダブルクリックするとスクリプトエディタが起動してPythonコードを直接編集できます。
先ほどの参考サイトの記載どおりに、コードを編集します。
onLoadメソッドでALFrameManagerオブジェクトを生成します。
def onLoad
(self):
# ここから追加 self.framemanager = ALProxy("ALFrameManager")# ここまで追加
onInput_onStartメソッドで先ほど生成したALFrameManagerオブジェクトのgetBehaviorPathメソッドを使って、写真の保存先のディレクトリを再定義します。
このディレクトリがShow Imageボックスで表示する画像のディレクトリパスです。
平行してAmazon Rekognitionで解析するためのAPIへ画像を渡すためにPythonスクリプトのボックスへもつないでいます。
PythonスクリプトがS3へアップロードする画像の参照先も同じディレクトリです。
def onInput_onStart
(self):
# ここから追加 import os self.recordFolder = os.path.join( self.framemanager.getBehaviorPath(self.behaviorId), "../html")# ここまで追加
Show Image
Pepperが解析した結果を話している間、撮影した写真をタブレットに表示するためにShow Imageボックスを使います。
表示する写真はimage.jpgです。
Take Pictureでは拡張子が指定できないのか省略形式で入力、
Show Imageでは拡張子までを指定、とややくせがあるので注意です。
Show Imageで表示する写真はhtmlディレクトリが必要なのでプロジェクト直下に作成しておく必要があります。
このままのShow Imageだと、ファイルパスが同じ場合に、前の画像がキャッシュされてしまうので、それを回避するために、先述のサイトを参考にさせていただき、下記コードを追加しています。
def onInput_onStart
(self):
# ここから追加 import time# ここまで追加 tabletService = self._getTabletService() if tabletService: try: url = self.getParameter("ImageUrl") if url == '': self.logger.error("URL of the image is empty") if not url.startswith('http'): url = self._getAbsoluteUrl(url)# ここから追加 url += "?" + str(time.time())# ここまで追加 tabletService.showImage(url)
Python Script
Show Imageで撮影した写真の表示と平行して、本処理である画像をAmazon API Gateway経由でAWS Lambdaを実行し、Amazon S3にアップロードしてAmazoon Rekognitionで解析した結果を受け取ります。
呼び出すコードは下記のようにしました。
def onInput_onStart
(self): import os import requests recordFolder = os.path.join( self.framemanager.getBehaviorPath(self.behaviorId), "../html") file_path = recordFolder + '//image.jpg' data = open(file_path, 'rb').read() response = requests.post( url=api_url, data=data, headers={'Content-Type': 'image/jpg'} )
requestsモジュールはPepperに標準でインストールされているので、インストール不要です。
Python Scriptでは結果として次のボックスの渡したい文字列を、self.text()メソッドにセットします。
self.text(return_text)
self.text()メソッドにセットした文字列は出力のtextから受け取れるので、それを次のSay Textボックスへ渡します。
Say Text
Python ScriptでAPIを実行した結果をtextで受け取って、Say Textボックスを使ってPepperに話してもらいます。
Say Textは直前のボックスから渡されたテキストをそのまま話します。
話すスピードや抑揚の調整ができます。
そして、OnStoppedで話し終わったあとに、タブレットをデフォルトの表示に戻すために、別で用意したShow Imageのボックスへつなぎます。
Show Image(デフォルト画像表示用)
プログラム開始直後に表示しておいて、Take Pictureで新たな写真が撮影されるまで表示されています。
Say Textで顔分析結果を話終わった後もこのShow Imageに戻るようにフローをつないでいます。
デフォルトイメージはあらかじめプロジェクトに追加しておいたロゴ画像が表示されるようにしました。
今回のデモを作ってみて
Python Scriptではコードを書いてAPIを実行して結果を日本語文字列になるように調整していますが、それ以外のPepperそのものの動作については、ほとんどGUIだけで実装することが出来ました。
各ボックスも必要に応じてPythonコードを修正出来るので、どうしても変更したい場合にこまわりが効きます。
Amazon RekognitionはSDKを使えばたったの1行で実装することができました。
このように先端技術と呼ばれるものが標準化されて非常に扱いやすいサービスとして提供されています。
そしてAWSもPepperも使いたいサービスを選択して組み合わせるという特徴が似ています。
インフラを考えるのではなく、サービスを組み合わせて設計するといった機会が今後ますます増えていくのではと感じた次第でございます。
※ソフトバンクロボティクスのPepperを活用し、自社が独自に実施しているものです。
▼オススメ資料ダウンロード:「Amazon Web Services 学びの小冊子」▼
トレノケートのAWS認定講師による「Amazon Web Services学びの小冊子」をプレゼント中!
AWSの導入や資格取得準備、AWSへの移行をお考えの方、是非ご活用ください。
→ 詳細はこちらから