PythonとAWSで始める感情分析AIをLINE Bot開発③Amazon Rekognition実装

LINE

Amazon Rekognition

https://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/faces-detect-images.html

RekognitionはAmazonが提供する画像分析サービスであり、最近ではマスクをしている人としていない人なども検知することができるようです。今までとの大きな違いはLambdaとRekoginitionとの間で発生する表情分析です。テキストではなく、画像の受け取りが出来るようにコードを書く必要があります。今回はその中でもDetectFacesというサービスを使用していきます。

boto3というAWSのWebAPIをサポートしているサービスを利用する。

mylinebot.py

import os
 
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage, ImageMessage,
)
 
import boto3
 
handler = WebhookHandler(os.getenv('LINE_CHANNEL_SECRET'))
line_bot_api = LineBotApi(os.getenv('LINE_CHANNEL_ACCESS_TOKEN'))
client = boto3.client('rekognition')
 
def lambda_handler(event, context):
    headers = event["headers"]
    body = event["body"]
    signature = headers['x-line-signature']
    handler.handle(body, signature)
    return {"statusCode": 200, "body": "OK"}
 
@handler.add(MessageEvent, message=TextMessage)
def handle_text_message(event):
    """ TextMessage handler """
    input_text = event.message.text
 
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=input_text))

@handler.add(MessageEvent, message=ImageMessage)
def handle_image_message(event):
    message_content = line_bot_api.get_message_content(event.message.id)
    file_path = "/tmp/sent-image.jpg"
    with open(file_path, 'wb') as fd:
        for chunk in message_content.iter_content():
            fd.write(chunk)
    with open(file_path, 'rb') as fd:
        sent_image_binary = fd.read()
        response = client.detect_faces(Image={'Bytes': sent_image_binary},
                                       Attributes=["ALL"])
        if all_happy(response):
            message = "いい笑顔ですね!!"
        else:
            message = "ぼちぼちですね"
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text = message))
    os.remove(file_path)


def all_happy(result):
    """検出した顔が全てhappyなら、tureを返す"""
    for detail in result["FaceDetails"]:
        if most_confident_emotion(detail["Emotions"]) != "HAPPY":
            return False
    return True

def most_confident_emotion(emotions):
    max_conf = 0
    result = ""
    for e in emotions:
        if max_conf < e["Confidence"]:
           max_conf = e["Confidence"]
           result = e["Type"]
    return result
template.json

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Transform": "AWS::Serverless-2016-10-31",
  "Parameters": {
    "LineChannelAccessToken": {"Type": "String", "Description": "LINE のアクセストークン"},
    "LineChannelSecret": {"Type": "String", "Description": "LINE のチャンネルシークレット"}
  },
  "Resources": {
    "EndPointFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Runtime": "python3.8",
        "CodeUri": "src",
        "Handler": "mylinebot.lambda_handler",
        "Environment": {"Variables": {
            "LINE_CHANNEL_ACCESS_TOKEN": {"Ref": "LineChannelAccessToken"},
            "LINE_CHANNEL_SECRET": {"Ref": "LineChannelSecret"}
        }},
        "Policies": [{"RekognitionDetectOnlyPolicy":{}}],
        "Events": {
          "API": {
            "Type": "Api",
            "Properties": {"Path": "/api_endpoint", "Method": "post"}
          }
        }
      }
    }
  },
  "Outputs": {
    "ApiEndpointURL": {
      "Description": "API Endpoint URL",
      "Value": {"Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/${ServerlessRestApi.Stage}/api_endpoint"}
    }
  }
}
requirement.txt

line-bot-sdk
boto3

このように画像を受け取り、笑顔と判断してコメントを返すことが出来るようになりました。^^

kazuhiro

旅行が趣味で、国内外さまざまな場所を訪れています。外資系企業で働きながら、副業として不動産投資も行っています。 https://vdhqm2p0.autosns.app/line

特集記事

コメント

この記事へのコメントはありません。

TOP
CLOSE