【AWSハンズオン】サーバレスアーキテクチャで、有名人識別サービスを作ろう!

こんにちは。SCSK 産業事業グループの樋口です。

本ハンズオンでは、有名人の画像をアップロードすると名前をレスポンスしてくれる、簡単な API サービスを AWS上にて構築します。
本ハンズオンを通して、AWSのサーバレスアーキテクチャについての理解が深まれば幸いです。

本記事で作成するもの:有名人識別サービス

  1. 「ファイルを選択」ボタンから、有名人の画像(例えば、日本が世界に誇る有名俳優「渡辺謙」さんの画像)を選択します。
  2. ファイルを選択後、「送信」ボタンを押すと…
  3. “He/She is Ken Watanabe with 100% confidence.” と表示されます! 
  • 所要時間は、約1時間です。
  • プログラミング言語は Python を使用していますが、基礎知識が無くても楽しめる構成にしています。
  • ハンズオンの実施にあたっては、以下のリソースが必要です。
    • インターネットに接続できるPC( Windows, Mac 問わない)
    • AWS IAM ユーザーアカウント
本資料の作成には細心の注意を払っておりますが、その正確性を担保するものではありません。
また、本資料が起因して生じた損害について、作成者は一切の責任を負いません。

はじめに

概要説明

  • Amazon Rekognition(画像解析AI) を用いて、有名人識別APIを作成します。
  • システム構成図は以下のようになります。
    • 明示的なサーバが存在しない「サーバレスアーキテクチャ」のため構築が簡単です。
    • また運用管理の手間やコストも軽減します。 

APIの動作説明

  1. クライアントPCから API Gateway 経由で有名人の画像をアップロードします。
  2. 画像ファイルを受信すると、Lambda 関数が起動します。
  3. Lambda 関数内で Amazon Rekognition の recognize_celebrities 機能に画像ファイルを送り、画像内の有名人を検出します。
  4. 検出した有名人の情報を出力用に整形して、API Gateway を通して返します。
  5. 呼び出し元のブラウザ上で、識別結果が表示されます。 image.png

AWS サービスについて

使用する AWS サービスの紹介

  • 今回使用する3つのサービスを簡単に紹介します。
  • 「習うより慣れよ」の考えで、ハンズオンを進めていきましょう。 image.png

AWS 用語解説:「サーバレス」とは

  • 利用者がサーバを意識する必要のないサービスやアーキテクチャのことです。
    • 注意:サーバが全く存在しないわけではありません。サーバはAWSが管理しています。
  • プログラムコードを「置くだけ」で動作します。そのため運用管理が楽になります。 image.png

AWS 用語解説:「マネージドサービス」とは

  • AWSが運用管理(の一部)を担ってくれるサービスのことです。
  • 担ってくれる運用管理の内容や範囲はサービスによって多様ですが、「バックアップを定期的にとる」などだけではなく、「アクセスが増えたら自動でスケールする」なども提供していることが多いです。
  • 運用管理の範囲が広く、利用者の手間がほとんどかからない場合は、「フルマネージドサービス」と言われることが多いです。
  • 「マネージド」であっても、常に「サーバレス」とは限りません。 image.png

開発手順

AWSへのサインイン

  • AWSマネジメントコンソールへアクセスし、IAM ユーザー情報でサインインをしてください。
https://console.aws.amazon.com/
  • image.png
  • サインインの補足情報
    • 今回のハンズオンでは、ハンズオンを実施するIAMユーザーに”AdministratorAccess”のIAMポリシーが付与されていることを前提にして進めています。“AdministratorAccess” の権限が付与されていなかった場合、以下の手順の中でリソースが作れない等のエラーが発生する可能性があります。
    • その場合は、適切なポリシーをアタッチした上で再度実行をしてください。
    • なお、以下のサイトに記載されていたIAMの設定内容は大変参考になりました。

リージョンと言語の確認

  • 画面右上が「東京(リージョン)」 画面左下が「日本語」になっていることを確認します。image.png

[補足] リージョンの変更方法

  • 画面右上の地名を押下し、「アジアパシフィック(東京)ap-northeast-1」を選択します。 image.png

[補足] 言語の変更方法

  • 画面左下の言語を押下し、「日本語」を選択します。 image.png

Lambda 関数の作成

Lambda 関数の新規作成

  • 最初にLambda 関数を作成し、基本的な使い方を学習しましょう。
    image.png
  • マネジメントコンソールの画面にて、検索窓に「Lambda」と入力し、表示された「Lambda」を選択してください。
    image.png
  • Lambdaの画面が開きましたら、「関数の作成」ボタンを押してください。
    image.png
  • 関数の作成画面にて、以下を選択・入力し、最後に画面右下の「関数の作成」ボタンを押下します。
    • 「一から作成」を選択
    • 「関数名」に「《お名前》-rekognition-handson」と入力 (例:higuchi-rekognition-handson)
    • 「ランタイム」に「Python3.8」を選択
    • 「アクセス権限」-「デフォルトの実行ロールの変更」 を開き、「基本的なLambdaアクセス権限で新しいロールを作成」を選択 image.png
  • Lambda関数が作成されます。
    image.png
  • 今から動くコードを記述していきます。
  • 下にスクロールし、「コード」のタブを表示します。
  • lambda_function.py をダブルクリックし、エディタを開きます。
    image.png

Lambda 関数の使い方説明

  • まずは、シンプルなPythonコードを書いて Lambda の動きを学習しましょう。
  • 例えば、文字列を結合して出力する、以下のコードを記述します。
    • 変数に文字列を設定し、結合をしたものを return する内容となっています。
    • 具体的には、’Pen’ + ’Pineapple’ + ’Apple’ + ’Pen’ → ‘PenPineappleApplePen’ になります。
def lambda_handler(event, context):
    a = 'Pen'
    b = 'Pineapple'
    c = 'Apple'
    x = a + b + c + a
    return {
        'statusCode': 200,
        'body': x
    }
  • 入力後、「Deploy」 ボタンを押します。
    image.png
  • Deploy が完了した後、上部の「Test」を押下します。
    image.png
  • 「テストイベントの設定」画面が表示されます。以下の設定をした後、「作成」ボタンを押下します。
    • 「新しいテストイベントの作成」を選択します。
    • イベントテンプレートは「hello-world」を選択します。
    • イベント名に「SimpleEvent」と入力します。 image.png
  • 再度「Test」ボタンを押下します。
    • 先ほど作成したテストイベントで、Lambda 関数がテスト実行されます。 image.png
  • Lambda 関数がテスト実行されました。
    • 画面に{"statuscCode":200, "body": "PenPineappleApplePen"}と表示が出れば、コードは正常に動いた証拠です。 image.png

デバッグ方法(ログの確認方法)

  • Lambda 実行時の詳細なログは、”CloudWatch Logs” で確認できます。
    • 「モニタリング」タブ ->「CloudWatchのログを表示」ボタンをクリックすると、“CloudWatch Logs” のページに遷移します。 image.png
  • 「ログストリーム」画面にて「20xx/xx/xx[$LATEST]xxxxxx」を選択するとログが確認できます。デバック時にご活用ください。
    image.png
  • Logger などを設定すると、ここにログが出力されるようになります。
    image.png

Lambda 関数の編集

  • ここから、Lambda関数を、画像解析AI (Rekognition)と紐づける作業をしていきます。
  • Lambda関数からRekognitionを呼び出すには、適切な権限が必要です。
  • 具体的には、Lambdaに付与されているIAMロールに、Rekognitionへのアクセスを許可するIAMポリシーをアタッチする必要があります。
  • まずは、権限付与から行っていきましょう。 image.png

IAM ロール(権限)の変更

  • Lambda画面で「設定」タブ -> 「一般設定」項目 -> 「編集」を選択します。
    image.png
  • 「基本設定を編集」画面の下部まで行き、「IAMコンソールでxxxロールを表示します。」をクリックします。
    image.png
  • 別タブで、IAMロールの画面が開きます。
  • 「ポリシーをアタッチします」ボタンを押下します。
    image.png
  • 検索窓に「Rekognition」と入力し、「AmazonRekognitionReadOnlyAccess」ポリシーにチェックを入れて、「ポリシーのアタッチ」ボタンを押下します。
    image.png
  • IAMのコンソール画面で、「AmazonRekognitionReadOnlyAccess」がアタッチされていることを確認します。
  • これで、Lambda に Rekognition を呼び出せる権限を付与できました。
    image.png
  • Lambda の「基本設定を編集」画面に戻ります。
    • タイムアウトを「10秒」に変更します。
  • 上記設定後、「保存」ボタンを押下します。image.png

Lambda 関数の更新

  • Lambda 関数を、有名人識別のソースコードに書き換えます。
  • 「関数コード」を以下の内容で上書きし、「Deploy」ボタンを押下します。 image.png
貼り付けるソースコード
import boto3
import base64
import io
import cgi
import logging
import traceback


# logger設定
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# rekognition インスタンスの作成
rekognition = boto3.client('rekognition')

# lambda_handler 関数の定義(メインロジック)
def lambda_handler(event, context):
    logger.info(f'Received event = {event}')

    # HTMLフォームからアップロードされた部分はBase64形式でエンコードされた状態で受信するため、bytes型にデコードする(正確にはbytes-like object)
    received_body = base64.b64decode(event['body-json'])
    # cgi.FieldStorageでHTMLフォームを解析できるように、BytesIO オブジェクトを生成する
    body_bytes = io.BytesIO(received_body)

    # cgi.FieldStorageクラスを用いて、フォームの内容を解析する
    environ = {'REQUEST_METHOD': 'POST'}
    headers = {'content-type': event['params']['header']['content-type']}
    form = cgi.FieldStorage(fp=body_bytes, environ=environ, headers=headers)
    # 画像ファイルをbytes型で取得('uploadfile'は送信時に設定した当該ファイルのnameの値)
    image = form.getvalue('uploadfile')

    # 取得した画像ファイルを、Rekognitionのrecognize_celebritiesメソッドに渡して有名人の検出をする
    response = rekognition.recognize_celebrities(
        Image={'Bytes': image}
    )
    logger.info(f'Rekognition response = {response}')

    try:
        # Rekognition のレスポンスから有名人の名前と信頼度を取り出し、APIのコール元へレスポンスする
        label   = response['CelebrityFaces'][0]
        name    = label['Name']
        conf    = round(label['Face']['Confidence'])
        output  = f'He/She is {name} with {conf}% confidence.'
        logger.info(f'API response = {output}')
        return output

    except IndexError as e:
        # Rekognition のレスポンスから有名人情報を取得出来なかった場合、他の写真にするように伝える。
        logger.info(f"Coudn't detect celebrities in the Photo. Exception = {e}")
        logger.info(traceback.format_exc())
        return "Couldn't detect celebrities in the uploaded photo. Please upload another photo."

コードの説明( #コメントに書ききれなかった部分)

API Gateway の追加

  • ここから、API Gateway と Lambda を紐づけていきます。
    image.png
  • 画面上部「サービス」から検索窓に”API”と入力し、候補にあがる「API Gateway」 を選択します。
    image.png
  • API Gateway の画面に遷移します。
    image.png
  • 画面下部の REST API の「構築」ボタンを押下します。
    image.png
  • 確認画面が表示された際は、「OK」ボタンを押下します。
    image.png
  • 「新しいAPIの作成」画面にて以下の設定を行い、最後に画面右下の「APIの作成」ボタンを押下します。
    • 「新しいAPI」を選択
    • API名:「《お名前》-api-handson」と入力(例:higuchi-api-handson)
    • エンドポイントタイプ:「リージョン」を選択 image.png
  • API は「リソース」×「メソッド」で開発をしていきます。
    • 例えば「/users に GET」や「/users/12345 にPOST」などです。 image.png
  • まず、リソースを作成します。「アクション」から「リソースの作成」を選択します。
    image.png
  • リソース名に「Rekognition」と入力し「リソースの作成」ボタンを押下します。
    image.png
  • 次にメソッドの作成をします。リソースを選択した上で、「アクション」->「メソッドの作成」を選択します。
    image.png
  • プルダウンから「POST」を選んで、「チェックボタン」を押下します。
    image.png
  • 統合タイプにて「Lambda関数」を選択し、Lambda関数にて先ほど作成した「《お名前》-rekognition-handson」を選択後、「保存」ボタンを押下します。
    image.png
  • 「Lambda 関数に権限を追加する」の確認画面が表示されるので、「OK」ボタンを押下します。
    image.png
  • 「統合リクエスト」を選択します。
    image.png
  • 画面下部「マッピングテンプレート」を展開し、「リクエスト本文のパススルー」の項目で「テンプレートが定義されていない場合(推奨)」を選択します。
  • 「Content-Type」の項目にて、「マッピングテンプレートの追加」を押下します。
    image.png
  • 「Content-Type」の項目にて、multipart/form-data と入力し、チェックボタンを押します。
    image.png
  • 画面下部にテンプレートの生成画面が追加されます。
  • テンプレートの生成のプルダウンにて、「メソッドリクエストのパススルー」を選択し「保存」ボタンを押します。
    image.png
  • 画面左「設定」を選択し、「設定」画面の下部「バイナリメディアタイプ」の項目にて「バイナリメディアタイプの追加」を押下します。
    image.png
  • multipart/form-data と入力し、「変更の保存」ボタンを押下します。
    image.png
  • 画面左ペイン「リソース」を選択後、画面上部「アクション」より「APIのデプロイ」を選択します。
    image.png
  • APIのデプロイ画面にて、以下の設定をし、「デプロイ」ボタンを押下します。
    • デプロイされるステージ:「新しいステージ」を選択
    • ステージ名:「dev」を入力 image.png
  • 画面左ペインから、「ステージ」を選択し、「dev」-「rekognition」-「POST」を選択します。
  • 画面右に、「URLの呼び出し」として作成された API の URL が表示されるので、これをコピーします。
    image.png

HTML ファイルの作成

  • 以下のHTMLの****API Gateway URL 貼り付け****の部分に、先ほど作成した API Gateway の URL を貼り付け、”index.html”のファイル名でパソコン上に保存します。
    • フォームを用いて、選択されたファイルを送信するだけの、単純な HTML ファイルです。
index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>有名人認識AIハンズオン</title>
    </head>
    <body>
        <p>画像識別AIである Amazon Rekognition を用いて、有名人の認識をします!</p>
        <form action="****API Gateway URL 貼り付け****" enctype="multipart/form-data" method="POST">
            <input type="file" name="uploadfile" />
            <input type="submit"/>
        </form>
    </body>
</html>
  • 作成したIndex.html をブラウザで開きます。(ファイルを選択しブラウザ上までドラッグ&ドロップすれば開けます) image.png

動作確認

  • 例えば、日本が世界に誇るお笑い芸人(?)「世界のワタベ」で試してみましょう。
    • ※以下のスクリーンショットでは、知財権保護のため画像をぼかしています。 image.png
  • ファイルを選択し、「送信」ボタンを押すと…
  • "He/She is Ken Watabe with 100% confidence." と表示されました!
  • 有名人識別サービスの完成です!
    • さすが「世界のワタベ」ですね。 image.png
正常に動作しない場合は、「デバッグ方法(ログの確認方法)」のセクションに記載をした、CloudWatch logs を確認することで、問題個所が分かると思います。

お片付け

  • 以下のリソースを削除していきます。
    • API Gateway
    • Lambda
    • CloudWatch ロググループ(Lambdaの実行ログ)
    • Lambda用 IAMロール image.png

API Gateway の削除

  • API Gateway の画面から、作成した「《お名前》-api-handson」を選択します。
    image.png
  • 画面左ペインで「リソース」が選択されている状態で、アクションから「APIの削除」を選択します。
    image.png
  • 削除前の確認画面が表示されるので、API名を入力後、「APIの削除」を押下します。
    image.png

CloudWatch ログの削除

  • Lambda のコンソール画面へ遷移するために、画面上部の「サービス」から「Lambda」を検索し選択します。
    image.png
  • 一覧画面にて、「《お名前》-rekognition-handson」を選択します。
    image.png
  • 画面上部「モニタリング」を選択し、「CloudWatchのログを表示」ボタンを押下します。
    image.png
  • CloudWatch Logs の画面に遷移します。「アクション」から「ロググループの削除」を選択します。
    image.png
  • 確認画面が表示されるので、「削除」ボタンを押します。
    image.png

IAM ロールの削除

  • Lambda の画面に戻り、「設定」タブ ->「一般設定」項目 -> 「編集」ボタンを選択します。
    image.png
  • 「基本設定を編集」画面の下部まで行き、「IAMコンソールでxxxロールを表示します。」を選択します。
    image.png
  • IAMロールの画面に遷移します。画面右上「ロールの削除」を選択します。
    image.png
  • 確認画面が出るので、「はい、削除します」を押下します。
    image.png

Lambda 関数の削除

  • Lambda の画面に戻り、画面上部「アクション」から「関数の削除」を選択します。
    image.png
  • 確認画面が表示されるので、「削除」を選択します。
    image.png
  • 「正常に削除されました。」と表示がでます。
    image.png
  • お片付けは以上で終了です。お疲れ様でした。

補足事項

料金

  • AWSの各種サービスには、一定の無料利用枠があります。
  • 今回の構成は、APIを大量にコールしない限り、全てAWSの無料利用枠に収まる想定です。
  • 参考までに、無料枠を超えた際に発生する料金の目安を記載しておきます。
    • (2021年7月27日時点 東京リージョン 月単位)
サービス分類 区分 料金 補足
データ通信料 AWSへのイン 0.000USD/GB  
AWSからのアウト 0.114USD/GB 最初の1GB~10TB
CloudWatch ログ収集 0.760USD/GB  
ログ保存 0.033USD/GB  
Lambda リクエスト課金 0.20USD/100万件  
実行時間課金 0.0000000021USD
/128MB,1ミリ秒
 
API Gateway REST API 4.25USD/100万件 最初の3億3,300万コール受信数
Rekognition Image 0.0013USD/1画像 最初の100万枚

参考資料・ドキュメント

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