Amazon Rekognitionをアルティメット完全理解する

2024.03.09

こんちには。

データアナリティクス事業本部 機械学習チームの中村(nokomoro3)です。

本記事ではAmazon Rekognitionにアルティメット完全理解(再入門)していきます。

Amazon Rekognitionとは

Amazon Rekognitionとは、AWSが提供する画像分析についてのマネージドな機械学習サービスとなっています。

機械学習のモデルやインフラをゼロから構築することなく、トレーニング済みまたはカスタマイズ可能な画像処理APIをアプリケーションに素早く追加することが可能です。

画像認識(物体認識)、顔画像の検索、モデレーション(有害検出)など機能が多岐に渡っているサービスです。

Amazon Rekognitionの構成

Rekognitionの中で以下のような部分に分かれています。

  • Amazon Rekognition Image : 静止画向け
  • Amazon Rekognition Video : 動画向け
  • Amazon Rekognition Custom Labels : ラベル検出のカスタム
  • Amazon Rekognition Face Liveness : 写真か本物の人間かの判定
  • Amazon Rekognition Custom Moderation : モデレーションのカスタム

それぞれの機能や動作を確認していきましょう。

Amazon Rekognition Image

概要

「Amazon Rekognition Image」は静止画を対象とした画像分析を行うサービスとなっています。

以下のようなことが可能です。

  • 顔画像のマッチング
  • 顔画像の検索
  • ラベル検出
  • モデレーション(有害性の検出)
  • 顔の検出と分析
  • 画像中のテキスト検出
  • 有名人の認識
  • 個人用防護具 (PPE) 検出
  • 画像のプロパティ分析

今回はboto3から使ってみますが、それぞれの機能はマネジメントコンソールからトライアルすることが可能ですので、ぜひ触ってみてください。

顔画像のマッチング

顔画像のマッチングは、2つの顔画像が一致するかどうかを判定します。

サンプルコードとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

with (
    open("./source.jpg", 'rb') as f1,
    open("./target.jpg", 'rb') as f2
):
    response = client.compare_faces(SimilarityThreshold=80,
        SourceImage={'Bytes': f1.read()},
        TargetImage={'Bytes': f2.read()})

    print(json.dumps(response, indent=4))

SourceImageがマッチング(検索)したい顔画像を指定します。

別途与えるTargetImageの中から、SourceImageと一致する顔画像をマッチングします。

そのため、SourceImageには1人の顔画像が写っている前提で、複数の顔が写っている場合は最も画像サイズの大きい顔がマッチングする顔画像として選択されます。 また逆に、TargetImageには複数の顔画像が写っていても良いので、マッチした顔とそうでない顔を分けて結果を得ることができます。

なおSourceImageやTargetImageにはS3バケットのオブジェクトを指定することもできます。

(これは以降で登場するAPIでも共通して同様です)

以下がレスポンスの抜粋です。

{
    "SourceImageFace": {
        "BoundingBox": {
            "Width": 0.28875553607940674,
            "Height": 0.6640532612800598,
            "Left": 0.3812910318374634,
            "Top": 0.15785908699035645
        },
        "Confidence": 99.99982452392578
    },
    "FaceMatches": [
        {
            "Similarity": 99.99186706542969,
            "Face": {
                "BoundingBox": {
                    "Width": 0.18647146224975586,
                    "Height": 0.4844239056110382,
                    "Left": 0.40962982177734375,
                    "Top": 0.16498763859272003
                },
                "Confidence": 99.99944305419922,
                "Landmarks": [ /* 省略 */ ]
                "Pose": { /* 省略 */ }
                "Quality": { /* 省略 */ }
            }
        }
    ]
}

SourceImageFaceは顔の位置検出(BoundingBox)、位置検出の信頼度(Confidence)などが結果として得られ、FaceMatchesは更に細かく顔のパーツの場所やSharpnessやBrigntnessなどの画像の指標も得ることができます。

詳細は以下もご覧ください。

顔画像の検索

あらかじめ顔画像をベクトル化して登録しておくことで、そのコレクションの中から検索することができます。

主に以下のような流れでAPIを実行して登録処理をします。

  • コレクションの作成 (CreateCollection)
  • 顔画像のベクトルを作成してコレクションに追加 (IndexFaces)
  • ユーザ(個人)を作成 (CreateUser)
  • 顔画像をユーザ(個人)に関連付け (AssociateFaces)

その後以下で検索を実行します。

  • コレクション内のユーザを画像データで検索 (SearchUsersByImage)
  • コレクション内のユーザをUser ID(コレクション内のID)で検索 (SearchUsers)

ユーザ単位の検索ではなく、顔画像(Face)で検索することもできます。

  • コレクション内の顔画像を画像データで検索 (SearchFacesbyImage)
  • コレクション内の顔画像をFace ID(コレクション内のID)で検索 (SearchFaces)

ユーザと顔画像の関連付け解除には以下をコールします。

  • 関連付けを解除 (DisassociateFaces)

サンプルとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

# コレクションの作成
collection_id = "sample-collection"
response = client.create_collection(CollectionId=collection_id)

# 顔画像のベクトルを作成してコレクションに追加
face_ids = []
for file_name in ["./andy-1.jpg", "./andy-2.jpg", "./jeff.jpg"]:
    with open(file_name, 'rb') as f:
        response = client.index_faces(
            CollectionId=collection_id,
            Image={'Bytes': f.read()})
        face_ids.append(response["FaceRecords"][0]["Face"]["FaceId"])

# ユーザ(andy)を作成
user_id = "andy"
response = client.create_user(
    CollectionId=collection_id,
    UserId=user_id)

# 顔画像をユーザ(個人)に関連付け
andy_face_ids = face_ids[:-1]
response = client.associate_faces(
    CollectionId=collection_id,
    UserId=user_id,
    FaceIds=andy_face_ids)

# コレクション内のユーザを画像データで検索
with open("./andy-1.jpg", 'rb') as f:
    response = client.search_users_by_image(CollectionId=collection_id,
        Image={'Bytes': f.read()})
print(json.dumps(response, indent=4))

# コレクションの削除(必要あれば)
response = client.delete_collection(CollectionId=collection_id)

以下がレスポンスの抜粋です。

{
    "UserMatches": [
        {
            "Similarity": 99.99998474121094,
            "User": {
                "UserId": "andy",
                "UserStatus": "ACTIVE"
            }
        }
    ],
    "SearchedFace": {
        "FaceDetail": {
            "BoundingBox": {
                "Width": 0.28875553607940674,
                "Height": 0.6640532612800598,
                "Left": 0.3812910318374634,
                "Top": 0.15785908699035645
            }
        }
    },
    "UnsearchedFaces": []
}

UserMatchesに検索結果が格納され、実際与えられた画像の中の顔画像の位置がSearchedFaceという形で得られます。Similarityが検索された顔との類似度になります。

また画像内に複数の顔画像が含まれる場合は、最もサイズの大きい顔画像が検索対象とされ、それ以外の顔画像もUnsearchedFacesに顔検出の結果が格納されるようです。

詳細は以下もご覧ください。

ラベル検出

ラベル付け機能は画像に対してあらかじめ決められた数千種類のラベル付けが可能です。

画像全体としてのラベリングと、物体検出を伴う画像内の特定箇所へのラベリングの双方ができます。

サンプルコードとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

with open("./skateboard.jpg", 'rb') as f:
    response = client.detect_labels(
        Image={'Bytes': f.read()})
    print(json.dumps(response, indent=4))

以下がレスポンスの抜粋です。

{
    "Labels": [
        {
            "Name": "City",
            "Confidence": 99.9817886352539,
            "Instances": [],
            "Parents": [],
            "Aliases": [
                {
                    "Name": "Town"
                }
            ],
            "Categories": [
                {
                    "Name": "Buildings and Architecture"
                }
            ]
        },
        {
            "Name": "Person",
            "Confidence": 98.33113098144531,
            "Instances": [
                {
                    "BoundingBox": {
                        "Width": 0.2067909687757492,
                        "Height": 0.2868824005126953,
                        "Left": 0.430451363325119,
                        "Top": 0.34091803431510925
                    },
                    "Confidence": 98.33113098144531
                },
                {
                    "BoundingBox": {
                        "Width": 0.010391795076429844,
                        "Height": 0.018741684034466743,
                        "Left": 0.2174091786146164,
                        "Top": 0.535003125667572
                    },
                    "Confidence": 80.30162048339844
                },
                /* 省略 */
            ],
            "Parents": [],
            "Aliases": [
                {
                    "Name": "Human"
                }
            ],
            "Categories": [
                {
                    "Name": "Person Description"
                }
            ]
        }
    ]
}

Instancesがないものは画像全体に対するラベルで、Instancesがあるものは物体検出を伴うラベリングです。

Nameがラベリングの結果に相当しますが、親となるラベル、エイリアスとなるラベル、カテゴリなどの情報も得られることが分かります。

ラベル検出をカスタマイズしたい場合は後述の「Amazon Rekognition Custom Labels」を使う必要があります。

詳細は以下もご覧ください。

モデレーション(有害性の検出)

前述のラベル検出とは別に、画像の有害性をいくつかのラベルに分けて検出できます。

サンプルコードとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

with open("./sample_moderation.jpg", 'rb') as f:
    response = client.detect_moderation_labels(
        Image={'Bytes': f.read()})
    print(json.dumps(response, indent=4))

以下がレスポンスの抜粋です。

{
    "ModerationLabels": [
        {
            "Confidence": 95.3407974243164,
            "Name": "Swimwear or Underwear",
            "ParentName": "",
            "TaxonomyLevel": 1
        },
        {
            "Confidence": 95.3407974243164,
            "Name": "Female Swimwear or Underwear",
            "ParentName": "Swimwear or Underwear",
            "TaxonomyLevel": 2
        }
        /* 省略 */
    ]
}

モデレーションも親子関係があり、TaxonomyLevelはその親子関係の階層を表しています。約30程度の種類のラベルがあるようです。

詳細は以下もご覧ください。

顔の検出と分析

顔に特化した位置検出や顔の状態、感情、顔のパーツの細かい位置、眼鏡やサングラスの有無などを分析できます。複数の人物が写っている場合も有効です。

サンプルコードとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

with open("./sample_face.jpg", 'rb') as f:

    response = client.detect_faces(
        Image={'Bytes': f.read()},
        Attributes=["ALL"])

    print(json.dumps(response, indent=4))

以下がレスポンスの抜粋です。

{
    "FaceDetails": [
        {
            "BoundingBox": {
                "Width": 0.20745284855365753,
                "Height": 0.40392470359802246,
                "Left": 0.15659691393375397,
                "Top": 0.13662809133529663
            },
            "AgeRange": {
                "Low": 25,
                "High": 33
            },
            "Smile": {
                "Value": true,
                "Confidence": 66.76490020751953
            },
            "Eyeglasses": {
                "Value": true,
                "Confidence": 100.0
            },
            "Sunglasses": {
                "Value": true,
                "Confidence": 100.0
            },
            "Gender": {
                "Value": "Female",
                "Confidence": 99.96575927734375
            },
            "Beard": {
                "Value": false,
                "Confidence": 92.73422241210938
            },
            "Mustache": {
                "Value": false,
                "Confidence": 99.97575378417969
            },
            "EyesOpen": {
                "Value": true,
                "Confidence": 98.76766967773438
            },
            "MouthOpen": {
                "Value": true,
                "Confidence": 94.49341583251953
            },
            "Emotions": [
                {
                    "Type": "HAPPY",
                    "Confidence": 96.09375
                },
                /* 省略 */
            ],
            "Landmarks": [
                {
                    "Type": "eyeLeft",
                    "X": 0.23195792734622955,
                    "Y": 0.2863580584526062
                },
                /* 省略 */
            ],
            "Pose": {
                "Roll": -0.843227744102478,
                "Yaw": 17.80661964416504,
                "Pitch": 7.945673942565918
            },
            "Quality": {
                "Brightness": 70.4559097290039,
                "Sharpness": 97.45164489746094
            },
            "Confidence": 99.99922180175781,
            "FaceOccluded": {
                "Value": true,
                "Confidence": 99.97982788085938
            },
            "EyeDirection": {
                "Yaw": 16.69062042236328,
                "Pitch": -6.638859272003174,
                "Confidence": 0.0
            }
        }
    ]
}

検出された顔領域がBoundingBoxとして得られます。

またそれ以外にも様々な要素が分析結果として得られ、AttributesをDEFAULTとするとBoundingBox、Conficence、Pose、Quality、Landmarksが得られます。

Poseは顔の向きの情報、Qualityは顔画像内の明るさ・シャープネス、Landmarksは顔のパーツ位置についての情報です。

今回はAttributesをALLとしてため、すべての分析結果が得られています。

年齢の範囲、髭の有無、視線、サンブラスや眼鏡、目が明いているかどうか、性別、感情など様々な結果が得られます。

また最大100名分の顔画像を分析できるようです。

詳細は以下もご覧ください。

画像中のテキスト検出

画像中のテキストを認識することができます。

サンプルコードとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

with open("./sample_text.jpg", 'rb') as f:

    response = client.detect_text(
        Image={'Bytes': f.read()})

    print(json.dumps(response, indent=4))

以下がレスポンスの抜粋です。

{
    "TextDetections": [
        {
            "DetectedText": "but keep",
            "Type": "LINE",
            "Id": 2,
            "Confidence": 99.92005157470703,
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.2024739533662796,
                    "Height": 0.080078125,
                    "Left": 0.6399739384651184,
                    "Top": 0.5283203125
                },
                "Polygon": [ /* 省略 */ ]
            }
        },
        {
            "DetectedText": "but",
            "Type": "WORD",
            "Id": 6,
            "ParentId": 2,
            "Confidence": 99.85265350341797,
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.080078125,
                    "Height": 0.0625,
                    "Left": 0.6399739384651184,
                    "Top": 0.5283203125
                },
                "Polygon": [ /* 省略 */ ]
            }
        },
        {
            "DetectedText": "keep",
            "Type": "WORD",
            "Id": 7,
            "ParentId": 2,
            "Confidence": 99.9874496459961,
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.107421875,
                    "Height": 0.080078125,
                    "Left": 0.7350260615348816,
                    "Top": 0.5283203125
                },
                "Polygon": [ /* 省略 */ ]
            }
        }
    ]
}

TypeにはLINEとWORDがあり、LINEは2個以上のWORDの集合で必ずしもセンテンスを表すわけではないですが、同じ行に並んでいる単語と見なされた単位になります。

対応言語は以下となっており日本語には対応していないためご注意ください。

Amazon Rekognition is designed to detect words in English, Arabic, Russian, German, French, Italian, Portuguese and Spanish.

詳細は以下もご覧ください。

有名人の認識

有名人の認識ができます。

サンプルコードとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

with open("./jeff.jpg", 'rb') as f:
    response = client.recognize_celebrities(
        Image={'Bytes': f.read()})
    print(json.dumps(response, indent=4))

以下がレスポンスの抜粋です。

{
    "CelebrityFaces": [
        {
            "Urls": [
                "www.wikidata.org/wiki/Q312556",
                "www.imdb.com/name/nm1757263"
            ],
            "Name": "Jeff Bezos",
            "Id": "1SK7cR8M",
            "Face": {
                "BoundingBox": { /* 省略 */ },
                "Confidence": 99.98967742919922,
                "Landmarks": [ /* 省略 */ ],
                "Pose": { /* 省略 */ },
                "Quality": { /* 省略 */ },
                "Emotions": [ /* 省略 */ ],
                "Smile": { /* 省略 */ }
            },
            "MatchConfidence": 99.70896911621094,
            "KnownGender": {
                "Type": "Male"
            }
        }
    ],
    "UnrecognizedFaces": [],
}

検出された有名人の参考情報のURLなども取得されます。

また、顔検出と同じようにPoseやEmotionなども検出結果として出てくるようです(顔検出のALLよりは分析情報が少ないです)。

有名人と認識されなかった顔画像もUnrecognizedFacesに格納され、最大64人分の顔を一度に検出します。

詳細は以下もご覧ください。

個人用防護具 (PPE) 検出

人物を検出し、ヘルメットやグローブなど保護用具の検出ができます。

サンプルコードとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

with open("./sample_ppe.jpg", 'rb') as f:
    response = client.detect_protective_equipment(
        Image={'Bytes': f.read()})

    print(json.dumps(response, indent=4))

以下がレスポンスの抜粋です。

{
    "ProtectiveEquipmentModelVersion": "1.0",
    "Persons": [
        {
            "BodyParts": [
                {
                    "Name": "FACE",
                    "Confidence": 99.9974365234375,
                    "EquipmentDetections": [
                        {
                            "BoundingBox": {
                                "Width": 0.14317916333675385,
                                "Height": 0.15404963493347168,
                                "Left": 0.43585532903671265,
                                "Top": 0.33858799934387207
                            },
                            "Confidence": 99.89533233642578,
                            "Type": "FACE_COVER",
                            "CoversBodyPart": {
                                "Confidence": 98.52064514160156,
                                "Value": true
                            }
                        }
                    ]
                },
                {
                    "Name": "LEFT_HAND",
                    "Confidence": 96.88862609863281,
                    "EquipmentDetections": [ /* 省略 */ ]
                },
                {
                    "Name": "RIGHT_HAND",
                    "Confidence": 99.85781860351562,
                    "EquipmentDetections": [ /* 省略 */ ]
                },
                {
                    "Name": "HEAD",
                    "Confidence": 99.99998474121094,
                    "EquipmentDetections": [ /* 省略 */ ]
                }
            ],
            "BoundingBox": {
                "Width": 0.7484375238418579,
                "Height": 0.9370836615562439,
                "Left": 0.02291666716337204,
                "Top": 0.0444115474820137
            },
            "Confidence": 99.98688507080078,
            "Id": 0
        }
    ]
}

BodyPartsに顔(FACE)、両手(LEFT_HAND、RIGHT_HAND)、頭部(HEAD)に分けた結果が得られています。

BoundingBoxはパーツに対してもありますが、人に対しても検出されるようです。

複数の人物が写っている場合も有効です。

詳細は以下もご覧ください。

画像のプロパティ分析

画像のプロパティとして画像の明るさやシャープネスを分析することができます。

サンプルコードとしては以下のようになります。

import boto3
import json

session = boto3.Session()
client = session.client('rekognition')

with open("./skateboard.jpg", 'rb') as f:

    response = client.detect_labels(
        Image={'Bytes': f.read()},
        Features=['IMAGE_PROPERTIES'])

    print(json.dumps(response, indent=4))

以下がレスポンスの抜粋です。

{
    "Labels": [],
    "LabelModelVersion": "3.0",
    "ImageProperties": {
        "Quality": {
            "Brightness": 63.60965347290039,
            "Sharpness": 78.32762145996094,
            "Contrast": 81.00885009765625
        },
        "DominantColors": [
            {
                "Red": 70,
                "Blue": 180,
                "Green": 130,
                "HexCode": "#4682b4",
                "CSSColor": "steelblue",
                "SimplifiedColor": "blue",
                "PixelPercent": 15.71516227722168
            },
            /* 省略 */
        ],
        "Foreground": {
            "Quality": {
                "Brightness": 57.707061767578125,
                "Sharpness": 85.51693725585938
            },
            "DominantColors": [
                {
                    "Red": 0,
                    "Blue": 0,
                    "Green": 0,
                    "HexCode": "#000000",
                    "CSSColor": "black",
                    "SimplifiedColor": "black",
                    "PixelPercent": 27.027027130126953
                },
                /* 省略 */
            ]
        },
        "Background": {
            "Quality": {
                "Brightness": 63.929100036621094,
                "Sharpness": 77.41754913330078
            },
            "DominantColors": [
                {
                    "Red": 70,
                    "Blue": 180,
                    "Green": 130,
                    "HexCode": "#4682b4",
                    "CSSColor": "steelblue",
                    "SimplifiedColor": "blue",
                    "PixelPercent": 21.483020782470703
                },
                /* 省略 */
            ]
        }
    }
}

全体、background、ForegroundごとにDominantColorsやQualityが得られています(画像ファイルによっては全体だけのケースもありました)。

QualityとしてはContrast、Brightness、Sharpnessが得られ、それ以外にもDominantColorsを得ることができます。

詳細は以下の「Image Properties」の箇所もご覧ください。

料金

以下に記載されています。

ページによると料金は以下のように大きく分けて「Image Analysis」と「Face Metadata Storage」に分かれています。

  • Image Analysis
    • 画像分析に対する料金 (1画像 x 1API処理あたりの料金)
  • Face Metadata Storage
    • 顔画像のベクトルを保存するためのストレージ料金 (顔画像あたりの月額料金)

また「Image Analysis」の中で更に細かく料金が分かれていますが、基本的にはAPI x 画像数の単位で料金が発生します。

顔画像の検索関連だけ、複数のAPIを呼び出す関係でその分の料金が発生するようです。

  • Group 1 : 顔画像のマッチングや顔画像の検索に関するAPI
    • 顔画像のマッチンAグAPI : CompareFaces
    • 顔画像の検索API : IndexFaces, AssociateFaces, DisassociateFaces, SearchFacesbyImage, SearchFaces, SearchUsersByImage, SearchUsers
  • Group 2 : それ以外の分析処理に関するAPI単位の課金
    • ラベル検出API : DetectLabels
    • モデレーション(有害性の検出)API : DetectModerationLabels
    • 顔の検出と分析API : DetectFaces
    • 画像中のテキスト検出API : DetectText
    • 有名人の認識API : RecognizeCelebrities
    • 個人用防護具の検出API : DetectPPE
  • 画像のプロパティ分析API
    • ラベル検出と同じDetectLabelsでIMAGE_PROPERTIESを指定した場合に有効
    • GENERAL_LABELが通常のラベル検出だが、これと同時に指定することも可能(双方の料金が発生)

Group 1とGroup 2はそれぞれで料金が少しだけ異なっていますが、 「Over 35 million images」で差異が出てきますので、多くのデータを処理する際に留意が必要となってきます。

また、画像のプロパティ分析というものだけは独立した料金となっており、Group 1やGroup 2より低い料金で実行できます。

Amazon Rekognition Video

概要

「Amazon Rekognition Video」は動画を対象とした画像分析を行うサービスとなっています。

以下のようなことが可能です。

  • Streaming Video Events : ストリーミングデータ向け
    • 顔画像の検索
  • Stored Video Analysis : 保存されたmp4ファイルなどの動画データ向け
    • 顔画像の検索
    • ラベル検出
    • モデレーション(有害性の検出)
    • 顔の検出と分析
    • 画像中のテキスト検出
    • 有名人の認識
    • 人物の追跡(トラッキング)
  • Media Analysis : 保存されたmp4ファイルなどの動画データ向け
    • 特殊な映像の検出(黒フレームやカラーバーなど)
    • シーン切り替わりの検出

多くは静止画向けの「Amazon Rekognition Image」と共通で以下が動画分析特有の処理です。

  • 人物の追跡(トラッキング)
  • 特殊な映像の検出(黒フレームやカラーバーなど)
  • シーン切り替わりの検出

ストリーミング処理

概要で述べたように、ストリーミングデータと保存された動画ファイルに対応しています。

ストリーミングは顔画像の検索処理のみが対応しており、CreateStreamProcessorのInputとしてKinesis Video Streamを指定することにより処理するようです。

こちらはKinesis Video Stream等の準備が必要となり、今回は内容としては割愛いたします。

動画ファイル処理

ラベル検出を例に、動画ファイル処理するコード例を見てみましょう。

非同期なAPIとなるため、静止画より少し複雑なAPI呼び出しになります。

import boto3
import json
import time

session = boto3.Session()
client = session.client('rekognition')

response = client.start_label_detection(
    Video={
        "S3Object": {
            "Bucket": "{S3バケット名}"
            , "Name": "{オブジェクトキー}"
        }
    }
)

job_id = response["JobId"]
print(f"{job_id=}")

非同期実行となりますので、ジョブの処理待ちが必要です。

NotificationChannelにSNSトピックを指定することで、完了時に通知を行うことも可能なようです。

今回はPythonでwait処理を行い、18秒程度の動画ファイルで結果の取得までに20~40秒程度かかりました。

while True:
    response = client.get_label_detection(
        JobId=job_id
    )
    print(f"{response['JobStatus']=}")

    if response['JobStatus'] == 'IN_PROGRESS':
        print("time.sleep(10)")
        time.sleep(10)
    else:
        break

結果は1000件単位のラベルで得られますので、全件取得するにはNextTokenを使う必要があります。

all_labels = []
next_token = None

while True:
    if next_token is None:
        response = client.get_label_detection(
            JobId=job_id
        )
    else:
        response = client.get_label_detection(
            JobId=job_id
            , NextToken=next_token
        )
    next_token = response.get("NextToken")
    labels = response["Labels"]
    all_labels.extend(labels)

    if next_token is None:
        break

得られる結果の抜粋は以下の通りです。

[
    {
        "Timestamp": 845,
        "Label": {
            "Name": "Accessories",
            "Confidence": 99.78988647460938,
            "Instances": [],
            "Parents": [],
            "Aliases": [
                {
                    "Name": "Accessory"
                }
            ],
            "Categories": [
                {
                    "Name": "Apparel and Accessories"
                }
            ]
        }
    },
    /* 省略 */
]

Timestampはミリ秒単位で、そのTimestampの結果が格納されています。

Timestampは毎フレームというわけでは無いようで845の次は1345となります。ここは動画データに依存して変わってくる可能性がありますが、今回はおおむね500ミリ秒ごとに結果が得られました。

ラベル検出を例にとりましたが、その他の処理毎に以下のようにAPIが準備されています。これらは同様になりますので、今回は割愛します。

動画データ特有の処理についての詳細は以下を参照ください

料金

以下に記載されています。

以下のどの機能も分単位で料金が発生し、それぞれ料金が異なっています。

  • 分析処理
    • Streaming Video Events :ストリーミングデータ向け
    • Stored Video Analysis : 保存されたmp4ファイルなどの動画データ向け
    • Media Analysis : 保存されたmp4ファイルなどの動画データ向け
  • Face Metadata Storage
    • 顔画像のベクトルを保存するためのストレージ料金 (顔画像あたりの月額料金)

Amazon Rekognition Custom Labels

概要

「Amazon Rekognition Custom Labels」はユーザがラベルを準備することで、ある特定のものに特化した画像内のオブジェクトやシーンを識別することができる機能です。

ラベル検出のカスタム版と考えればよいと思います。

データセットの準備方法

マネジメントコンソール等でProjectを作成し、データセットを作成します。

データセットは少なくとも10枚の画像を使用する必要があります。

詳細は以下の記載を参照ください。

データセット作成時に以下の4つから選択することができます。

データセットを手動またはS3経由でアップロードし、Rekognitionのコンソール上でラベリングすることも可能ですが、SageMaker Ground Truth形式のマニフェストファイルがあればimportすることも可能です。

SageMaker Ground Truth形式のマニフェストファイルは、クラス分類の場合、以下のようなJSONを持つJSONLとして準備します。(見やすさのため改行を入れています)

{
    "source-ref": "{s3に置いた画像ファイルのURI}",
    "candy": 1,
    "candy-metadata": {
        "confidence": 1,
        "job-name": "{適当なジョブ名}",
        "class-name": "candy",
        "human-annotated": "yes",
        "creation-date": "2024-03-09T14:46:39",
        "type": "groundtruth/image-classification"
    }
}

candyの部分は各分類クラスに応じて読み替えてください。

また物体検出の場合のマニフェストは、以下のようなJSONを持つJSONLをマニフェストとして準備します。(見やすさのため改行を入れています)

{
    "source-ref": "{s3に置いた画像ファイルのURI}",
    "bounding-box": {
        "annotations": [
            {
                "left": 336,
                "top": 233,
                "width": 293,
                "height": 298,
                "class_id": 2
            },
            /* 省略 */
        ],
        "image_size": [
            {"width": 3024, "depth": 3, "height": 4032}
        ]
    },
    "bounding-box-metadata": {
        "job-name": "{適当なジョブ名}",
        "class-map": {
            "2": "orange",
            "1": "melon-soda"
        },
        "human-annotated": "yes",
        "objects": [
            {"confidence": 1},
            /* 省略 */
        ],
        "creation-date": "2024-03-09T14:46:39",
        "type": "groundtruth/object-detection"
    }
},
/* 省略 */

物体検出で良く使われるCOCO形式を、SageMaker Ground Truthに変換する方法も公式ドキュメントに記載があります。

前段のCOCO形式でデータセットを作るには以下を参照ください。

使用方法

データセットを準備後はモデルを学習(CreateProjectVersion)して、デプロイ(StartProjectVersion)後に、DetectCustomLabelsで検出を行います。

通常のDetectLabelsとはAPIが異なりますのでご注意ください。

詳細は本記事では割愛致しますので、詳しくは以下を参照ください。

料金

以下に記載されています。

モデルの学習と推論にそれぞれ費用が掛かります。

  • Training Hours
    • 実時間ではなくコンピューティングの実行時間で計算
    • トレーニング時間はラベル数や画像数により異なるが、9割のものは24時間未満で完了し、72時間以上かかる場合は自動的に終了される
  • Inference Hours
    • プロビジョニングされたコンピューティングの起動時間で計算
    • バッチ処理をする場合は、プロビジョニング後に処理を行い、リソースを終了する必要がある

特に推論側ですが、何も処理をしない場合でもプロビジョニングされている間(StartProjectVersionからStopProjectVersionまで)は料金が発生するため、注意が必要です。

Amazon Rekognition Custom Moderation

概要

「Amazon Rekognition Custom Moderation」はユーザがデータセットを準備することで、モデレーションをカスタマイズすることができる機能です。

モデレーション(有害性検出)のカスタム版と考えればよいですが、「Amazon Rekognition Custom Labels」とはかなり構成が異なりますのでご注意ください。

構成が異なる点は以下です。

  • 独自のラベルは追加できない
  • APIは通常の(DetectModerationLabels)と共通でよい
  • デフォルトのモデレーションと同時実行できる
    • そのため学習対象をモデルではなくアダプターと呼称する
  • モデルのプロビジョニングが不要

データセットの準備方法

「Amazon Rekognition Custom Labels」と同様にマネジメントコンソール等でProjectを作成し、データセットを作成します。

データセットは少なくとも有害なラベルごとに50枚、または有害ではない画像に対しては20枚のデータを準備する必要があります。

詳細は以下の記載を参照ください。

データセット作成時には以下の4つの方法から選択することができます。

データセットを手動またはS3経由でアップロードし、Rekognitionのコンソール上でラベリングすることも可能ですが、SageMaker Ground Truth形式のマニフェストファイルがあればimportすることも可能です。

ageMaker Ground Truth形式のマニフェストファイルは、以下のようなJSONを持つJSONLとして準備します。(見やすさのため改行を入れています)

{
    "source-ref": "{s3に置いた画像ファイルのURI}",
    "content-moderation-groundtruth":{
        "ModerationLabels":[
            {"Name":"Violence"}
        ]
    }
}

フォーマットの詳細は以下を参照ください。

使用方法

使用方法としてはDetectModerationLabelsの実行時に、アダプターのProjectVersionを指定すれば良いようです。

詳細は本記事では割愛致します。

料金

アダプターの学習と推論にそれぞれ費用が掛かります。

  • Training cost
    • 実時間ではなくコンピューティングの実行時間で計算
    • トレーニング時間はラベル数や画像数により異なるが、9割のアダプタは60分未満のトレーニングで学習が完了
    • トレーニングが自動的に終了してしまった場合は料金は発生しない
  • Inference cost
    • Custom Labelsと異なり、推論した画像の数で料金が発生する

Custom Labelsと異なり、Inference costがプロビジョニング単位ではない点は使いやすい印象を持ちました。

Amazon Rekognition Face Liveness

概要

「Amazon Rekognition Face Liveness」はなりすましを防止するチェック機能で、短い自撮りビデオを分析し、それが撮影された写真や動画、ディープフェイクなどではないかを判定し、本物の人かどうかをチェックすることができます。

使用方法

以下の詳細が記載されていますが、枠内に顔を持ってくる必要があるなど、使用者とのインタラクティブなやりとりを必要としますので、Amplify向けのSDK等が準備されています。

本機能もマネジメントコンソールからトライアルすることができますので、興味があればそちらでお試しされてください。

料金

この機能はチェック1回あたりの料金で費用が発生します。

その他の機能

Bulk Analytsis (バッチ分析)

バッチ分析は、モデレーション(有害性の検出)のみが現在は対応しているようです。

詳細は以下を参照ください。

まとめ

いかがでしたでしょうか。本記事がAmazon Rekognitionをお使いになられる方のご参考になれば幸いです。