【Rekognition】【初心者コピペ20分】2つの写真の顔をローカルで比較しよう Part2
はじめに
お疲れ様です。
クワハラと申します。
2回に渡りAmazon Rekognitionを使って、シンプルにローカルで2つの写真から顔を切り取り、類似度を表示するように実装します。
今回は前回作成したVite×Reactのプロジェクトの続きで、
RekognitionのCompareFacesオペレーションを使用して、顔の位置と類似度の取得を実装していきます。
前回の内容をまだご覧になっていない方は、まずはそちらをご確認ください。

目次
CompareFacesについて
概要
Rekognitionでは、2つの画像から顔の比較を行なうことができる機能としてCompareFaces
オペレーションが用意されています。
これにより、2つの画像の顔の類似度や位置情報を取得することができます。
今回はこのCompareFaces
オペレーションを使用して、2つの写真の顔の比較をします。
今回の実装における使用上の注意点
利用上の注意点としてCompareFaces
オペレーションは、比較元の画像では1つの顔しか検出されません。
そのため比較元の画像に複数の顔が写っている場合、最も大きな顔を検出し比較されます。
また、デフォルトでは80%以上の類似度を持つ比較対象の顔のみがレスポンスに含まれます。
今回は必ず顔を返すようにするため、SimilarityThreshold
の値を0にし調整します。
なお、比較対象の画像には複数の顔が写っていても問題ありませんが、
今回は実装の複雑さを避けるため、比較元と比較対象の画像には1つの顔のみが写っていることを前提として実装します。
詳細な内容は、AWSの公式ドキュメントをご参照してください。
完成形のイメージ
前提条件
Part1と同じ条件となります。
実行環境
Part1と同じです。他のバージョンで実行する場合は適宜調整してください。
処理概要図
今回は以下のような処理を想定しています。
※★がついているところを今回は実装します。

CompareFacesを使用する
Rekognitionの認証情報を設定
AWSマネジメントコンソール上部の検索エリアに[IAM]と入力して、IAMホーム画面を開いてください。

IAM画面左側の[アクセス管理] > [ユーザー]を選択して、IAMユーザ一覧画面を表示してください。

[ユーザーの作成]を選択してください。

ユーザ詳細画面にて以下を設定し、[次へ]を選択してください。
項目名 | 設定値 |
ユーザー名 | 任意 ※今回は rekognition-demo とします |
AWSマネジメントコンソールへのユーザーアクセスを提供する | チェックなし |

今回はデモのためRekognitionへのフルアクセス権限を付与してIAMユーザを作成してください。
※ 実際にシステム構築する際は、AWSベストプラクティスである「最小権限の原則」に従い、必要な権限のみ付与するようにしてください。


IAMユーザ作成後、該当IAMユーザの詳細画面からアクセスキーを発行しましょう。
[セキュリティ認証情報]タブの[アクセスキー]セクションにて、[アクセスキーを作成]を選択してください。

ユースケースを選択して、[次へ]を選択してください。

説明タグは省略して[アクセスキーを作成]を選択してください。

アクセスキーをダウンロードし外部に漏れないように厳重に保管してください。
次に、ローカルからAWSへのアクセス設定のため、.env.local
をプロジェクトのルートディレクトリに作成します。
.
├── .env.local ★追加
├── ・・・
├── src
│ ├── api
│ │ └── index.ts
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ ├── originalSrc
│ │ │ └── compare1.png
│ │ ├── react.svg
│ │ └── targetSrc
│ │ └── compare2.png
│ ├── hooks
│ │ └── useFaceSearch.ts
│ ├── index.css
│ ├── main.tsx
│ ├── utils
│ │ └── index.ts
│ └── vite-env.d.ts
└── ・・・
.env.local
に先ほど取得したIAMユーザのアクセスキー情報を記述します。
VITE_AWS_ACCESS_KEY=取得したアクセスキー
VITE_AWS_SECRET_KEY=取得したシークレットキー
APIを実装
src/utils/index.ts
を開き、以下のコードを追加します。
// existing code...
// 以下を追加
// 画像をBase64形式の文字列に変換する関数
const convertImageToBase64 = (imageSrc: string): Promise<string> => {
return new Promise((resolve, reject) => {
fetch(imageSrc)
.then((response) => response.blob())
.then((blob) => {
const reader = new FileReader(); // 各呼び出しで新しいFileReaderを作成
reader.onload = () => resolve(reader.result as string);
reader.onerror = reject;
reader.readAsDataURL(blob);
})
.catch(reject);
});
};
// Base64文字列からUint8Arrayに変換する関数
const base64ToUint8Array = (base64: string): Uint8Array => {
// data:image/xxx;base64, のプレフィックスを除去
const trimmingRegex = /^data:image\/[a-z]+;base64,/;
const base64Data = base64.replace(trimmingRegex, "");
const binaryString = atob(base64Data);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
};
// 2つの画像をBase64形式に変換し、Uint8Arrayとして返す関数
export const convertImagesToUnit8Array = async (
originalSrc: string,
compareSrc: string
) => {
const [originalBase64, compareBase64] = await Promise.all([
convertImageToBase64(originalSrc),
convertImageToBase64(compareSrc),
]);
const originalBinary = base64ToUint8Array(originalBase64);
const compareBinary = base64ToUint8Array(compareBase64);
return [originalBinary, compareBinary];
};
src/api/index.ts
を開き、全て以下のコードに書き換えます。
(リクエストについて)
- Bytes: AWS SDK for JavaScript v3では、ローカルの画像はBase64にエンコーディング→Uint8Arrayに変換することで、送信が可能になります。
※Bytesパラメータで送信できる画像は最大5MBまでとなります。 - SimilarityThreshold: 指定しない場合デフォルトで80となり、類似度が80%以上でない顔はレスポンスに含まれなくなります。今回は必ず顔を取得したいため0で設定します。
※Rekognitionは機械学習システムで確率的であるため、用途に応じて適切な閾値設定を行ってください。
import { convertImagesToUnit8Array } from "../utils";
import type { CompareFacesCommandOutput } from "@aws-sdk/client-rekognition";
import {
CompareFacesCommand,
RekognitionClient,
} from "@aws-sdk/client-rekognition";
const awsConfig = {
region: "ap-northeast-1", // 対象のAWSリージョンを指定してください。
credentials: {
accessKeyId: import.meta.env.VITE_AWS_ACCESS_KEY,
secretAccessKey: import.meta.env.VITE_AWS_SECRET_KEY,
},
};
const rekognition = new RekognitionClient(awsConfig);
export const executeCompareFace = async (
originalSrc: string,
targetSrc: string
) => {
try {
// 比較元と比較対象の画像を変換
const [originalBinary, compareBinary] = await convertImagesToUnit8Array(
originalSrc,
targetSrc
);
// MEMO:ローカルで画像を使用する際はUint8Arrayに変換する必要があります。
const params = {
SourceImage: {
Bytes: originalBinary,
},
TargetImage: {
Bytes: compareBinary,
},
SimilarityThreshold: 0, // MEMO:今回は必ず顔を取得したいため0で設定します。
};
const command = new CompareFacesCommand(params);
const res: CompareFacesCommandOutput = await rekognition.send(command);
return res;
} catch (error) {
console.error("Error converting images:", error);
throw error;
}
};
完成
以下のコマンドでViteを起動します。
% npm run dev
ブラウザでhttp://localhost:5173/
にアクセスし、以下のような動作ができれば成功です。
- 比較元の画像と比較対象の画像が表示され、比較ボタンをクリックすると類似度が表示されます。
- 類似度は0〜100の割合で表示され、100に近いほど顔が一致していることを示します。
※Part1と比べて顔の位置が正確に切り取れ、類似度の取得もできました。
まとめ
いかがでしたでしょうか。
2回に渡り、2つの写真の顔を比較するためにRekognitionのCompareFacesをローカルで実装しました。
これらを使用することで自前でサーバーなどを立てずに顔の比較や認識を簡単に行うことができます。
皆様の一助になれば幸いです。
以上です。
最後までお読みいただき、ありがとうございました。