[Amazon SageMaker] 撮影と同時にアノテーションを追加してAmazon SageMaker Ground Truth形式のデータを作成してみました

2020.04.20

1 はじめに

CX事業本部の平内(SIN)です。

Amazon SageMaker Ground Truth (以下、Ground Truth)で物体検出(Bounding box)用に作成されたデータセットは、Amazon RekognitionのCustom Labelsや、Amazon SageMaker(以下、Sage Maker)のビルトインオブジェクト検出にそのまま利用できます。

参考:[Amazon SageMaker] Amazon SageMaker Ground Truth で作成したデータを使用してオブジェクト検出でモデルを作成してみました

今回は、このGround Truthで作成されるデータ形式に併せて、写真撮影とアノテーションを一気に行えるようにしてみました。

以前に、RekognitionのCustom Labels用に作成したものと、同等です。

[Amazon Rekognition] Custom Labelsのデータセットを高速に作成するアプリを作ってみました

上記は、データ(画像及び、アノテーション)の保管をS3にしたため、若干、操作が重たくなってしまったのと、OpenCV.JSが、メモリ周りでちょっと使いづらかったので、今回は、ローカル保存でPython版となっています。

最初に、使用している様子です。

矩形の検出は、OpenCVで2値化した画像を元に作成していますが、状況に併せてその閾値を調整できます。また、対象物によっては、背景(明暗)を変えた方が検出しやすいようです。 ラベルは、テキストで指定され、撮影と同時にアノテーション情報として保存されます。

2 コード

メインの処理は、下記の通りです。

OpenCVでWebカメラの画像を読み取り、各クラスで、それぞれ処理しています。

  • 撮影クラス(Shoot) モニター表示(アノテーション含む)する
  • アノテーションクラス(Annotation) 画像から矩形を検出する
  • マニフェストクラス(Manifest)output.manifestを生成する
  • コントロールクラス(controller) 矩形検出のためのしきい値等を設定する

モニター画面のシャッターをクリックすると、その時点の矩形と画像を保存するようになっています。

import cv2
import time

import shoot as sh
import annotation as an
import controller as cn
import manifest as ma

# 設定
outputPath = "/xxxxx/VoTT-DataSet/tmp0"
s3Path = "s3://my-bucket/MyProject"
projectName = "MyProject"

def main():

# カメラ初期化
deviceId = 3 # Webカメラ
height = 600
width = 800
cap = cv2.VideoCapture(deviceId)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)

fps = cap.get(cv2.CAP_PROP_FPS)
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
print("FPS:{} WIDTH:{} HEIGHT:{}".format(fps, width, height))

# アノテーションクラス初期化
scale = 0.5
annotation = an.Annotation(width, height, fps, scale)

# コントロールクラス初期化
threshold = 120 # 2値化の敷居値
only_one = 1 # 1件だけ検出する
margin = 0 # 余白
inversion = 0 # 白黒反転
controller = cn.Controller(threshold, only_one, margin, inversion)

# マニフェストクラス初期化
manifest = ma.Manifest(outputPath, width, height, s3Path, projectName)

# 撮影クラス初期化
shoot = sh.Shoot(width, height)

while True:

# カメラ画像取得
ret, frame = cap.read()
if(frame is None):
continue

# ラベル読み込み
with open('./label.txt') as f:
label = f.read()

if(shoot.Shutter()):
# 画面をグレーにする
shoot.dispGray(frame.copy())
# 名前作成
fileName = "{}-{}".format(label, int(time.time() * 1000000))
# 画像保存
cv2.imwrite("{}/{}.jpg".format(outputPath, fileName), frame)
# アノテーション保存
manifest.save("{}.jpg".format(fileName), annotation.rectangles, label)
time.sleep(0.5)
print("saved")

# コントローラ表示
controller.disp()
# アノテーション取得
annotation.detection(frame.copy(), controller)
# モニター表示
shoot.disp(frame.copy(), annotation.rectangles, label)

cv2.waitKey(1)

cap.release()
cv2.destroyAllWindows()

main()

3 画面構成

画面の構成は、以下の3つであり、それぞれの役割は下記の通りです。

  • モニター画面(撮影用のモニター、シャッター、検出された矩形の表示)
  • 2値化処理画面(矩形検出のための処理画面、コントロールの設定を確認)
  • コントロール画面(2値化のためのパラメータ設定)

4 コントロール

コントロール画面では、以下の設定が可能です。

  • inversion 白黒反転 (ON/OFF)
  • only_one 最大の矩形を1つだけ検出する(ON/OFF)
  • margin 矩形のマージン(0〜10)
  • threshold 2値化のしきい値(0-255)

5 最後に

今回は、撮影と同時にアノテーションを追加してデータセットを作成するツールを作ってみました。 オブジェクト検出では、どうしてもデータセットの準備に手間がかかるため、軽易に試す事ができないのですが、このような仕組みで、ハードルが下がれば、作業も捗るのではないかと考えています。

全てのコードは、下記に置きました。

https://github.com/furuya02/AutoAnnotation