LoginSignup
11
10

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-10-25

本記事について

  • 会社の同僚向けに、業務外にて実施をした「AWS ハンズオン」の資料を、一般公開したものです。
  • サーバレスアーキテクチャを用いて、有名人の画像解析 API サービスを、約1時間で作成するという内容になっています。
  • 言語は Python を用いますが、基礎知識が無くても楽しめる構成にしています。
  • ハンズオンの実施にあたっては、以下のリソースが必要です。
    • インターネットに接続できるPC( Windows, Mac 問わない)
    • AWS IAM ユーザーアカウント
  • 本資料の作成には細心の注意を払っておりますが、その正確性を担保するものではありません。また、本資料が起因して生じた損害について、作成者は一切の責任を負いません。

追記:スライド版を公開

はじめに(概要説明)

つくるもの

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

動作イメージ

  • 例えば、日本が世界に誇る有名俳優「渡辺謙」さんの写真を用意し、今回作成するAIに読み込ませてみます。
    • ※ 以下のスクリーンショットでは、知財権保護のため画像をぼかしています。
  • 「ファイルを選択」ボタンから「渡辺謙」さんの画像を選択します。 image.png
  • ファイルを選択後、「送信」ボタンを押すと…
  • “He/She is Ken Watanabe with 100% confidence.” と表示されます。
  • 今回のハンズオンでは、このサービスのバックエンドを作成していきます。 image.png

アーキテクチャ説明

  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マネジメントコンソールへアクセスし、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

  • 今から動くコードを記述していきます。

  • 「関数コード」のところまで下にスクロールします。ここがロジックを記述するエディタとなります。
    image.png

Lambda 関数の使い方説明

  • まずは、シンプルなPythonコードを書いて Lambda の動きを学習しましょう。
    image.png

  • 例えば、文字列を結合して出力する、以下のコードを記述します。

    • 変数に文字列を設定し、結合をしたものを return する内容となっています。
    • 具体的には、’Pen’ + ’Pineapple’ + ’Apple’ + ’Pen’ → ‘PenPineappleApplePen’ になります。
lambda_function.py
def lambda_handler(event, context):
    a = 'Pen'
    b = 'Pineapple'
    c = 'Apple'
    x = a + b + c + a
    return {
        'statusCode': 200,
        'body': x
    }
  • 記述後、「Deploy」 ボタンを押したのち、右上の「テスト」を押下します。
    image.png

  • 「テストイベントの設定」画面が表示されます。以下の設定をした後、「作成」ボタンを押下します。

    • 「新しいテストイベントの作成」を選択します。
    • イベント名に「SimpleEvent」と入力します image.png
  • 右上の「テスト」を押下します。

    • 先ほど作成したテストイベントで、テストが実行されます。 image.png
  • Lambda がテスト実行されました。

    • 画面上部に「成功」と表示が出れば、コードは正常に動いた証拠です。 image.png
  • 詳細をクリックすると、関数の実行結果が展開されます。

    • ここでは、“body” が “PenPineappleApplePen”となっており、期待した通りの output になっています。 image.png
  • Lambda 実行時の詳細なログは、"CloudWatch Logs" で確認できます。

    • 「モニタリング」→「CloudWatchのログを表示」をクリックすると、“CloudWatch Logs” のページに遷移します。 image.png
  • 「ログストリーム」画面にて「20xx/xx/xx[$LATEST]xxxxxx」を選択するとログが確認できます。デバック時にご活用ください。

    • Logger などを設定すると、ここにログが出力されるようになります。 image.png

Lambda 関数の編集

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

IAM ロール(権限)の変更

  • Lambda画面の上部で「設定」を選びます
    image.png

  • 「設定」画面の下部「基本設定」の「編集」を選択します。
    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

貼り付けるコード

lambda_function.py
import boto3
import base64
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}')

    # バイナリデータがBase64形式でエンコードされた状態で受信するため、bytes型にデコードする。
    received_body = base64.b64decode(event['body-json'])

    # AWSが付与したファイル情報を除く(bytes文字列'\r\n'の4つ目以降がアップロードしたファイルの本体情報)
    images  = received_body.split(b'\r\n',4)
    image   = images[4]

    # 取得したBlob形式の画像情報を、Rekognitionに渡して有名人の識別をする
    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を作成」を押下します。
    image.png

  • REST API の「構築」ボタンを押下します。
    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="写真ファイルを選択" />
            <input type="submit" name="アップロード"/>
        </form>
    </body>
</html>
  • 作成したIndex.html をブラウザで開きます。(ファイルを選択しブラウザ上までドラッグ&ドロップすれば開けます) image.png

動作確認

  • 例えば、日本が世界に誇るお笑い芸人(?)「世界のワタベ」で試してみましょう。

    • ※以下のスクリーンショットでは、知財権保護のため画像をぼかしています。 image.png
  • ファイルを選択し、「送信」ボタンを押すと…

  • "He/She is Ken Watabe with 100% confidence." と表示されました!

  • 有名人識別サービスの完成です! 

    • さすが「世界のワタベ」ですね。 image.png

お片付け

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

API Gateway の削除

  • API Gateway の画面から、作成した「《お名前》-api-handson」を選択します。
    image.png

  • 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 の画面に遷移します。「アクション」から「Delete log group」を選択します。
    image.png

  • 確認画面が表示されるので、「削除」ボタンを押します。
    image.png

IAM ロールの削除

  • Lambda の画面に戻り、「設定」を開きます。
    image.png

  • Lambdaの画面下部、「基本設定」の「編集」を押します。
    image.png

  • 「基本設定を編集」画面の下部まで行き、「IAMコンソールでxxxロールを表示します。」を選択します。
    image.png

  • IAMロールの画面に遷移します。画面右上「ロールの削除」を選択します。
    image.png

  • 確認画面が出るので、「はい、削除します」を押下します。
    image.png

Lambda 関数の削除

  • Lambda の画面に戻り、画面上部「アクション」から「関数の削除」を選択します。
    image.png

  • 確認画面が表示されるので、「削除」を選択します。
    image.png

  • 「正常に削除されました。」と表示がでます。
    image.png

  • お片付けは以上で終了です。お疲れ様でした。

補足事項

料金

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

参考資料・ドキュメント

11
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10