本記事について
- 会社の同僚向けに、業務外にて実施をした「AWS ハンズオン」の資料を、一般公開したものです。
- サーバレスアーキテクチャを用いて、有名人の画像解析 API サービスを、約1時間で作成するという内容になっています。
- 言語は Python を用いますが、基礎知識が無くても楽しめる構成にしています。
- ハンズオンの実施にあたっては、以下のリソースが必要です。
- インターネットに接続できるPC( Windows, Mac 問わない)
- AWS IAM ユーザーアカウント
- 本資料の作成には細心の注意を払っておりますが、その正確性を担保するものではありません。また、本資料が起因して生じた損害について、作成者は一切の責任を負いません。
追記:スライド版を公開
- Speaker Deck にて、本ハンズオンのスライド版資料を公開しています。
- スライド版の方が、デザインが整っていて見やすいかと思います。
- 対して、Qiitaの本記事の方には、ソースコードをコピペできるメリットがあります。
- スライド版、Qiita版、両方を併用して実施されると良いと思います。
- https://speakerdeck.com/hayate_h/awshanzuon-sabaresuakitekutiyade-you-ming-ren-shi-bie-sabisuwozuo-rou
-
はじめに(概要説明)
つくるもの
- Amazon Rekognition(画像解析AI) を用いて、有名人識別APIを作成します。
- システム構成図は以下のようになります。
動作イメージ
- 例えば、日本が世界に誇る有名俳優「渡辺謙」さんの写真を用意し、今回作成するAIに読み込ませてみます。
- ※ 以下のスクリーンショットでは、知財権保護のため画像をぼかしています。
- 「ファイルを選択」ボタンから「渡辺謙」さんの画像を選択します。
- ファイルを選択後、「送信」ボタンを押すと…
-
“He/She is Ken Watanabe with 100% confidence.”
と表示されます。 -
今回のハンズオンでは、このサービスのバックエンドを作成していきます。
アーキテクチャ説明
- クライアントPCから API Gateway 経由で有名人の画像をアップロードします。
- 画像ファイルを受信すると、Lambda 関数が起動します。
- Lambda 関数内で Amazon Rekognition の recognize_celebrities 機能に画像ファイルを送り、画像内の有名人を識別します。
- 取得した有名人の情報を出力用に整形して、API Gateway を通して返します。
- 呼び出し元のブラウザ上で、識別結果が表示されます。
AWS サービスについて
使用する AWS サービスの紹介
AWS 用語解説:「サーバレス」とは
- 利用者がサーバを意識する必要のないサービスやアーキテクチャのことです。
- 注意:サーバが全く存在しないわけではありません。サーバはAWSが管理しています。
- プログラムコードを「置くだけ」で動作します。そのため運用管理が楽になります。
AWS 用語解説:「マネージドサービス」とは
- AWSが運用管理(の一部)を担ってくれるサービスのことです。
- 担ってくれる運用管理の内容や範囲はサービスによって多様ですが、「バックアップを定期的にとる」などだけではなく、「アクセスが増えたら自動でスケールする」なども提供していることが多いです。
- 運用管理の範囲が広く、利用者の手間がほとんどかからない場合は、「フルマネージドサービス」と言われることが多いです。
- 「マネージド」であっても、常に「サーバレス」とは限りません。
開発手順
サインイン
-
AWSマネジメントコンソールへアクセスし、IAM ユーザー情報でサインインをしてください。
-
サインイン補足情報
- 今回のハンズオンでは、ハンズオンを実施するIAMユーザーに**”AdministratorAccess”のIAMポリシーが付与されていることを前提**にして進めています。
- “AdministratorAccess” の権限が付与されていなかった場合、以下の手順の中でリソースが作れない等のエラーが発生する可能性があります。
- その場合は、適切なポリシーをアタッチした上で再度実行をしてください。
- なお、以下のサイトに記載されていたIAMの設定内容は大変参考になりました。
- ハンズオンの手順が全て実行できることを確認済みです。
- 社外の開発メンバーをAWSアカウントに入れるときのIAM設定を考えている - kmiya_bbmのブログ
リージョンと言語の確認
[補足] リージョンの変更方法
[補足] 言語の変更方法
Lambda 関数の作成
Lambda 関数の新規作成
-
関数の作成画面にて、以下を選択、入力していきます。
- 「一から作成」を選択
- 「関数名」に「《お名前》-rekognition-handson」と入力
- 例:higuchi-rekognition-handson
- 「ランタイム」に「Python3.8」を選択
- 「アクセス権限」-「デフォルトの実行ロールの変更」 を開き、「基本的なLambdaアクセス権限で新しいロールを作成」を選択
-
今から動くコードを記述していきます。
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
}
-
「テストイベントの設定」画面が表示されます。以下の設定をした後、「作成」ボタンを押下します。
-
右上の「テスト」を押下します。
-
Lambda がテスト実行されました。
-
詳細をクリックすると、関数の実行結果が展開されます。
-
Lambda 実行時の詳細なログは、"CloudWatch Logs" で確認できます。
-
「ログストリーム」画面にて「20xx/xx/xx[$LATEST]xxxxxx」を選択するとログが確認できます。デバック時にご活用ください。
Lambda 関数の編集
- ここから、Lambda関数を、画像解析AI (Rekognition)と紐づける作業をしていきます。
- Lambda関数から、Rekognitionを呼び出すには、適切な権限が必要です。
- 具体的には、Lambdaに付与されているIAMロールに、Rekognitionへのアクセスを許可するIAMポリシーをアタッチする必要があります。
-
まずは、権限付与から行っていきましょう。
IAM ロール(権限)の変更
-
別タブで、IAMロールの画面が開きます。
-
検索窓に「Rekognition」と入力し、「AmazonRekognitionReadOnlyAccess」ポリシーにチェックを入れて、「ポリシーのアタッチ」ボタンを押下します。
-
IAMのコンソール画面で、「AmazonRekognitionReadOnlyAccess」がアタッチされていることを確認します。
-
Lambda の「基本設定を編集」画面に戻ります。
- タイムアウトを「10秒」に変更します。
Lambda 関数の更新
貼り付けるコード
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."
コードの説明( #コメントに書ききれなかった部分)
- 1行目
import boto3
- AWS サービスを扱う上で必要なモジュールのインポートをしています。
- boto3はPythonでAWSリソースを操作する際に用いるSDKです。
- https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html
- 25~27行目
response = rekognition.recognize_celebrities(Image={'Bytes': image})
- rekognitionの使い方は、boto3のドキュメントに記載されています。
- https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rekognition.html#Rekognition.Client.recognize_celebrities
- 37行目
return文
- これは、実はアンチパターンの return 文です。
- 実際には、Lambdaのプロキシ統合のフォーマットに合わせたレスポンス形式にすると良いでしょう。
- 今回は、ブラウザ上での動作確認を行うため、明示的にプロキシ統合を使わず、また出力のフォーマットも意図的に無視をした記載にしています。
- 詳しくは「API Gateway 統合レスポンス」で検索してください。
- https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-integration-settings-integration-response.html
API Gateway の追加
-
「新しいAPIの作成」画面にて以下の設定を行い、「APIの作成」ボタンを押下します。
-
API は「リソース」×「メソッド」で開発をしていきます。
-
統合タイプにて「Lambda関数」を選択し、Lambda関数にて先ほど作成した「《お名前》-rekognition-handson」を選択後、「保存」ボタンを押下します。
-
画面下部「マッピングテンプレート」を展開し、「リクエスト本文のパススルー」の項目で「テンプレートが定義されていない場合(推奨)」を選択します。
-
画面下部にテンプレートの生成画面が追加されます。
-
画面左「設定」を選択し、「設定」画面の下部「バイナリメディアタイプ」の項目にて「バイナリメディアタイプの追加」を押下します。
-
APIのデプロイ画面にて、以下の設定をし、「デプロイ」ボタンを押下します。
-
画面左ペインから、「ステージ」を選択し、「dev」-「rekognition」-「POST」を選択します。
HTML ファイルの作成
- 以下のHTMLの
****API Gateway URL 貼り付け****
の部分に、先ほど作成した API Gateway の URL を貼り付け、"index.html"のファイル名で保存します。- フォームを用いて、選択されたファイルを送信するだけの、単純な 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>
動作確認
-
例えば、日本が世界に誇るお笑い芸人(?)「世界のワタベ」で試してみましょう。
-
ファイルを選択し、「送信」ボタンを押すと…
-
"He/She is Ken Watabe with 100% confidence."
と表示されました! -
有名人識別サービスの完成です!
お片付け
API Gateway の削除
CloudWatch ログの削除
IAM ロールの削除
Lambda 関数の削除
-
お片付けは以上で終了です。お疲れ様でした。
補足事項
料金
- 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万枚 |