この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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 最後に
今回は、撮影と同時にアノテーションを追加してデータセットを作成するツールを作ってみました。 オブジェクト検出では、どうしてもデータセットの準備に手間がかかるため、軽易に試す事ができないのですが、このような仕組みで、ハードルが下がれば、作業も捗るのではないかと考えています。
全てのコードは、下記に置きました。