12
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

めちゃくちゃ簡単 Amazon Rekognition

Last updated at Posted at 2019-12-19

AIとか画像解析とか聞くとなんか難しそうだけど、Amazonが提供しているサービスを使うと簡単に実装できるので、試してみた!

Amazon Rekognitionとは

Amazon Rekognition では、イメージ分析とビデオ分析をアプリケーションに簡単に追加することができます。Amazon Rekognition API にイメージやビデオを指定するだけで、このサービスによってモノ、人物、テキスト、シーン、アクティビティを識別できます。不適切なコンテンツも検出できます。また、Amazon Rekognition では、高精度な顔分析および顔認識も可能です。顔の検出、分析、比較は、ユーザー検証、カタログ作成、人数計数、公共安全など、多岐にわたって活用できます。

ひとまず実装してみる

環境を作成するのが手間なのでLambdaを使って実装。
プログラムはLambdaで提供があるPython 3.7。

顔認識

人物が写っている2枚の写真から同一人物かどうかを判定する。
S3にアップされている写真を比較するサンプルプログラム。

from boto3 import Session

def lambda_handler(event, context):
    session = Session(region_name="ap-northeast-1")
    rekognition = session.client("rekognition")
    
    response=rekognition.compare_faces(
        SourceImage={'S3Object':{'Bucket':"XXXXX",'Name':"XXXXX"}},
        TargetImage={'S3Object':{'Bucket':"XXXXX",'Name':"XXXXX"}},
        SimilarityThreshold=80)

    return response

簡単にプログラムの解説。

from boto3 import Session

AWSの各種サービスを簡単に仕様できるライブラリboto3を使って実装。
※ライブライはC++、Go、Java、JavaScript,.Net、Node.js、PHP、Rubyがある

    session = Session(region_name="ap-northeast-1")
    rekognition = session.client("rekognition")

サービスを使用するためには必ずSessionというAWSとの接続情報が必要。
リージョンはアジア東京を指定。
rekognitionを使用するためのオブジェクト取得。

    response=rekognition.compare_faces(
        SourceImage={'S3Object':{'Bucket':"XXXXX",'Name':"XXXXX"}},
        TargetImage={'S3Object':{'Bucket':"XXXXX",'Name':"XXXXX"}},
        SimilarityThreshold=80)

これがAmazonから提供されている「顔認証」関数。
API仕様 こちらから

SourceImageに認識したい顔だけが写っている写真
TargetImageに解析したい写真
SimilarityThresholdに認識度。高いほど厳しいチェックになる。0-100で指定。

responseは
FaceMatches に同一人物を判断した顔の情報
UnmatchedFaces に違うと判断した顔の情報

Confidenceがその判断の信頼度

{
  "SourceImageFace": {
    "BoundingBox": {
      "Width": 0.30209746956825256,
      "Height": 0.21446102857589722,
      "Left": 0.319732129573822,
      "Top": 0.23807010054588318
    },
    "Confidence": 99.99998474121094
  },
  "FaceMatches": [
    {
      "Similarity": 99.37952423095703,
      "Face": {
        "BoundingBox": {
          "Width": 0.21386872231960297,
          "Height": 0.16094279289245605,
          "Left": 0.6417301297187805,
          "Top": 0.6225799322128296
        },
        "Confidence": 99.99987030029297,
        "Landmarks": [
          {
            "Type": "eyeLeft",
            "X": 0.7082532644271851,
            "Y": 0.6811327934265137
          },
          {
            "Type": "eyeRight",
            "X": 0.7683542370796204,
            "Y": 0.7155389189720154
          },
          {
            "Type": "mouthLeft",
            "X": 0.6812899112701416,
            "Y": 0.7383925914764404
          },
          {
            "Type": "mouthRight",
            "X": 0.7310847640037537,
            "Y": 0.7682420015335083
          },
          {
            "Type": "nose",
            "X": 0.6889581680297852,
            "Y": 0.7370006442070007
          }
        ],
        "Pose": {
          "Roll": 38.84079360961914,
          "Yaw": -19.29507827758789,
          "Pitch": -41.210079193115234
        },
        "Quality": {
          "Brightness": 44.140357971191406,
          "Sharpness": 78.64350128173828
        }
      }
    }
  ],
  "UnmatchedFaces": [
    {
      "BoundingBox": {
        "Width": 0.01333685964345932,
        "Height": 0.013453098013997078,
        "Left": 0.9252238869667053,
        "Top": 0.4759874939918518
      },
      "Confidence": 97.7153091430664,
      "Landmarks": [
        {
          "Type": "eyeLeft",
          "X": 0.9277710914611816,
          "Y": 0.4811204969882965
        },
        {
          "Type": "eyeRight",
          "X": 0.933621883392334,
          "Y": 0.4823104441165924
        },
        {
          "Type": "mouthLeft",
          "X": 0.9270203113555908,
          "Y": 0.4870522618293762
        },
        {
          "Type": "mouthRight",
          "X": 0.931785523891449,
          "Y": 0.4880983531475067
        },
        {
          "Type": "nose",
          "X": 0.9278116226196289,
          "Y": 0.484792023897171
        }
      ],
      "Pose": {
        "Roll": 13.193720817565918,
        "Yaw": -30.132854461669922,
        "Pitch": -10.473925590515137
      },
      "Quality": {
        "Brightness": 75.9936752319336,
        "Sharpness": 73.32209777832031
      }
    },
    {
      "BoundingBox": {
        "Width": 0.2887393832206726,
        "Height": 0.32251936197280884,
        "Left": 0.1142626702785492,
        "Top": 0.45462948083877563
      },
      "Confidence": 99.99995422363281,
      "Landmarks": [
        {
          "Type": "eyeLeft",
          "X": 0.1551831066608429,
          "Y": 0.5991319417953491
        },
        {
          "Type": "eyeRight",
          "X": 0.25697842240333557,
          "Y": 0.6217619776725769
        },
        {
          "Type": "mouthLeft",
          "X": 0.14137881994247437,
          "Y": 0.7185965180397034
        },
        {
          "Type": "mouthRight",
          "X": 0.22245647013187408,
          "Y": 0.7383744716644287
        },
        {
          "Type": "nose",
          "X": 0.14210543036460876,
          "Y": 0.6684256792068481
        }
      ],
      "Pose": {
        "Roll": 17.434614181518555,
        "Yaw": -41.510498046875,
        "Pitch": -21.136119842529297
      },
      "Quality": {
        "Brightness": 41.628482818603516,
        "Sharpness": 95.51618957519531
      }
    },
    {
      "BoundingBox": {
        "Width": 0.007370786275714636,
        "Height": 0.008144599385559559,
        "Left": 0.6609883904457092,
        "Top": 0.49813687801361084
      },
      "Confidence": 83.50224304199219,
      "Landmarks": [
        {
          "Type": "eyeLeft",
          "X": 0.6622864603996277,
          "Y": 0.5042642951011658
        },
        {
          "Type": "eyeRight",
          "X": 0.6650356650352478,
          "Y": 0.5022475719451904
        },
        {
          "Type": "mouthLeft",
          "X": 0.6650884747505188,
          "Y": 0.5060529112815857
        },
        {
          "Type": "mouthRight",
          "X": 0.6673902273178101,
          "Y": 0.5043438076972961
        },
        {
          "Type": "nose",
          "X": 0.6656265258789062,
          "Y": 0.505027174949646
        }
      ],
      "Pose": {
        "Roll": -43.10660934448242,
        "Yaw": -4.3733038902282715,
        "Pitch": -33.09136962890625
      },
      "Quality": {
        "Brightness": 73.02571868896484,
        "Sharpness": 53.330047607421875
      }
    },
    {
      "BoundingBox": {
        "Width": 0.009758301079273224,
        "Height": 0.010332607664167881,
        "Left": 0.966498851776123,
        "Top": 0.46405404806137085
      },
      "Confidence": 61.05154037475586,
      "Landmarks": [
        {
          "Type": "eyeLeft",
          "X": 0.9691260457038879,
          "Y": 0.4726991653442383
        },
        {
          "Type": "eyeRight",
          "X": 0.9677429795265198,
          "Y": 0.4707190990447998
        },
        {
          "Type": "mouthLeft",
          "X": 0.9723362326622009,
          "Y": 0.4712704122066498
        },
        {
          "Type": "mouthRight",
          "X": 0.9711670279502869,
          "Y": 0.4696311056613922
        },
        {
          "Type": "nose",
          "X": 0.9699736833572388,
          "Y": 0.4713567793369293
        }
      ],
      "Pose": {
        "Roll": -119.80672454833984,
        "Yaw": -8.657889366149902,
        "Pitch": 21.94735336303711
      },
      "Quality": {
        "Brightness": 84.52898406982422,
        "Sharpness": 73.32209777832031
      }
    },
    {
      "BoundingBox": {
        "Width": 0.018424568697810173,
        "Height": 0.020794881507754326,
        "Left": 0.7489200830459595,
        "Top": 0.47518208622932434
      },
      "Confidence": 87.87468719482422,
      "Landmarks": [
        {
          "Type": "eyeLeft",
          "X": 0.7618342638015747,
          "Y": 0.48698189854621887
        },
        {
          "Type": "eyeRight",
          "X": 0.7628127336502075,
          "Y": 0.4866960644721985
        },
        {
          "Type": "mouthLeft",
          "X": 0.7631105184555054,
          "Y": 0.4888738989830017
        },
        {
          "Type": "mouthRight",
          "X": 0.7637985944747925,
          "Y": 0.4886566698551178
        },
        {
          "Type": "nose",
          "X": 0.7641363143920898,
          "Y": 0.48711803555488586
        }
      ],
      "Pose": {
        "Roll": -34.46097946166992,
        "Yaw": 60.46308135986328,
        "Pitch": -14.032490730285645
      },
      "Quality": {
        "Brightness": 67.51453399658203,
        "Sharpness": 83.14741516113281
      }
    },
    {
      "BoundingBox": {
        "Width": 0.011087420396506786,
        "Height": 0.011487020179629326,
        "Left": 0.9760779142379761,
        "Top": 0.4641396105289459
      },
      "Confidence": 97.86558532714844,
      "Landmarks": [
        {
          "Type": "eyeLeft",
          "X": 0.978825032711029,
          "Y": 0.469203919172287
        },
        {
          "Type": "eyeRight",
          "X": 0.9811084270477295,
          "Y": 0.4689272344112396
        },
        {
          "Type": "mouthLeft",
          "X": 0.9797573685646057,
          "Y": 0.47199031710624695
        },
        {
          "Type": "mouthRight",
          "X": 0.9815858006477356,
          "Y": 0.47177186608314514
        },
        {
          "Type": "nose",
          "X": 0.979856014251709,
          "Y": 0.47067731618881226
        }
      ],
      "Pose": {
        "Roll": -11.149984359741211,
        "Yaw": -42.128475189208984,
        "Pitch": -1.7187515497207642
      },
      "Quality": {
        "Brightness": 79.50706481933594,
        "Sharpness": 73.32209777832031
      }
    },
    {
      "BoundingBox": {
        "Width": 0.008290473371744156,
        "Height": 0.009163682349026203,
        "Left": 0.6165273785591125,
        "Top": 0.5080556273460388
      },
      "Confidence": 73.62310791015625,
      "Landmarks": [
        {
          "Type": "eyeLeft",
          "X": 0.6195554137229919,
          "Y": 0.5123717188835144
        },
        {
          "Type": "eyeRight",
          "X": 0.6210446357727051,
          "Y": 0.5128311514854431
        },
        {
          "Type": "mouthLeft",
          "X": 0.6189116835594177,
          "Y": 0.5142983794212341
        },
        {
          "Type": "mouthRight",
          "X": 0.6200852394104004,
          "Y": 0.5146732926368713
        },
        {
          "Type": "nose",
          "X": 0.6193997263908386,
          "Y": 0.5135700702667236
        }
      ],
      "Pose": {
        "Roll": 20.73882293701172,
        "Yaw": -33.038211822509766,
        "Pitch": -11.055394172668457
      },
      "Quality": {
        "Brightness": 41.28157424926758,
        "Sharpness": 67.22731018066406
      }
    }
  ],
  "ResponseMetadata": {
    "RequestId": "d638e263-eeb5-4cbf-807d-aa6328f8096b",
    "HTTPStatusCode": 200,
    "HTTPHeaders": {
      "content-type": "application/x-amz-json-1.1",
      "date": "Thu, 19 Dec 2019 12:20:36 GMT",
      "x-amzn-requestid": "d638e263-eeb5-4cbf-807d-aa6328f8096b",
      "content-length": "5545",
      "connection": "keep-alive"
    },
    "RetryAttempts": 0
  }
}

導入事例

千株式会社の写真販売サービス「はいチーズ」。幼稚園や保育園でのイベントの写真販売の際に、スマホから「自分の子どもが映った写真」だけを選んで抽出できるサービスを提供。

テキスト検出

from boto3 import Session

def lambda_handler(event, context):
    session = Session(region_name="ap-northeast-1")
    rekognition = session.client("rekognition")

    response=rekognition.detect_text(Image={'S3Object':{'Bucket':"XXXXX",'Name':"XXXXX"}})
    
    return response

簡単にプログラムの解説。

from boto3 import Session

AWSの各種サービスを簡単に仕様できるライブラリboto3を使って実装。
※ライブライはC++、Go、Java、JavaScript,.Net、Node.js、PHP、Rubyがある

    session = Session(region_name="ap-northeast-1")
    rekognition = session.client("rekognition")

サービスを使用するためには必ずSessionというAWSとの接続情報が必要。
リージョンはアジア東京を指定。
rekognitionを使用するためのオブジェクト取得。

    response=rekognition.detect_text(Image={'S3Object':{'Bucket':"XXXXX",'Name':"XXXXX"}})

これがAmazonから提供されている「テキスト検出」関数。
API仕様 こちらから

Imageに解析したい画像を渡すだけ。

demo2_car.jpeg

この画像を解析した結果。
行と単語ごとに解析される。
「J389 NLT」は行(line)で「J389 NLT」、単語で「J389」「NLT」。
DetectedTextが検出したテキスト
Confidenceが信頼度

{
  "TextDetections": [
    {
      "DetectedText": "C",
      "Type": "LINE",
      "Id": 0,
      "Confidence": 72.02649688720703,
      "Geometry": {
        "BoundingBox": {
          "Width": 0.04000072553753853,
          "Height": 0.022570611909031868,
          "Left": 0.25833332538604736,
          "Top": 0.1862500011920929
        },
        "Polygon": [
          {
            "X": 0.25833332538604736,
            "Y": 0.1862500011920929
          },
          {
            "X": 0.2983340620994568,
            "Y": 0.18744535744190216
          },
          {
            "X": 0.29803428053855896,
            "Y": 0.21001596748828888
          },
          {
            "X": 0.2580335736274719,
            "Y": 0.20882061123847961
          }
        ]
      }
    },
    {
      "DetectedText": "J389 NLT",
      "Type": "LINE",
      "Id": 1,
      "Confidence": 99.67211151123047,
      "Geometry": {
        "BoundingBox": {
          "Width": 0.16278892755508423,
          "Height": 0.054150763899087906,
          "Left": 0.47471365332603455,
          "Top": 0.7062126398086548
        },
        "Polygon": [
          {
            "X": 0.47471365332603455,
            "Y": 0.7062126398086548
          },
          {
            "X": 0.6375026106834412,
            "Y": 0.7274553775787354
          },
          {
            "X": 0.6343620419502258,
            "Y": 0.781606137752533
          },
          {
            "X": 0.4715730845928192,
            "Y": 0.7603633999824524
          }
        ]
      }
    },
    {
      "DetectedText": "C",
      "Type": "WORD",
      "Id": 2,
      "ParentId": 0,
      "Confidence": 72.02649688720703,
      "Geometry": {
        "BoundingBox": {
          "Width": 0.040019527077674866,
          "Height": 0.022515427321195602,
          "Left": 0.25833332538604736,
          "Top": 0.1862500011920929
        },
        "Polygon": [
          {
            "X": 0.25833332538604736,
            "Y": 0.1862500011920929
          },
          {
            "X": 0.2983333468437195,
            "Y": 0.1875
          },
          {
            "X": 0.29750001430511475,
            "Y": 0.20999999344348907
          },
          {
            "X": 0.25833332538604736,
            "Y": 0.20874999463558197
          }
        ]
      }
    },
    {
      "DetectedText": "J389",
      "Type": "WORD",
      "Id": 3,
      "ParentId": 1,
      "Confidence": 99.63874053955078,
      "Geometry": {
        "BoundingBox": {
          "Width": 0.08508982509374619,
          "Height": 0.05266508460044861,
          "Left": 0.4749999940395355,
          "Top": 0.706250011920929
        },
        "Polygon": [
          {
            "X": 0.4749999940395355,
            "Y": 0.706250011920929
          },
          {
            "X": 0.559166669845581,
            "Y": 0.71875
          },
          {
            "X": 0.5550000071525574,
            "Y": 0.7712500095367432
          },
          {
            "X": 0.4716666638851166,
            "Y": 0.7587500214576721
          }
        ]
      }
    },
    {
      "DetectedText": "NLT",
      "Type": "WORD",
      "Id": 4,
      "ParentId": 1,
      "Confidence": 99.70547485351562,
      "Geometry": {
        "BoundingBox": {
          "Width": 0.07040064036846161,
          "Height": 0.05260571464896202,
          "Left": 0.5674999952316284,
          "Top": 0.7200000286102295
        },
        "Polygon": [
          {
            "X": 0.5674999952316284,
            "Y": 0.7200000286102295
          },
          {
            "X": 0.637499988079071,
            "Y": 0.7275000214576721
          },
          {
            "X": 0.6341666579246521,
            "Y": 0.7799999713897705
          },
          {
            "X": 0.5649999976158142,
            "Y": 0.7724999785423279
          }
        ]
      }
    }
  ],
  "ResponseMetadata": {
    "RequestId": "b4280fa0-2982-4ac7-8ce3-02beb83b986f",
    "HTTPStatusCode": 200,
    "HTTPHeaders": {
      "content-type": "application/x-amz-json-1.1",
      "date": "Thu, 19 Dec 2019 13:26:41 GMT",
      "x-amzn-requestid": "b4280fa0-2982-4ac7-8ce3-02beb83b986f",
      "content-length": "2131",
      "connection": "keep-alive"
    },
    "RetryAttempts": 0
  }
}

料金

API を使用して画像を分析するたびに料金が発生。
だいたい、 1 か月あたり 100 万枚分析して 1000 USD。

料金例は こちらから

捕捉

ACCESS_KEY、SECRET_KEYを指定せずに正常にsessionが取得できているのはLambdaを使っているからですね。
ポリシーを作成し、Lambda実行するロールに割り当ている。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rekognition:DetectText",
                "rekognition:CompareFaces",
                "s3:*"
            ],
            "Resource": "*"
        }
    ]
}

rekognition:DetectText、rekognition:CompareFacesの使用とs3への全ての操作を許可。

これがないと下記のエラーが出る。

 "errorMessage": "An error occurred (AccessDeniedException) when calling the CompareFaces operation: User: arn:aws:sts::294326415501:assumed-role/testRekognitionPythonFace-role-jcjxzbmq/testRekognitionPythonFace is not authorized to perform: rekognition:CompareFaces",
12
9
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
12
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?