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

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

# 追記：スライド版を公開
- Speaker Deck にて、**本ハンズオンのスライド版資料を公開**しています。
    - スライド版の方が、デザインが整っていて見やすいかと思います。
    - 対して、Qiitaの本記事の方には、ソースコードをコピペできるメリットがあります。
    - スライド版、Qiita版、両方を併用して実施されると良いと思います。
    - [https://speakerdeck.com/hayate_h/awshanzuon-sabaresuakitekutiyade-you-ming-ren-shi-bie-sabisuwozuo-rou](https://speakerdeck.com/hayate_h/awshanzuon-sabaresuakitekutiyade-you-ming-ren-shi-bie-sabisuwozuo-rou)
    - 　
[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/568d5a52-87ad-950b-8114-862d0d27464f.png" width="500px">](https://speakerdeck.com/hayate_h/awshanzuon-sabaresuakitekutiyade-you-ming-ren-shi-bie-sabisuwozuo-rou)


# はじめに（概要説明）
## つくるもの
- [Amazon Rekognition（画像解析AI）](https://aws.amazon.com/jp/rekognition/?blog-cards.sort-by=item.additionalFields.createdDate&blog-cards.sort-order=desc) を用いて、有名人識別APIを作成します。
- システム構成図は以下のようになります。
    - 明示的なサーバが存在しない「サーバレスアーキテクチャ」のため構築が簡単です。
    - また運用管理の手間やコストも軽減します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/d48f5a03-e71a-92bf-2608-75d92fa983c4.png)

## 動作イメージ
- 例えば、日本が世界に誇る有名俳優「渡辺謙」さんの写真を用意し、今回作成するAIに読み込ませてみます。
    - ※ 以下のスクリーンショットでは、知財権保護のため画像をぼかしています。
- 「ファイルを選択」ボタンから「渡辺謙」さんの画像を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/8c4b7fcd-8042-182a-2b72-0a06fde80d63.png)
- ファイルを選択後、「送信」ボタンを押すと…
- `“He/She is Ken Watanabe with 100% confidence.”` と表示されます。
- **今回のハンズオンでは、このサービスのバックエンドを作成していきます。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/eee4bac3-2a79-5d31-63ea-9f4391a50475.png)

## アーキテクチャ説明
1. クライアントPCから API Gateway 経由で有名人の画像をアップロードします。
2. 画像ファイルを受信すると、Lambda 関数が起動します。
3. Lambda 関数内で Amazon Rekognition の recognize_celebrities 機能に画像ファイルを送り、画像内の有名人を識別します。
4. 取得した有名人の情報を出力用に整形して、API Gateway を通して返します。
5. 呼び出し元のブラウザ上で、識別結果が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/dbe42b3a-57c2-a90e-e16a-172490710406.png)

## AWS サービスについて

### 使用する AWS サービスの紹介
- 今回使用する３つのサービスを簡単に紹介します。
- 「習うより慣れよ」の考えで、ハンズオンを進めていきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/76f04573-c725-1230-b157-b287e730f0de.png)



### AWS 用語解説：「サーバレス」とは
- 利用者がサーバを意識する必要のないサービスやアーキテクチャのことです。
    - 注意：サーバが全く存在しないわけではありません。サーバはAWSが管理しています。
- プログラムコードを「置くだけ」で動作します。そのため運用管理が楽になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/470288bf-ae90-2c69-bd4e-4e8d575073eb.png)


### AWS 用語解説：「マネージドサービス」とは
- AWSが運用管理（の一部）を担ってくれるサービスのことです。
- 担ってくれる運用管理の内容や範囲はサービスによって多様ですが、「バックアップを定期的にとる」などだけではなく、「アクセスが増えたら自動でスケールする」なども提供していることが多いです。
- 運用管理の範囲が広く、利用者の手間がほとんどかからない場合は、「フルマネージドサービス」と言われることが多いです。
- 「マネージド」であっても、常に「サーバレス」とは限りません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/8bbe83d3-8bc6-5cb4-dd5a-6403da0f2d49.png)




# 開発手順

## サインイン
- AWSマネジメントコンソールへアクセスし、IAM ユーザー情報でサインインをしてください。
- https://console.aws.amazon.com/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/8e488a5b-b50d-426d-f065-3dac4fb0f400.png)

- **サインイン補足情報**
    - 今回のハンズオンでは、ハンズオンを実施するIAMユーザーに**”AdministratorAccess”のIAMポリシーが付与されていることを前提**にして進めています。
    - “AdministratorAccess” の権限が付与されていなかった場合、以下の手順の中でリソースが作れない等のエラーが発生する可能性があります。
    - その場合は、適切なポリシーをアタッチした上で再度実行をしてください。
    - なお、以下のサイトに記載されていたIAMの設定内容は大変参考になりました。
        - ハンズオンの手順が全て実行できることを確認済みです。
        - [社外の開発メンバーをAWSアカウントに入れるときのIAM設定を考えている - kmiya_bbmのブログ](https://kmiya-bbm.hatenablog.com/entry/2019/09/07/221740)

## リージョンと言語の確認
- 画面右上が「東京（リージョン）」　画面左下が「日本語」になっていることを確認します。
- 変更が必要な場合は、次のページを参考に切り替え作業を行ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/cf5505c7-ba53-5169-44bf-79b40bed4909.png)

### [補足] リージョンの変更方法
- 画面右上の地名を押下し、「アジアパシフィック（東京）ap-northeast-1」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/5334c7d3-ad74-4ffb-d21c-a7c3344155e7.png)

### [補足] 言語の変更方法
- 画面左下の言語を押下し、「日本語」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/8cc8fa99-23af-5ea3-eb97-e5fa5681da02.png)

## Lambda 関数の作成
### Lambda 関数の新規作成
- 最初にLambda 関数を作成し、基本的な使い方を学習しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/97f88b69-1bd7-76d7-aa15-4595e77c2f85.png)

- マネジメントコンソールの画面にて、検索窓に「Lambda」と入力し、表示された「Lambda」を選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/80f2f2c8-c167-98a0-4a4b-79fad6d0a575.png)

- Lambdaの画面が開きましたら、「関数の作成」ボタンを押してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/d50c0d4f-8dc6-08ef-34a2-e6b3fc6bae84.png)

- 関数の作成画面にて、以下を選択、入力していきます。
    - 「一から作成」を選択
    - 「関数名」に「《お名前》-rekognition-handson」と入力
        - 例：higuchi-rekognition-handson
    - 「ランタイム」に「Python3.8」を選択
    - 「アクセス権限」-「デフォルトの実行ロールの変更」 を開き、「基本的なLambdaアクセス権限で新しいロールを作成」を選択
- 上記設定が終わったら、画面右下「関数の作成」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/c74f859d-a42e-4cea-d3b9-3c3b33f9befe.png)

- Lambda関数が作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/e5fb75e0-81ca-5956-0358-80f4c511db7c.png)

- 今から動くコードを記述していきます。
- 「関数コード」のところまで下にスクロールします。ここがロジックを記述するエディタとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/900f1509-1ae9-e01d-3538-357182b44ddd.png)

### Lambda 関数の使い方説明
- まずは、シンプルなPythonコードを書いて Lambda の動きを学習しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/4c9ed274-5ac4-2866-1273-382000f41c0e.png)

- 例えば、文字列を結合して出力する、以下のコードを記述します。
    - 変数に文字列を設定し、結合をしたものを return する内容となっています。
    - 具体的には、’Pen’ + ’Pineapple’ + ’Apple’ + ’Pen’  → ‘PenPineappleApplePen’ になります。

```python: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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/cea21c08-bae9-06b0-6c02-9228928c8a0b.png)

- 「テストイベントの設定」画面が表示されます。以下の設定をした後、「作成」ボタンを押下します。
    - 「新しいテストイベントの作成」を選択します。
    - イベント名に「SimpleEvent」と入力します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/ecf492dc-9e46-b1db-e816-3b56ab01db0e.png)

- 右上の「テスト」を押下します。
    - 先ほど作成したテストイベントで、テストが実行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/8618e283-6361-95a7-d656-2ae660a77bfb.png)

- Lambda がテスト実行されました。
    - 画面上部に「成功」と表示が出れば、コードは正常に動いた証拠です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/20f70077-76ce-a75c-2faa-0ae3c4d91c14.png)

- 詳細をクリックすると、関数の実行結果が展開されます。
    - ここでは、“body” が “PenPineappleApplePen”となっており、期待した通りの output になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/6aa85fad-ec3c-34d5-2b48-9d6c3365e268.png)

- Lambda 実行時の詳細なログは、"CloudWatch Logs" で確認できます。
    - 「モニタリング」→「CloudWatchのログを表示」をクリックすると、“CloudWatch Logs” のページに遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/2c0c15d2-8a2d-adb8-c8e0-c163969a7b38.png)

- 「ログストリーム」画面にて「20xx/xx/xx[$LATEST]xxxxxx」を選択するとログが確認できます。デバック時にご活用ください。
    - Logger などを設定すると、ここにログが出力されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/3a7dfc4c-f1b2-6281-c19c-f7f5c050d0ef.png)

## Lambda 関数の編集
- ここから、**Lambda関数を、画像解析AI (Rekognition)と紐づける作業**をしていきます。
- Lambda関数から、Rekognitionを呼び出すには、適切な権限が必要です。
- 具体的には、Lambdaに付与されているIAMロールに、Rekognitionへのアクセスを許可するIAMポリシーをアタッチする必要があります。
- **まずは、権限付与から行っていきましょう。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/b1fe1426-5a48-a36e-39cc-50c0adef4df3.png)


### IAM ロール（権限）の変更
- Lambda画面の上部で「設定」を選びます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/bc55c1bb-d342-eab9-b77a-1aff980cacbb.png)


- 「設定」画面の下部「基本設定」の「編集」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/73091781-7641-578c-c812-415807e1d03b.png)

- 「基本設定を編集」画面の下部まで行き、「IAMコンソールでxxxロールを表示します。」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/c748061f-4d86-ae83-6c03-a391fdf5ac22.png)

- 別タブで、IAMロールの画面が開きます。
- 「ポリシーをアタッチします」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/4124b939-d7ee-f256-46a7-408da9294b09.png)

- 検索窓に「Rekognition」と入力し、「AmazonRekognitionReadOnlyAccess」ポリシーにチェックを入れて、「ポリシーのアタッチ」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/5bce5028-7ca2-c079-1dee-df8c19465eee.png)

- IAMのコンソール画面で、「AmazonRekognitionReadOnlyAccess」がアタッチされていることを確認します。
- これで、Lambda に Rekognition を呼び出せる権限を付与できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/4b9a53c9-f2c6-4ca5-9fb0-df0568636720.png)

- Lambda の「基本設定を編集」画面に戻ります。
    - タイムアウトを「10秒」に変更します。
- 上記設定後、「保存」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/3df3f470-a93f-5b0e-b05e-5a8c23f91093.png)

### Lambda 関数の更新
- Lambda 関数を、有名人識別のコードに書き換えます。
- 「関数コード」を以下の内容で上書きし、「Deploy」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/84c25338-ea47-b29b-f5a2-454d0fbc0397.png)

#### 貼り付けるコード

```python: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."
```

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

- 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 Gateway と Lambda を紐づけていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/20f4fdbe-4bca-93fd-d691-5fe870b364dc.png)

- 画面上部「サービス」から検索窓に"API"と入力し、候補にあがる「API Gateway」 を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/25ed78cf-66bf-3eef-f4b3-4ee2378982a8.png)

- 画面右上「APIを作成」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/d3aa8bd0-25cf-d50a-1199-ee4742ecf89f.png)

- REST API の「構築」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/001f69d7-e6ce-9162-16b4-cfb3bd6ec874.png)

- 「新しいAPIの作成」画面にて以下の設定を行い、「APIの作成」ボタンを押下します。
    - 「新しいAPI」を選択
    - API名：「《お名前》-api-handson」と入力（例：higuchi-api-handson）
    - エンドポイントタイプ：「リージョン」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/39674b76-d171-b698-f673-fbcbef627a1a.png)



- API は「リソース」×「メソッド」で開発をしていきます。
    - 例えば「/users に GET」や「/users/12345 にPOST」などです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/0e6fa798-8254-adda-f152-664992076c92.png)

- まず、リソースを作成します。「アクション」から「リソースの作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/ebc1e31c-89ab-a8f2-329d-e678ed2e0b4f.png)

- リソース名に「Rekognition」と入力し「リソースの作成」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/b9801eaf-7bd2-4eb4-3c8c-7ed55786a067.png)

- 次にメソッドの作成をします。リソースを選択した上で、「アクション」→「メソッドの作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/5e6606a2-4269-d5b1-4061-b2fa32ae90f1.png)

- プルダウンから「POST」を選んで、「チェックボタン」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/dc225d8b-63ba-ef3c-2230-e734c9d17374.png)

- 統合タイプにて「Lambda関数」を選択し、Lambda関数にて先ほど作成した「《お名前》-rekognition-handson」を選択後、「保存」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/45cce914-0192-de75-51d5-ccc514ca0eba.png)

- 「Lambda 関数に権限を追加する」の確認画面が表示されるので、「OK」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/9338b8ff-446f-243b-aaff-a0b25049ebaf.png)

- 「統合リクエスト」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/c7035242-822c-8e15-0018-2a5fb79a4c1a.png)

- 画面下部「マッピングテンプレート」を展開し、「リクエスト本文のパススルー」の項目で「テンプレートが定義されていない場合（推奨）」を選択します。
- 「Content-Type」の項目にて、「マッピングテンプレートの追加」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/e79826b6-7425-bfac-f6eb-a4389341f393.png)

- 「Content-Type」の項目にて、`multipart/form-data` と入力し、チェックボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/818de887-d3e4-936c-567e-d2a36013fc3b.png)

- 画面下部にテンプレートの生成画面が追加されます。
- テンプレートの生成のプルダウンにて、「メソッドリクエストのパススルー」を選択し「保存」ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/ddab4889-32bb-44a0-790f-ba4ab294c53a.png)

- 画面左「設定」を選択し、「設定」画面の下部「バイナリメディアタイプ」の項目にて「バイナリメディアタイプの追加」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/993cfced-683c-5a36-8fec-c6326843c025.png)

- `multipart/form-data` と入力し、「変更の保存」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/24e6a1e1-6d95-e6d6-adde-7cf087c5fdb5.png)

- 画面左ペイン「リソース」を選択後、画面上部「アクション」より「APIのデプロイ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/f0ccb1b2-10fd-b4fd-99a0-d55f6919db74.png)

- APIのデプロイ画面にて、以下の設定をし、「デプロイ」ボタンを押下します。
    - デプロイされるステージ：「新しいステージ」を選択
    - ステージ名：「dev」を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/9d74ecb9-4c01-a389-5d41-7f082e23f125.png)

- 画面左ペインから、「ステージ」を選択し、「dev」-「rekognition」-「POST」を選択します。
- 画面右に、「URLの呼び出し」として作成された API の URL が表示されるので、これをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/5775c68c-b9d1-ddc6-2f4f-a1dca4f2ddd7.png)


## HTML ファイルの作成
- 以下のHTMLの`****API Gateway URL 貼り付け****`の部分に、先ほど作成した API  Gateway の URL を貼り付け、"index.html"のファイル名で保存します。
    - フォームを用いて、選択されたファイルを送信するだけの、単純な 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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/595f01bc-e9e5-a66f-c4b8-cb8a990289cb.png)


## 動作確認
- 例えば、日本が世界に誇るお笑い芸人（？）「世界のワタベ」で試してみましょう。
    - ※以下のスクリーンショットでは、知財権保護のため画像をぼかしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/21a52e10-3b7e-d3f1-174d-24d8146b3753.png)

- ファイルを選択し、「送信」ボタンを押すと…
- `"He/She is Ken Watabe with 100% confidence."` と表示されました！
- 有名人識別サービスの完成です！　
    - さすが「世界のワタベ」ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/14c0d36d-3ebb-eb22-f97e-76f6c33578ad.png)


# お片付け
- 以下のリソースを削除していきます。
    - API Gateway
    - Lambda
    - CloudWatch ロググループ（Lambdaの実行ログ）
    - Lambda用　IAMロール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/d9d38c09-a3e2-f727-b6f4-b19836b51051.png)


## API Gateway の削除
- API Gateway の画面から、作成した「《お名前》-api-handson」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/87db26bb-ca53-afef-236c-f9c201ccc9d0.png)

- API Gateway の画面から、作成した「《お名前》-api-handson」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/2d4982ee-d683-79ae-ff27-58214d34d111.png)

- 画面左ペインで「リソース」が選択されている状態で、アクションから「APIの削除」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/812b8e56-f3e9-ad87-3f02-c5f314957b6e.png)

- 削除前の確認画面が表示されるので、API名を入力後、「APIの削除」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/65490027-17ff-97a3-dd01-12c473d9bc7e.png)

## CloudWatch ログの削除
- Lambda のコンソール画面へ遷移するために、画面上部の「サービス」から「Lambda」を検索し選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/01507194-32ca-6710-474e-a14eee1fac8a.png)

- 一覧画面にて、「《お名前》-rekognition-handson」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/4199cc33-397d-f7fa-c172-225636541fbd.png)

- 画面上部「モニタリング」を選択し、「CloudWatchのログを表示」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/25adb2bb-617d-3325-474f-24e044b9ee16.png)

- CloudWatch Logs の画面に遷移します。「アクション」から「Delete log group」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/f2820e9d-b0f8-abb4-0be6-88ff335569b9.png)

- 確認画面が表示されるので、「削除」ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/bb81f1bc-276f-ba31-61ee-dbb334fd27a2.png)

## IAM ロールの削除
- Lambda の画面に戻り、「設定」を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/890852bd-8e2b-f0c1-cdaa-f0c9980646c7.png)

- Lambdaの画面下部、「基本設定」の「編集」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/a5cf3def-96c8-9123-a5f8-86e39784c9b8.png)

- 「基本設定を編集」画面の下部まで行き、「IAMコンソールでxxxロールを表示します。」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/23ba9373-40e2-4029-7f7a-e3c861635321.png)

- IAMロールの画面に遷移します。画面右上「ロールの削除」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/868cf713-dddb-5b47-ac82-1dbe3659ad7c.png)

- 確認画面が出るので、「はい、削除します」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/4598c686-bd61-63b6-3690-61c10604b20a.png)

### Lambda 関数の削除
- Lambda の画面に戻り、画面上部「アクション」から「関数の削除」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/06086dd6-3c85-6cec-adb0-e76193cc851e.png)

- 確認画面が表示されるので、「削除」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/012b1ac4-9901-3f80-a436-ac82e95faac3.png)

- 「正常に削除されました。」と表示がでます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341404/931995e9-e1d5-0642-811d-cc72df47a44c.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<br />/128MB,100ミリ秒 |                                |
| API Gateway      | REST API        | 4.25USD/100万件                       | 最初の3  億3,300万コール受信数 |
| Rekognition      | Image           | 0.0013USD/1画像                       | 最初の100万枚                  |




## 参考資料・ドキュメント
- [AWS Hands-on for Beginners Serverless #1サーバーレスアーキテクチャで翻訳 Web API を構築する| AWS](https://pages.awscloud.com/event_JAPAN_Hands-on-for-Beginners-Serverless-2019_LP.html)
- [AWS API Gateway + Lambda から multipart/form-dataを用いてバイナリデータ(wav)をS3にputする – Qiita](https://qiita.com/tetsu0831/items/220ba032116dc94063b3)
- [Rekognition — Boto3 Docs 1.15.11 documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rekognition.html)
- [API Gateway で統合レスポンスを設定する - Amazon API Gateway](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-integration-settings-integration-response.html)
- その他、AWS 公式ドキュメント