LoginSignup
131
121

More than 5 years have passed since last update.

Amazon Rekognitionで顔認証してみた

Last updated at Posted at 2017-02-17

はじめに

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とか顔認証とか、ちょっとハードルが高そうだと思っていましたが、いよいよ身近になってきたなぁという感じがします。
ドラ○もんの誕生もそう遠くないかもしれませんね。

131
121
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
131
121