新宿ラーニングセンターの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への移行をお考えの方、是非ご活用ください。
→ 詳細はこちらから


山下 光洋(やました みつひろ)

山下 光洋(やました みつひろ)

トレノケート株式会社 講師。AWS Authorized Instructor Champion / AWS認定インストラクター(AAI) / AWS 認定ソリューションアーキテクト - プロフェッショナル /AWS認定DevOpsエンジニア - プロフェッショナル / AWS 認定デベロッパー - アソシエイト / AWS 認定 SysOps アドミニストレーター - アソシエイト / AWS 認定クラウドプラクティショナー / kintone認定 カスタマイズスペシャリスト他。著書に「AWS認定試験対策 AWS クラウドプラクティショナー」がある。前職では2016年にAWS Summitにパネラーとして参加。その前はLotus Technical Award 2009 for Best Architectとして表彰されている。現在はAWS認定インストラクターとして活躍。また、各コミュニティの運営にも個人的に関わり、勉強会にてスピーカーや参加をしている。

   

AWS認定資格サンプル問題に挑戦

AWS に関する記事

全51件中 1〜 5件を表示

人気記事

人材育成専門企業トレノケート【公式ブログ】
© Trainocate Japan, Ltd. All Right Reserved. 2008-2018