顔を採点するLINE BOTをLambdaで作ってみた

スポンサーリンク
顔を採点するLINE BOTを作ってみたAIを作ってみる

LINEに画像を送ると顔の美しさを採点して返信するアプリを作ってみました。

 

顔を採点するLINE_BOT

 

アプリの構成

今回は、AWSを使ってサーバレスのアーキテクチャで構築しました。

顔を採点するLINE BOTのアーキテクチャ

 

利用しているサービスは以下の3つです。

  • Line Developers : Lineのメッセージの送受信を実施
  • API Gateway : REST APIの受け口を作成
  • Lambda : 顔採点処理の実行

 

アプリ(Lambda)のソースコード

Lambdaでは画像を受け取り、受け取った画像を顔採点用のAPIに投げてその結果を受け取っています。

顔採点用のAPIはface++を使用していて、詳細はこちらの記事で紹介しています。

【Face++】AIで日本の美女の顔を採点してみた
以下環境で動作確認を行いました。 動作環境 Ubuntu18.04 Python 3.6.9 AI(Face++のDetect API)を使って日本人の美女の美しさを推論してみまし...

 

今回実装したLambdaのコードです。

from linebot.exceptions import LineBotApiError
from linebot.models import TextSendMessage, MessageEvent, TextMessage, ImageMessage
from linebot import LineBotApi, WebhookHandler
import requests
import json
import os
import logging
import boto3
import base64
from PIL import Image, ImageDraw

logger = logging.getLogger()
logger.setLevel(logging.INFO)

CHANNEL_ACCESS_TOKEN = os.environ["ChannelAccessToken"]
CHANNEL_SECRET = os.environ["ChannelSecret"]
LINE_HANDLER = WebhookHandler(CHANNEL_SECRET)
LINE_BOT_API = LineBotApi(CHANNEL_ACCESS_TOKEN)


def lambda_handler(event, context):
    logger.info(event)
    signature = event["headers"]["x-line-signature"]
    body = event["body"]

    # 画像メッセージの場合
    @LINE_HANDLER.add(MessageEvent, message=ImageMessage)
    def on_image_message(line_event):
        image_file_path = "/tmp/file.png"
        image = LINE_BOT_API.get_message_content(line_event.message.id)

        with open(image_file_path, "wb") as f:
            for chunk in image.iter_content():
                f.write(chunk)
                
        face_score = face_scoring(image_file_path)

        LINE_BOT_API.reply_message(line_event.reply_token, TextSendMessage(f"{face_score}です"))

    LINE_HANDLER.handle(body, signature)

    return {
        "statusCode": 200,
        "body": json.dumps(
            {
                "message": "line API complate",
            }
        ),
    }


def face_scoring(file_path):
    # 画像ファイルをbase64バイナリ形式で読み出します
    with open(file_path, 'rb') as f:
        img_file = base64.encodebytes(f.read())

    # パラメータ設定
    # API
    face_api_key = os.environ["FaceApiKey"]
    face_api_secret = os.environ["FaceApiSecret"]

    # 顔判定
    response = requests.post(
        'https://api-us.faceplusplus.com/facepp/v3/detect',
        {
            'api_key': face_api_key,
            'api_secret': face_api_secret,
            'image_base64': img_file,  # 画像のURL
            'return_attributes': 'gender,beauty'  # 取得したい属性
        }
    )

    json_dict = json.loads(response.text)
    result_dict = {}
    for faces in json_dict["faces"]:
        try:
            gender = faces["attributes"]["gender"]["value"] 
            if gender == "Female":
                text = str(faces["attributes"]["beauty"]["female_score"])
            else:
                text = str(faces["attributes"]["beauty"]["male_score"])
            
            result_dict[f"{faces['face_rectangle']['left']:05}"] = text

        except:
            pass  # 5人以上はレスポンスが帰ってこない
    
    if len(result_dict) == 1:
        key = next(iter(result_dict))
        result_text = f"{result_dict[key]}点"
    else:
        result_dict = sorted(result_dict.items()) # 左の人からになるようにソート
        result_text = "左から順に\n"
        for i_score in result_dict:
            result_text += f"{i_score[1]}点\n"
    return result_text

 

Lambda・API Gatewayの作成

AWSの環境はSAM(AWS Serverless Application Model )を使って構築しました。

├ line-face-scoring/ 
   ├ app/ # lambdaのソース用のディレクトリ
   │  ├ app.py # lambdaのソース
   │  ├ Dockerfile # lambdaのDocker環境
   │  ├ __init__.py
   │  ├ requirements.txt # lambdaで利用するライブラリ
   ├ __init__.py
   ├ samconfig.toml # samコマンドの設定
   ├ template.yaml # AWSのリソースの設定

 

リソースはそれぞれ以下の設定ファイルをもとに作成しています。

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  python3.8
  Sample SAM Template for line-face-scoring

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 30
  Api:
    OpenApiVersion: 3.0.2 #samのバグを回避(不要なステージが作成される)

Parameters:
  Env:
    Type: String
    AllowedValues:
      - dev
      - prod
    Default: prod
  ChannelAccessToken:
    Type: String
  ChannelSecret:
    Type: String
  LineUserID:
    Type: String
  FaceApiKey:
    Type: String
  FaceApiSecret:
    Type: String

Resources:
  FaceScoringFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      FunctionName: !Sub lambda-face-scoring-Function
      PackageType: Image
      Role: !GetAtt FaceScoringFunctionRole.Arn
      Environment:
        Variables:
          ChannelAccessToken:  !Ref ChannelAccessToken
          ChannelSecret:  !Ref ChannelSecret
          LineUserID: !Ref LineUserID
          FaceApiKey: !Ref FaceApiKey
          FaceApiSecret: !Ref FaceApiSecret

      Events:
        LineAPI:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /facescoring/v1
            Method: post
            RestApiId:
              Ref: FaceScoringAPIateway
      ImageUri: !Sub ${Env}-face-scoring:python3.8-v1
    Metadata:
      Dockerfile: Dockerfile
      DockerContext: ./face_scoring
      DockerTag: python3.8-v1
  
  FaceScoringAPIateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Sub ${Env}
  
  FaceScoringFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      RoleName: !Sub lambda-line-face-scoring

 

samconfig.toml
version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "face-scoring"

image_repository = "xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/line-api-ecr"

region = "ap-northeast-1"
confirm_changeset = false
capabilities = "CAPABILITY_NAMED_IAM"
parameter_overrides = [
    "Env=prod",
    "ChannelAccessToken=dummy",
    "ChannelSecret=dummy",
    "LineUserID=dummy",
    "FaceApiKey=dummy",
    "FaceApiSecret=dummy"
    ]

 

Dockerfile
FROM public.ecr.aws/lambda/python:3.8

COPY app.py requirements.txt ./

RUN python3.8 -m pip install -r requirements.txt -t .

# Command can be overwritten by providing a different command in the template directly.
CMD ["app.lambda_handler"]

 

requirements.txt
requests
line-bot-sdk
Pillow

 

まとめ

今回はLineAPIGatewayLambdaを使って、顔採点アプリを作成してみました。

AIサービスは無料で使えるAPIあるので、それを活用すると簡単に独自のアプリを作ることができますね。

コメント

タイトルとURLをコピーしました