Amazon Rekognitionを導入してみた

新興メディアシステム1部でチームルームの担当をしている中川です!

チームルームは地域コミュニティやクラブ活動など、チーム活動を支援するサービスです。 掲示板でのメンバー同士のやり取りやアルバム機能によるクラブ活動写真のシェアなどの機能があります。

今回はアルバムにアップロードされる不適切なコンテンツの自動検知のためにAmazon Rekognitionを導入しましたので、簡単な機能説明と利用方法について紹介しようと思います。

導入の経緯

チームルームは利用規約として猥褻・グロテスクといった不適切なコンテンツの投稿は禁止となっており、健全なサービス維持のためCS担当者によって投稿されたメディアの監視を行っております。
サービス開始当初はCS担当者に目視で確認・判断していただいておりましたが、サービスを続けている中で課題が浮上したため、導入に至りました。

監視担当者への健康被害

不適切なコンテンツは1枚見るだけでも精神的に辛いものがあります。 そういったコンテンツに何時間も晒され続けたり、普通の画像のリストに突然不適切なコンテンツが現れてしまう環境は担当していただいてる方の健康に大きく影響してきます。 AIによる監視のワンクッションを入れることで、AIでわかるレベルの不適切コンテンツはAIに任せ、少しでもストレスを軽減することができると判断しました。

Amazon Rekognitionとは

AWS - Amazon Rekognition
機械学習によって画像や動画から様々な情報を読み取ることができるサービスです。AWSのサービスの一つとして提供されています。
読み取れる情報としては人物・オブジェクト・テキスト・利用者が指定したパターンなど、ほぼなんでも読み取れます。
利用方法としても基本はメディアを読み込ませれば結果が返ってくるだけで、機械学習や事前準備も特に不要です。

チームルームでは不適切なコンテンツの検出(Content Moderation)を利用しました。 不適切な要素のパラメータとしては下記のようなjson形式のレスポンスとなり、どういう属性がどのくらいの一致度合いかという情報が返されます。
Amazon Rekognition - コンテンツの節度

{
    "ModerationLabels": [ 
        {
            "Confidence": 99.43121337890625, // このカテゴリである信頼度 
            "Name": "Revealing Clothes",     // 第2レベルカテゴリ - 露出の多い服
            "ParentName": "Suggestive"       // 最上位カテゴリ - 暗示的
        },
        {
            "Confidence": 99.43121337890625, // 最上位カテゴリでの最大信頼度
            "Name": "Suggestive",
            "ParentName": "" 
        }
    ],

    ...
}

動画のモデレーションの場合は何秒時点にどういう属性があったかというようにレスポンスのフォーマットが少し違うため、画像と同列に処理するには少し整形が必要です。

{
    ...,

    "ModerationLabels": [
        {
            "Timestamp": 500,
            "ModerationLabel": {
                "Confidence": 77.4461441040039,
                "Name": "Explicit Nudity",
                "ParentName": ""
            }
        },
        {
            "Timestamp": 500,
            "ModerationLabel": {
                "Confidence": 77.4461441040039,
                "Name": "Sexual Activity",
                "ParentName": "Explicit Nudity"
            }
        },
        {
            "Timestamp": 1500,
            "ModerationLabel": {
                "Confidence": 80.55899810791016,
                "Name": "Explicit Nudity",
                "ParentName": ""
            }
        },
        {
            "Timestamp": 1500,
            "ModerationLabel": {
                "Confidence": 80.55899810791016,
                "Name": "Sexual Activity",
                "ParentName": "Explicit Nudity"
            }
        },
        {
            "Timestamp": 2000,
            "ModerationLabel": {
                "Confidence": 80.58533477783203,
                "Name": "Explicit Nudity",
                "ParentName": ""
            }
        },
        {
            "Timestamp": 2000,
            "ModerationLabel": {
                "Confidence": 80.58533477783203,
                "Name": "Sexual Activity",
                "ParentName": "Explicit Nudity"
            }
        }
    ],
    ...
}

全体構成

チームルームはサービス自体は自社サーバーで稼働しており、 ユーザーがアップロードしたメディアはAWS S3へ保管する構成となっています。
Amazon Rekognitionはモデレーションの実行にS3オブジェクトが必要なため、 S3へのアップロードをイベントのトリガーに設定し、Rekognitionを実行する構成としました。

画像のRekognition (DetectModerationLabels)

AWS - DetectModerationLabels
画像のモデレーションについては即時で結果を取得できるため、Lambda内にて処理が完結しています。

import boto3

...

# モデレーション実行(即時レスポンス)
rekognition = boto3.client('rekognition')
response = rekognition.detect_moderation_labels(Image={"S3Object": {"Bucket": bucket, "Name": name}})

# SQSへ結果を送信
sqs = boto3.client('sqs')
send_response = sqs.send_message(
    MessageBody = json.dumps(response),
    QueueUrl = sqs_url,
    DelaySeconds = 0
)

動画のRekognition(StartContentModeration)

AWS - StartContentModeration
動画のRekognitionについては処理に時間がかかるため処理が完了したタイミングでRekognition側からAmazon SNSへ通知してくれる機能があります。
そのため、動画のRekognitionは処理を開始したのち、Amazon SNSでの通知をトリガーとして処理結果を取得するLambdaを実装しました。
また、レスポンスのフォーマットとしても画像と違いタイムスタンプごとにモデレーション結果が格納されています。
結果の処理は画像のRekognitionと共通のため、画像のRekognitionのフォーマットに合わせています。

import boto3

...

# Rekognition Videoの処理依頼
rekognition = boto3.client('rekognition')
response = rekognition.start_content_moderation(
    Video={
        "S3Object": {"Bucket": bucket, "Name": name}
    },
    NotificationChannel={
        "SNSTopicArn": sns_topic_arn,
        "RoleArn": role_arn
        },
    JobTag = media_id
)
import boto3
rekognition = boto3.client('rekognition')

...

# SNSからのメッセージからモデレーション実行情報を抽出
message_json = json.loads(event['Records'][0]['Sns']['Message'])
job_id = message_json["JobId"]
media_id = message_json["JobTag"]

# 受信したJobIdからモデレーションの結果を取得
rekognition_result_response = rekognition.get_content_moderation(JobId=job_id)

# RekognitionImageと共通のSQSで送信し処理させるために、RekognitionVideoの結果をRekognitionImageの結果と合わせる
format_moderation_labels = [];
for moderation_label in rekognition_result_response['ModerationLabels']:
    format_moderation_labels.append(moderation_label['ModerationLabel'])

# MediaId: DB上でのレコードを特定するためのId
format_rekognition_result_response = {'ModerationLabels': format_moderation_labels, 'MediaId': media_id}

# SQSへ結果を送信
send_sqs_message(sqs_url, json.dumps(format_rekognition_result_response))

結果の受け取り

AWS上で処理された結果を自社サーバーのDBへ反映させるための方法としてはAmazon SQSを利用しています。
結果をSQSに格納し、サービス側のバッチ処理により一定間隔でSQSからメッセージを取得することでDBへの反映をしています。
Rekognition側で閾値の設定なども可能ですがサービス側で閾値の設定は管理したかったので、レスポンス自体に閾値は設けず、受け取った結果をもとにサービス側の閾値による処理の分岐を実装しています。

今後の改善

Rekognitionを導入したことで不適切なコンテンツは半自動で判定され、 監視担当者への精神的なストレスを下げることに貢献できました。
数ヶ月前にはRekognitionのバージョンアップもされ、誤検知もかなり減ってきております。
Amazon Rekognition で画像と動画に対するコンテンツモデレーションの精度が向上

しかし、チームルームでは導入を最優先として細かなチューニングがまだできていないため、改善点としては多く残っています。

・動画Rekognitionの費用削減
 →倍速動画でのモデレーションや開始数秒での判定
・特殊な不適切コンテンツの摘出
 →カスタムラベルによる抽出など追加学習

こうした改善案を取り入れた際には、またブログにてご紹介できればと思っています。

カカクコムでは共にサービスをつくる仲間を募集しています

カカクコムのエンジニアリングにご興味のある方は、是非こちらをご覧ください!

カカクコム採用サイト