Edited at

Amazon Rekognitionで顔認証してみた

More than 1 year has passed since last update.


はじめに

re:Invent 2016でRekognitionというAIを活用した画像認識サービスが発表されました。

ということで、今回はこのサービスを使用して顔認証システムを作ってみました。


Rekognitionとは

ここから「Try Demo」で試すことができます。

開発する時には、様々な言語をサポートしているので、得意なもので書きましょう。

残念ながら、東京リージョンにはまだありませんのでご注意ください。

できることは大きく分けて以下の4つです。


1.物体とシーンの検出

「この写真には○○が写ってる」や「こんな場面で撮られたんでは」などなどをラベル付けしてくれます。

例えばこんな感じ。

image

朝食っぽい画像をアップロードしてみました。

ちゃんとラベルに「Breakfast」がありますね。

ラベルの隣の数値は信頼度です。「97%朝食の画像っぽい」ということを判定してくれているようです。


2.顔分析

画像内の顔の位置を特定して、その人の感情を判定してくれます。

例えば

image

こちらの画像のタイトルは「腕を組んで怒る彼女」でした。

ちゃんと顔の位置を判断してくれていて、ラベルも「not smailing」や「angry」などタイトル通りの結果を返してくれています。

性別も判定してくれるようですね。


3.顔照合

同じ人が写っている2枚の画像を比較して、同一人物かどうかを判定してくれます。

またまた例えば

image

こんな風に顔を抽出して同一人物か判定してくれます。

(ちなみに写真は「日本一インターネットで顔写真が使われているフリー素材モデル」さんです。)


4.顔認識

あらかじめ作っておいたコレクションから、判定してほしい画像と同一人物を探してくれます。

顔照合が「1:1」だったのに対し、こちらは「1:多」で使用できます。

今回作ったものはこれを利用しています。


今回作ったもの

今回作成した顔認証システムについてご紹介します。

JavaScriptで実装しました。大まかな構成は以下の図です。

Rekognition構成図.png

■画像の登録

①S3バケットに画像をアップロードする

②それをトリガーにLambdaが動く

③LambdaがRekognitionのコレクションに画像を登録する

// 一部抜粋

exports.handler = function(event, context) {
console.log("strat import");
//pathを取得
var key = event.Records[0].s3.object.key;
var ids = key.split('/');
var params = {
CollectionId: "コレクション名",
DetectionAttributes: [
],
ExternalImageId: ids[ids.length-1],
Image: {
S3Object: {
Bucket: "バケット名",
Name: key
}
}
};
rekognition.indexFaces(params, function(err, data) {
if (err) console.log(err, err.stack);
else console.log(data);
});
}

■画像の削除

①S3バケット内の画像を削除する

②それをトリガーにLambdaが動く

③LambdaがRekognitionのコレクションの画像から削除対象を検索し、削除する

// 一部抜粋

exports.handler = (event, context, callback) => {
//共通変数
var collectionId = 'コレクション名'
//pathを取得
var key = event.Records[0].s3.object.key;
var ids = key.split('/');
var externalImageId = ids[ids.length-1];
// 検索用
function isThisName(element, index, array){
if(element == null || element.ExternalImageId!=externalImageId){
var param = {};
param.elementExternalImageId=element.ExternalImageId;
param.externalImageId=externalImageId;
param.message = 'error:Image not found';
return false;
}
return true;
}
// コレクションの顔一覧から名前を指定して探し出してDelete
var params = {
CollectionId: collectionId,
MaxResults: 20
};
rekognition.listFaces(params, function(err, data) {
if (err) console.log(err, err.stack);
else{
try{
var deleteId = data.Faces.find(isThisName).FaceId;
console.log('Face name detected! : ' + externalImageId); // コンソールに見つけた画像のIDを出力
var params = {
CollectionId: collectionId,
FaceIds: [
deleteId
]
};
rekognition.deleteFaces(params, function(err, data) {
if (err) console.log(err, err.stack);
else console.log(data + ' delete completed'); //正常に削除された場合
});
}catch(err){
console.log(err);
}
}
});
};

↑ここまでが顔認証するための下準備的な感じ↑

■顔認証

①画像をAPI GatewayにPOSTする

②それを(略)

③LambdaがRekognitionのコレクションから類似率の高い画像を探してくる

④類似率と類似率の高い画像の名前を返す

// 一部抜粋

exports.handler = (event, context, callback) => {
var response = {};
response.result = "ERROR";// デフォルトはエラー
response.matchedFaces = null;
response.stackTrace = null;

console.log(JSON.stringify(event));
console.log(JSON.stringify(event.base64Image));
var bufferImage = new Buffer(event.base64Image, 'base64');
var params = {
CollectionId: "コレクション名",
FaceMatchThreshold: 0,
Image: {
Bytes: bufferImage
},
MaxFaces: 5
};

rekognition.searchFacesByImage(params, function(err, data) {
if (err){
console.log(err, err.stack);
response.stackTrace = err.stack;
callback( null , response);
}
else{
if(data == null || data.FaceMatches == null || data.FaceMatches.length <= 0){
response.result = "NG";
response.matchedFaces = null;
callback( null , response);// マッチする顔画像がなかった場合
}else{
response.result = "OK";
response.matchedFaces = data.FaceMatches;
callback( null , response);// マッチする顔画像があった場合
}
}
});
};

そして顔認証を実行した結果がこちら

{

"result": "OK",
"matchedFaces": [
{
"Similarity": 99.94152069091797,
"Face": {
"FaceId": "852daf16-fe77-5867-a5b2-d1474ca69297",
"BoundingBox": {
"Width": 0.6410260200500488,
"Height": 0.48076900839805603,
"Left": 0.19658100605010986,
"Top": 0.25641000270843506
},
"ImageId": "fa85cbbe-78ce-5e45-bd35-22aee327f427",
"ExternalImageId": "類似率の高い画像のタイトル",
"Confidence": 99.99440002441406
}
}
],
"stackTrace": null
}


result:同一人物っぽい画像があったらOKなかったらNGを返しています

Similarity:同一人物である確度は何%かどうか(今回は99%)

ExternalImageId:コレクション内の類似度の高い画像のタイトル


だいたいこれらの値を見れば、POSTした画像の人がどの写真の人と、どのくらいの確率で同一人物かが分かります。


おわりに

ということで、今回はRekognitionを使って顔認証をしてみました。

AIとか顔認証とか、ちょっとハードルが高そうだと思っていましたが、いよいよ身近になってきたなぁという感じがします。

ドラ○もんの誕生もそう遠くないかもしれませんね。