Amazon Rekognitionを利用してAndrodアプリから顔の類似度を確認する

Amazon Rekognitionを利用して人物の顔の類似度の確認を行ってみたので、まとめておきます。
今回はAndroidアプリから確認しています。

# Amazon Rekognitionって？

詳しい説明については、多くのわかりやすい記事があるのでそちらに譲ります。
ざっくり説明すると、顔同士を比較し類似度を確認することができるAWSのサービスです。
類似度の確認以外にも、表情の分析や有名人の判別など、色々と面白いことができそうです。

![rekognition1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/740e622a-49f1-7cb8-0c7d-75a20cec3e85.png)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/e00b0923-2f80-c13a-2851-25e4b100c618.png" width=50%>

# Amplifyの初期設定

AndroidアプリからAmazon Rekognitionを利用するため、AWSの環境はAmplifyを使って構築していきます。
[ドキュメント](https://docs.amplify.aws/lib/project-setup/prereq/q/platform/android)が非常にわかりやすいので、基本はドキュメント通りに進めていけば問題有りません。

まずは、CLIからAmplifyを利用するためにパッケージをインストールします。

```sh
$ npm install -g @aws-amplify/cli
```

下記コマンドで正しくバージョンが表示されれば、インストール成功です。

```sh
$ amplify --version
```

次に、Amplifyの設定を行っていきます。

```sh
$ amplify configure
Follow these steps to set up access to your AWS account:

Sign in to your AWS administrator account:
https://console.aws.amazon.com/
Press Enter to continue

Specify the AWS Region
? region:  us-east-1  # 任意のリージョンを指定してください
? user name:  amplify  # Amprify操作用の任意のIAMユーザーを指定してください
Complete the user creation using the AWS console
Press Enter to continue
```

ここまで設定してEnterボタンを押下すると、AWSコンソールが開いてIAMユーザーの作成へと進みます。
今回は `AdministorAccess` を付与していますが、適宜適切な権限を付与してください。
最後の `アクセスキーID` と `シークレットアクセスキー` は後ほど使用するので、控えておいてください。

![amplify1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/b6751859-57b2-5674-fa8b-5e121ed236e4.png)

![amplify2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/ab3e29cf-28b1-94b3-d6fc-fe734f06815b.png)

![amplify3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/e186253e-7385-df03-0ab3-0c306ef7693b.png)

ターミナルに戻って、上記で控えた `アクセスキーID` と `シークレットアクセスキー` を設定します。
`Profile Name` はわかりやすいように `amplify` としています。

```sh
Enter the access key of the newly created user:
? accessKeyId:  ********************
? secretAccessKey:  ****************************************
? Profile Name:  amplify  # 任意の名前

Successfully set up the new user.
```

aws cliのプロファイルを追加しておきます。

```sh
$ aws configure --profile amplify
AWS Access Key ID: ********************
AWS Secret Access Key: ****************************************
Default region name: us-east-1
Default output format: json
```

# Androidアプリの初期設定

Androidアプリ側に設定を行っていきます。
こちらも、基本的に[ドキュメント](https://docs.amplify.aws/lib/project-setup/create-application/q/platform/android#n2-install-amplify-libraries)通りです。

アプリの `build.gradle` を下記のように設定します。

```gradle:build.gradle
android {
    compileOptions {
        // Support for Java 8 features
        coreLibraryDesugaringEnabled true
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    // Amplify core dependency
    implementation 'com.amplifyframework:core:1.17.0'

    // Support for Java 8 features
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}
```

正常にビルドできればOKです！

# Amplifyの設定

引き続き、Amplifyの設定をターミナルから行います。

```sh
$ amplify init
? Enter a name for the project YourAppName  # 任意のアプリ名
? Enter a name for the environment dev  # Amplifyで管理する任意の環境名
? Choose your default editor: Visual Studio Code  # 任意のIDEの指定
? Choose the type of app that you are building: android
? Where is your Res directory:  app/src/main/res
? Select the authentication method you want to use: AWS profile
? Please choose the profile you want to use amplify  # 先程作成したaws cliのプロファイル名を指定
```

以上で環境が構築され、AWS Amplifyのコンソールから確認できるようになります。
![amplify_console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/6c0f47e9-05a4-e8ec-c9ed-4094a9deb7f9.png)

# Amazon Rekognitionの設定

AmplifyからAmazon Rekognitionを利用するための設定して行っていきます。
こちらも詳細については[ドキュメント](https://docs.amplify.aws/lib/predictions/getting-started/q/platform/android)を確認してください。

Amplifyで `predictions` を追加します。
[Detect pre-determined entities in an image](https://docs.amplify.aws/lib/predictions/identify-entity/q/platform/android#detect-pre-determined-entities-in-an-image)の設定を参考に進めます。

```sh
$ amplify add predictions
? Please select from one of the categories below Identify
? You need to add auth (Amazon Cognito) to your project in order to add storage for user files. Do you want to add auth now? Yes

Using service: Cognito, provided by: awscloudformation
 
 The current configured provider is Amazon Cognito. 
 
 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Email
 Do you want to configure advanced settings? No, I am done.
Successfully added auth resource hogehoge locally

? Please select from one of the categories below Identify
? What would you like to identify? Identify Entities
? Provide a friendly name for your resource identifyEntitiesfugafuga
? Would you like use the default configuration? Advanced Configuration
? Would you like to enable celebrity detection? No
? Would you like to identify entities from a collection of images? Yes
? How many entities would you like to identify? 10
? Would you like to allow users to add images to this collection? Yes
? Who should have access? Auth and Guest users
```

設定完了後、下記のコマンドで反映します。

```sh
$ amplify push
```

# 比較する顔画像の登録

Androidアプリから送信される画像と比較するための画像を登録します。（[ドキュメントはこちら](https://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/collections.html)）
CLIから行っていきます。

まずは、[コレクションの一覧表示](https://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/list-collection-procedure.html)を行って、作成されたコレクションを確認しましょう。

```sh
$ aws rekognition list-collections
{
    "FaceModelVersions": [
        "5.0"
    ],
    "CollectionIds": [
        "identifyEntitiesfugafuga-dev"  # コレクションのID
    ]
}
```

次に、作成されたコレクションに対し[画像を追加](https://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/add-faces-to-collection-procedure.html)します。
比較するための画像として、フリー素材で見つけた下記の素敵な女性を利用させていただきます。
この画像を任意のS3バケットに保存してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/24ccd460-a26d-a6c2-e294-8ab9a70d5419.jpeg" width=50%>

下記コマンドから、コレクションに対して画像を追加します。
`bucket-name` には画像を保存したS3バケット名、`file-name` には画像名を指定してください。
`collection-id` には、先程確認したコレクションのIDを指定してください。
また、 `example-image.jpg` の部分には、画像を判別するための一意の名前を指定してください。

```sh
aws rekognition index-faces \
      --image '{"S3Object":{"Bucket":"bucket-name","Name":"file-name"}}' \
      --collection-id "collection-id" \
      --max-faces 1 \
      --quality-filter "AUTO" \
      --detection-attributes "ALL" \
      --external-image-id "example-image.jpg" 
```

以上で、比較用の画像が登録されました。

# Androidアプリの設定

Androidアプリ側に、下記のように設定していきます。

アプリのbuild.gradleに追記します。

```gradle:build.gradle
dependencies {
    implementation 'com.amplifyframework:aws-predictions:1.16.15'
    implementation 'com.amplifyframework:aws-auth-cognito:1.16.15'
}
```

次に `MainActivity.kt` を修正します。
比較対象の顔画像として、先程の画像と同一人物の別のフリー画像を用意しました。
`drawable` 内に `woman.jpg` として保存します。

今回はアプリ内に保存した画像を使用しますが、実際の運用ではカメラやギャラリーから画像を取得して比較する形になるかと思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/04737607-6af6-410c-196c-c9783702211c.jpeg" width=50%>

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        try {
            Amplify.addPlugin(AWSCognitoAuthPlugin())
            Amplify.addPlugin(AWSPredictionsPlugin())
            Amplify.configure(applicationContext)
            Log.i("MainActivity", "Initialized Amplify")
        } catch (error: AmplifyException) {
            Log.e("MainActivity", "Could not initialize Amplify", error)
        }

        // 顔画像を取得
        val image = BitmapFactory.decodeResource(resources, R.drawable.woman)

        Amplify.Predictions.identify(IdentifyActionType.DETECT_ENTITIES, image,
                { result ->
                    val identifyResult = result as IdentifyEntityMatchesResult
                    val match = identifyResult.entityMatches.firstOrNull()
                    Log.i("AmplifyQuickstart", "externalImageId: ${match?.externalImageId}")
                    Log.i("AmplifyQuickstart", "confidence: ${match?.confidence}")
                },
                { Log.e("AmplifyQuickstart", "Identify failed", it) }
        )
    }
}
```

# 類似度の確認

Androidアプリを起動しましょう。
Logcatに下記のように出力されます。

```
I/AmplifyQuickstart: externalImageId: 設定したexternal-image-id
I/AmplifyQuickstart: confidence: 99.99981
```

`confidence` が類似度（信頼度）を表します。
同一人物なので、もちろん類似度は高いですね！

手順は少し多いですが、比較的簡単に顔画像の比較が実装できたと思います！