2
1

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.

Splunkで画像解析データを分析(Amazon Rekognition連携)

Last updated at Posted at 2021-04-03

はじめに

Splunkでデータ集約、分析する中で、画像や動画データも対象にしたいという場合のお話です。
※例えばコミュニティサイトを運用している場合に変な画像をアップロードされていないかとか、ビジネス分析用途で、インスタグラムとかで自社の製品とかサービスに関連する画像でどんなものがアップされてるかとか

残念ながらSplunk自身では画像、動画データを取り込むことはできません。
じゃあ他の偉大なサービスの力を借りて実現しようということで、AmazonのRekognitionで解析して解析データを取り込んでみましたのでメモです。

Amazon Rekognitionとは

公式からコピペ。

Amazon Rekognition を使用すると、画像と動画の物体、人物、テキスト、シーン、活動を特定し、不適切なコンテンツを検出できます。
Amazon Rekognition は、非常に正確な顔分析および顔検索機能も備えています。これを使用して、さまざまなユーザー検証、人数のカウント、および公共安全のユースケースで顔を検出、分析、比較できます。

面白そうな関数はこの辺りです。恐ろしい時代です。

環境

  • Splunk Enterprise (HEC使うのでAWS上にあるもの) or Splunk Cloud
  • AWS Lambda
  • Amazon S3
  • Amazon Rekognition

こんなフローです。
S3へのアップロードをトリガーにLambdaを起動し、S3の情報をLambdaからRekognitionに渡して画像解析、結果をSplunkのHECに送信します。

image.png

それじゃやっていきましょう。

事前準備

IAMの設定

LambdaからS3、RekognitionにアクセスするためのIAMロールを作成します。
ユースケースはLambdaを選択します。
ポリシーで必要なのは以下です。

  • AmazonS3ReadOnlyAccess
  • AmazonRekognitionFullAccess
  • AWSLambdaBasicExecutionRole ※CloudWatchへのログ出力

image.png

S3 Bucketの準備

画像アップロードするS3 Bucketも作っておきましょう。
既存のものがあればそれでも結構です。

テスト用の画像をアップロードしておきます。
「情報量の多い画像」で有名なミシン紳士をお借りしますね。
test_image.jpg

Rekognitionのデータを取り込んでみよう

Lambda関数の作成

Lambdaの関数を作成します。
「一から作成」でランタイムはPython、実行ロールは先ほど作ったロールを選択します。

image.png

画像データが大きい場合に時間を要する場合があります。
関数作成後、設定 > 一般設定からタイムアウト値を増やしておきます。
※デフォルト3秒から10秒に変更しておきました

image.png

Rekognitionで解析

さて、Pythonのスクリプト作っていきましょう。
とは言ってもめちゃ簡単です。

画像に何が含まれているかを抽出してくれるDetectLabelsで試します。

lambda_function.py
import json
import boto3

def lambda_handler(event, context):
    
    bucket = "symmr.rekognition" # S3 Bucket名
    key = "test_image.jpg" # 画像ファイル名
    
    client = boto3.client("rekognition")
    response = client.detect_labels(Image = {"S3Object": {"Bucket": bucket, "Name": key}}, MaxLabels=20, MinConfidence=70)
    
    print(response)
    
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

boto3を使い、S3からデータ取得する場合はdetect_labelsにS3の情報とMaxLabelsで取得ラベル数(デフォルト無制限)、MinConfidenceで最小confidence(デフォルト55%)を指定するだけです。

APIリファレンスはこちら
※S3ではなく画像データを直接解析する場合はImage.Bytesにbase64にエンコードしたデータをセットすればOKです

ではテストしてみましょう。

テスト結果
{
  "statusCode": 200,
  "body": "\"Hello from Lambda!\""
}

Function Logs
START RequestId: cf212be4-c922-41b8-ab91-7c90c3a285ec Version: $LATEST
{'Labels': [{'Name': 'Person', 'Confidence': 99.77276611328125, 'Instances': [{'BoundingBox': {'Width': 0.07846866548061371, 'Height': 0.3057587146759033, 'Left': 0.13179878890514374, 'Top': 0.15125896036624908}, 'Confidence': 99.77276611328125}, {'BoundingBox': {'Width': 0.0827648788690567, 'Height': 0.20582953095436096, 'Left': 0.25745800137519836, 'Top': 0.1811434030532837}, 'Confidence': 99.7685546875}, {'BoundingBox': {'Width': 0.06163841113448143, 'Height': 0.2630268633365631, 'Left': 0.07908330857753754, 'Top': 0.16579791903495789}, 'Confidence': 99.69869995117188}, {'BoundingBox': {'Width': 0.042920779436826706, 'Height': 0.26353126764297485, 'Left': 0.18419542908668518, 'Top': 0.15169677138328552}, 'Confidence': 99.55378723144531}], 'Parents': []}, {'Name': 'Human', 'Confidence': 99.77276611328125, 'Instances': [], 'Parents': []}, {'Name': 'Suit', 'Confidence': 99.72770690917969, 'Instances': [], 'Parents': [{'Name': 'Overcoat'}, {'Name': 'Coat'}, {'Name': 'Clothing'}]}, {'Name': 'Clothing', 'Confidence': 99.72770690917969, 'Instances': [], 'Parents': []}, {'Name': 'Overcoat', 'Confidence': 99.72770690917969, 'Instances': [], 'Parents': [{'Name': 'Coat'}, {'Name': 'Clothing'}]}, {'Name': 'Coat', 'Confidence': 99.72770690917969, 'Instances': [], 'Parents': [{'Name': 'Clothing'}]}, {'Name': 'Apparel', 'Confidence': 99.72770690917969, 'Instances': [], 'Parents': []}, {'Name': 'Tuxedo', 'Confidence': 98.28694152832031, 'Instances': [], 'Parents': [{'Name': 'Suit'}, {'Name': 'Overcoat'}, {'Name': 'Coat'}, {'Name': 'Clothing'}]}, {'Name': 'Bush', 'Confidence': 88.96171569824219, 'Instances': [], 'Parents': [{'Name': 'Vegetation'}, {'Name': 'Plant'}]}, {'Name': 'Plant', 'Confidence': 88.96171569824219, 'Instances': [], 'Parents': []}, {'Name': 'Vegetation', 'Confidence': 88.96171569824219, 'Instances': [], 'Parents': [{'Name': 'Plant'}]}, {'Name': 'Blazer', 'Confidence': 71.90851593017578, 'Instances': [], 'Parents': [{'Name': 'Jacket'}, {'Name': 'Coat'}, {'Name': 'Clothing'}]}, {'Name': 'Jacket', 'Confidence': 71.90851593017578, 'Instances': [], 'Parents': [{'Name': 'Coat'}, {'Name': 'Clothing'}]}, {'Name': 'Housing', 'Confidence': 70.93521881103516, 'Instances': [], 'Parents': [{'Name': 'Building'}]}, {'Name': 'Building', 'Confidence': 70.93521881103516, 'Instances': [], 'Parents': []}], 'LabelModelVersion': '2.0', 'ResponseMetadata': {'RequestId': '786baec7-a946-4391-b728-4288d53a96e0', 'HTTPStatusCode': 200, 'HTTPHeaders': {'content-type': 'application/x-amz-json-1.1', 'date': 'Sat, 03 Apr 2021 14:43:01 GMT', 'x-amzn-requestid': '786baec7-a946-4391-b728-4288d53a96e0', 'content-length': '2166', 'connection': 'keep-alive'}, 'RetryAttempts': 0}}
END RequestId: cf212be4-c922-41b8-ab91-7c90c3a285ec
REPORT RequestId: cf212be4-c922-41b8-ab91-7c90c3a285ec	Duration: 1706.71 ms	Billed Duration: 1707 ms	Memory Size: 128 MB	Max Memory Used: 73 MB	Init Duration: 255.29 ms

Request ID
cf212be4-c922-41b8-ab91-7c90c3a285ec

Labelsに取得したラベルが入ってきます。ちょっと見にくいので抽出すると

ラベルと自信度
Name, Confidence
Person, 99.77276611328125
Human, 99.77276611328125
Suit, 99.72770690917969
Clothing, 99.72770690917969
Overcoat, 99.72770690917969
Coat, 99.72770690917969
Apparel, 99.72770690917969
Tuxedo, 98.28694152832031
Bush, 88.96171569824219
Plant, 88.96171569824219
Vegetation, 88.96171569824219
Blazer, 71.90851593017578
Jacket, 71.90851593017578
Housing, 70.93521881103516
Building, 70.93521881103516

すげぇや。
ちょっと違うかな?と思ったラベルについてはConfidenceもしっかり低めに出ています。
他にもそれぞれのラベルの親子関係や、対する画像内の位置情報も含まれています。

SplunkのHECに送信してみる

この結果をSplunkに送信しましょう。
準備など詳細は以下をご参照ください。
AWS LambdaでRESTでデータ取得してSplunkに送信してみる (Python編)

それで、できたスクリプトがこちらです。
※HECのパラメータはSPLUNK_HEC_TOKENSPLUNK_HEC_URLで環境変数化しています
※エラー処理は省いています

lambda_function.py
from splunk_http_event_collector import http_event_collector
import json
import boto3
import os
import logging
import sys

def lambda_handler(event, context):
    
    targetBucket = "symmr.rekognition"
    targetKey = "test_image.jpg"
    
    client = boto3.client("rekognition")
    response = client.detect_labels(Image = {"S3Object": {"Bucket": targetBucket, "Name": targetKey}}, MaxLabels=20, MinConfidence=70)
    
    print(response)
    
    # init logging config, this would be job of your main code using this class.
    logging.basicConfig(format='%(asctime)s %(name)s %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S %z')
    
    # Create event collector object, default SSL and HTTP Event Collector Port
    http_event_collector_key = os.environ["SPLUNK_HEC_TOKEN"]
    http_event_collector_host = os.environ["SPLUNK_HEC_URL"]
    
    event_to_send = http_event_collector(http_event_collector_key, http_event_collector_host)

    # perform a HEC reachable check
    hec_reachable = event_to_send.check_connectivity()
    if not hec_reachable:
        sys.exit(1)
    
    # Set to pop null fields.  Always a good idea
    event_to_send.popNullFields = True
    # set logging to DEBUG for example
    event_to_send.log.setLevel(logging.DEBUG)
    
    # Start event payload and add the metadata information
    payload = {}
    payload.update({"index":"aws_lambda"})
    payload.update({"sourcetype":"rekognition"})
    payload.update({"source":context.function_name})
    payload.update({"host":"lambda"})
    
    payload.update({"event":response})
    event_to_send.sendEvent(payload)
    
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

テストして、Splunkで見てみましょう。

image.png

やったね!

S3へのファイルアップロードをトリガーに設定

Rekognition→Splunk送信がうまくいったので、次はS3にファイルアップロードされたらLambdaが自動実行されるようにしましょう。

[トリガーを追加] で...

image.png

S3 Bucketを選択してトリガー作成します。

image.png

コードも若干修正します。
S3からのトリガー時には、対象のファイル情報はeventに入ってきます。BucketとKey情報を渡すようにします。
S3通知イベントの詳細はこちら

lambda_function.py
from splunk_http_event_collector import http_event_collector
import json
import boto3
import os
import logging
import sys

def lambda_handler(event, context):

    # アップロードされたファイル情報
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key']
    
    client = boto3.client("rekognition")
    response = client.detect_labels(Image = {"S3Object": {"Bucket": bucket, "Name": key}}, MaxLabels=20, MinConfidence=70)
    
    # 解析結果にファイル情報を結合
    response.update(event)
    
    print(response)
    
    # init logging config, this would be job of your main code using this class.
    logging.basicConfig(format='%(asctime)s %(name)s %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S %z')
    
    # Create event collector object, default SSL and HTTP Event Collector Port
    http_event_collector_key = os.environ["SPLUNK_HEC_TOKEN"]
    http_event_collector_host = os.environ["SPLUNK_HEC_URL"]
    
    event_to_send = http_event_collector(http_event_collector_key, http_event_collector_host)

    # perform a HEC reachable check
    hec_reachable = event_to_send.check_connectivity()
    if not hec_reachable:
        sys.exit(1)
    
    # Set to pop null fields.  Always a good idea
    event_to_send.popNullFields = True
    # set logging to DEBUG for example
    event_to_send.log.setLevel(logging.DEBUG)
    
    # Start event payload and add the metadata information
    payload = {}
    payload.update({"index":"aws_lambda"})
    payload.update({"sourcetype":"rekognition"})
    payload.update({"source":context.function_name})
    payload.update({"host":"lambda"})
    
    payload.update({"event":response})
    event_to_send.sendEvent(payload)
    
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

今度は写真じゃなくて絵をS3にアップしてみます。
image.png

すると自動でLambdaが動作して...

image.png

おk

どんどんアップロードしてみる

解析してみたい画像をどんどんアップロードしましょう。
※課金に注意

Splunkで分析

とりあえず扱いやすいように整形。

SPL
index=aws_lambda sourcetype=rekognition
| rename Labels{}.Name as label
| table _time, label, Records{}.s3.object.key
| mvexpand label

後はいかようにでも。

image.png

image.png

まとめ

Amazon Rekognitionを使い解析した画像(動画も)の結果をSplunkでお手軽に分析できるようになりました。
色々なサービスと組み合わせると面白いことができますね。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?