[Amazon SageMaker] 撮影と同時にアノテーションを追加してAmazon SageMaker Ground Truth形式のデータを作成してみました
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 最後に
今回は、撮影と同時にアノテーションを追加してデータセットを作成するツールを作ってみました。 オブジェクト検出では、どうしてもデータセットの準備に手間がかかるため、軽易に試す事ができないのですが、このような仕組みで、ハードルが下がれば、作業も捗るのではないかと考えています。
全てのコードは、下記に置きました。