Amazon Web Services ブログ

Amazon SageMaker Ground Truth での 3D オブジェクトトラッキングとセンサーフュージョンのデータのラベル付け



Amazon SageMaker Ground Truth は、3D ポイントクラウドデータのラベル付けをサポートするようになりました。リリースされた機能セットの詳細については、この AWS ニュースブログの記事を参照してください。 このブログ記事では、3D ポイントクラウドデータから必要なデータ変換を実行して、SageMaker Ground Truth で 3D オブジェクト追跡ユースケースのラベル付けジョブを作成する方法を具体的に説明します。

自律型運転車 (AV) 企業は通常、LiDAR センサーを使用して、車両周辺環境の 3D についての理解度を高めます。たとえば、LiDAR センサーを車両に取り付けて、特定の時点で周囲の 3D 環境スナップショットを継続的にキャプチャします。LiDAR センサーの出力は、一連の 3D ポイントクラウドフレームです (通常、キャプチャレートは 1 秒あたり 10 です)。車両の周囲から関心のあるオブジェクト (他の車両や歩行者など) を自動的に追跡できる知覚システムを構築するために、これらの企業は、最初に 3D ポイントクラウドフレーム内のオブジェクトに手動でラベルを付け、次にラベル付けされた 3D フレームを使用して機械学習 (ML) モデルをトレーニングします。

知覚システムの構築に関しては、複数のセンサーからの入力を使用して、個々のセンサーの欠点を軽減するのが一般的な方法です。たとえば、ビデオカメラは、信号が赤、黄、緑のいずれであるかなどの重要なコンテキスト情報を提供できますが、通常、暗い状況では知覚が制限されます。一方、LiDAR センサーは、交通信号の色のような特定のコンテキストを理解することはできませんが、外が明るいか暗いかに関係なく、360 度にわたって深度ある知覚を提供できます。

SageMaker Ground Truth は、ML トレーニングデータセットを構築するための一連の 3D ポイントクラウドフレームにわたってオブジェクトに簡単にラベルを付け、最大 8 台のビデオカメラ入力を備えた LiDAR データのセンサーフュージョンをサポートします。ビデオフレームと 3D ポイントクラウドフレームの事前同期が必要です。有効にすると、人間のラベル付け作業者は、同期されたビデオフレームと 3D ポイントクラウドフレームを並べて表示できます。ラベル付けの視覚的コンテキストを提供することに加えて、センサーフュージョン機能は、3D ポイントクラウドで描写されたラベルをビデオフレームに投影し、片方のフレームで行われたラベル調整がもう一方の方で表示されます。

この記事では、SageMaker Ground Truth が使用する 3D ポイントクラウドデータと同期された動画データを準備する方法を示します。まず、人気のある AV データセットである KITTI Vision Benchmark Suite から始めます。[1] ビデオデータに加え、Velodyne LiDAR センサーを使用して生成された 3D ポイントクラウドデータが含まれます。具体的には、次の手順について説明します。

  • Ground Truth 3D ポイントクラウドラベル付けジョブの入力データ形式と要件について話し合います。
  • KITTI データセットをローカル座標系からワールド座標系に変換します。
  • センサーフュージョン用に同期されたビデオデータを LiDAR データに関連付ける
  • SageMaker Ground Truth 入力マニフェストファイルを用意します。
  • 3D ポイントクラウドオブジェクトを検出し、一連のフレームにわたって追跡するためのラベル付けジョブを作成します。
  • 作業者ラベル付け UI のラベル付け支援ツールを使用します。

このチュートリアルを完了するには、ノートブックインスタンスの [Amazon SageMaker の例] タブの [Ground Truth ラベル付けジョブ] にあるノートブックの 3D-point-cloud-input-data-processing.ipynb を使用します。ノートブックは GitHub にもあります

3D ポイントクラウドラベル付けジョブの入力データ

このセクションでは、3D ポイントクラウドラベル付けジョブの Ground Truth 入力データの概念と要件の概要について説明します。

3D ポイントクラウドフレームと 3D ポイントクラウドシーケンス

ポイントクラウドフレームは、3D シーンを表す 3D ポイントのコレクションとして定義されます。各ポイントは、x、y、z の 3 つの座標を使用して記述されます。ポイントクラウドに色とポイント強度のバリエーションを追加するために、ポイントには、強度の i や赤 (r)、緑 (g)、青 (b) のカラーチャネル (8 ビット) の値などの追加属性がある場合があります。すべての位置座標 (x、y、z) はメートル単位です。Ground Truth 3D ポイントクラウドラベル付けジョブを作成する場合、ポイントクラウドデータを ASCII またはコンパクトなバイナリ形式で使用できます。

シーケンスは、LiDAR が移動中 (車の中など) にキャプチャされた 3D ポイントクラウドフレームの時系列として定義されます。SageMaker Ground Truth は、シーケンスファイル形式をフレームで順序付けられたシーケンスとして定義します。各フレームはタイムスタンプに関連付けられています。

この記事では、3D オブジェクト追跡のラベル付けジョブを作成する準備として、KITTI データセットから SageMaker Ground Truth シーケンスファイルを作成する方法を示します。

ワールド座標系

オブジェクト追跡では、基準ポイント (自律型車両) が移動している間のオブジェクト (歩道の歩行者など) の動きを追跡します。基準点には、周囲の環境を感知するために取り付けられたセンサーが付いてあり、通常、エゴ車両と呼ばれます。

エゴ車両自体が世界中を移動しているため、オブジェクト追跡を実行するときは、ワールド座標系 (別名基準点のグローバルフレーム) を使用する必要があります。一般的に、SageMaker Ground Truth は、ポイントクラウドデータをすでに選択した基準座標系に変換していると想定しています。通常、このような変換は、3D フレームの各ポイントに LiDAR センサーの外部行列を乗算することで行います。センサーの外部行列は、データの視点をセンサーの座標系からワールド座標系に変換するために使用される同次変換行列です。同次変換は、3 つの回転シーケンス (x、y、z 軸) と、原点の平行移動です。具体的には、回転行列が 3 つの回転のシーケンスを定義する 3×3 行列です。

この記事では、外部行列を使用して、KITTI 3D フレームをローカル座標系からワールド座標系に変換する方法について説明します。KITTI データセットは、各 3D ポイントクラウドフレームの外部行列を提供します。エゴ車両からの GPS データを使用して、独立して外部行列を作成できます。NumPy 行列乗算関数を使用してこの行列にフレーム内の各ポイントを乗算し、そのポイントを KITTI データセットが使用するワールド座標系に変換します。

独自の設定を使用すれば、エゴ車両の LiDAR センサーに対する GPS/IMU の位置と方向 (緯度/経度/高度/回転/速度/向き) を使用して、外部変換行列を個別に計算することもできます。たとえば、pose = convertOxtsToPose (oxts) を使用して KITTI 生データからポーズを計算し、oxts データを 4×4 剛体変換行列で指定されたローカルユークリッドポーズに変換できます。次に、ワールド座標系の基準フレーム変換行列を使用して、このポーズ変換行列をグローバル基準フレームに変換できます。

センサーフュージョン

LiDAR センサーと各カメラには独自の外部行列があり、SageMaker Ground Truth はその行列を使用してセンサーフュージョン機能を有効にします。3D ポイントクラウドからカメラのイメージプレーンにラベルを投影するには、SageMaker Ground Truth が 3D ポイントを LiDAR 座標系からカメラ座標系に変換する必要があります。これは通常、最初に LiDAR の外部行列を使用して、LiDAR の座標からワールド座標系に 3D ポイントを変換することによって行われます。次に、カメラの逆外部 (ワールドからカメラへ) を使用して、前のステップでワールド座標系から取得した 3D ポイントをカメラ画像平面に変換します。3D ポイントクラウドデータがすでにワールド座標系に変換されている場合、最初の変換は不要であり、3D と 2D の間の変換はカメラの外部行列のみによって決まります。

単一の外部変換行列の代わりに、ワールド座標系に回転行列 (軸の回転で構成される) と並進ベクトル (または原点) がある場合、回転と並進を直接使用してポーズを計算できます。次のコードを参照してください。

rotation = [[ 9.96714314e-01, -8.09890350e-02,  1.16333982e-03],
[ 8.09967396e-02,  9.96661051e-01, -1.03090934e-02],
[-3.24531964e-04,  1.03694477e-02,  9.99946183e-01]]
 
 origin= [1.71104606e+00
          5.80000039e-01
          9.43144935e-01]
         
from scipy.spatial.transform import Rotation as R
# 位置は原点です
position = origin 
r = R.from_matrix(np.asarray(rotation))
# scipy を使用した WCS の見出し 
heading = r.as_quat()

4×4 の外部行列がある場合、行列は [R T; 0 0 0 1] の形式になります。ここで、R は回転行列で、T は原点移動ベクトルです。つまり、次のように行列から回転行列と並進ベクトルを抽出できます。

import numpy as np

transformation 
= [[ 9.96714314e-01, -8.09890350e-02,  1.16333982e-03, 1.71104606e+00],
   [ 8.09967396e-02,  9.96661051e-01, -1.03090934e-02, 5.80000039e-01],
   [-3.24531964e-04,  1.03694477e-02,  9.99946183e-01, 9.43144935e-01],
   [              0,               0,               0,              1]]

transformation  = np.array(transformation )
rotation = transformation[0:3][0:3]
translation= transformation[0:3][3]

from scipy.spatial.transform import Rotation as R
# 位置は原点の並進です
position = translation
r = R.from_matrix(np.asarray(rotation))
# scipy を使用した WCS の見出し 
heading = r.as_quat()
print(f"position:{position}\nheading: {heading}")

センサーフュージョンの場合は、原点の位置 (並進の場合) およびクオータニオンの向き (3 軸の回転の場合) に関して、センサーポーズの形式で外部行列を提供します。次のコードは、入力マニフェストファイルで使用するポーズ JSON の例です。

{
    "position": {
        "y": -152.77584902657554,
        "x": 311.21505956090624,
        "z": -10.854137529636024
      },
      "heading": {
        "qy": -0.7046155108831117,
        "qx": 0.034278837280808494,
        "qz": 0.7070617895701465,
        "qw": -0.04904659893885366
      }
}

すべての位置座標 (x、y、z) はメートル単位です。すべてのポーズの見出し (qx、qy、qz、qw) は、空間方向で四元数で測定されます。カメラごとに、そのカメラの外部から抽出されたポーズデータを提供します。

カメラのキャリブレーション、組み込み、および歪曲

幾何学的カメラキャリブレーション (別名カメラリセクション) は、画像またはビデオカメラのレンズとイメージセンサーのパラメータを推定します。これらのパラメータを使用して、レンズの歪曲を修正したり、オブジェクトのサイズをワールド単位で測定したり、シーン内のカメラの位置を決定したりできます。さらに、カメラの画像が歪んでいる場合は、追加のキャリブレーションパラメータ (組み込みおよび歪曲など) を指定して画像を補正できます。

カメラパラメータには、組み込みの行列パラメータ、外部の行列パラメータ、および歪曲係数が含まれます。詳細はこちら。次のコードを参照してください。

# 固有パラメータ
fx (float) - focal length in x direction.
fy (float) - focal length in y direction.
cx (float) - x coordinate of principal point.
cy (float) - y coordinate of principal point.
# 放射型歪曲パラメーター
k1 (float) - Radial distortion coefficient.
k2 (float) - Radial distortion coefficient.
k3 (float) - Radial distortion coefficient.
k4 (float) - Radial distortion coefficient.
# 接線歪曲パラメータ
p1 (float) - Tangential distortion coefficient.
p2 (float) - Tangential distortion coefficient.

カメラ固有の変換は次の方程式として定義されます。* は行列の乗算です。

|x|   |f_x, 0, c_x|   |X|
|y| = |0, f_y, c_y| * |Y|
|z|   | 0,  0,  1 |   |Z|

マニフェストファイルを入力する

Ground Truth は、入力マニフェストを受け取ります。マニフェストの各行は、アノテーターによって (または一部の組み込みタスクタイプの自動ラベル付けによって) 完了するタスクの単位を記述しています。入力マニフェストファイルの形式は、タスクタイプによって異なります。

  • 3D ポイントクラウドオブジェクトの検出またはセマンティックセグメンテーションのラベル付けジョブ – 入力マニフェストファイルの各行には、単一の 3D ポイントクラウドフレームと関連するセンサーフュージョンデータに関する情報が含まれています。このマニフェストファイルは、3D ポイントクラウドフレーム入力マニフェストと呼ばれます。
  • 3D ポイントクラウドオブジェクトの検出とラベル付けの追跡ジョブ – 入力マニフェストファイルの各行には、3D ポイントクラウドフレームと関連するセンサーフュージョンデータのシーケンスを定義するシーケンスファイルへのリンクが含まれています。各シーケンスは 3D ポイントクラウドシーケンスと呼ばれます。このマニフェストは、イントクラウドシーケンスの入力マニフェストと呼ばれます。

このチュートリアルでは、ポイントクラウドシーケンスのマニフェストファイルを作成します。ソリューションを変更して、ポイントクラウドフレームの入力マニフェストを作成することもできます。詳細はサンプルノートブックに記載されています。

KITTI データセットをワールド座標系に変換する

ノートブックを使用して、このセクションのコードブロックを実行できます。

ワールド座標系はデータセットによって異なります。一部のデータセットは、最初のフレームの LiDAR 位置を原点として使用し、データセット内のすべての 3D フレームは、最初のフレームの原点に車両の向きと位置が配置される基準としてフレームを使用します。一部のデータセットは、原点とは異なるポイントから始まるデバイス位置を持っています。KITTI データセットは、最初のフレームの位置をそのワールド座標系の基準として使用します。

この記事では、最初のフレームの LiDAR センサーの原点を基準として、KITTI データセットをグローバル基準フレームとして変換し、SageMaker Ground Truth が消費できるようにする方法を示します。KITTI 生データセットには、各フレームの回転行列と並進ベクトルが含まれており、このデータを使用して各フレームの外部行列を計算できます。生データの操作はより困難な場合があり、pykitti Python モジュールなどの開発パッケージを使用して KITTI データセットを操作する方が簡単です。

データセットで、dataset.oxts[i].T_w_imu は、i 番目のフレームの LiDAR 外部変換を提供します。また、NumPy 行列乗算関数 matmul: matmul(lidar_transform_matrix, points) を使用して、フレームのポイントを乗算してワールドフレームに変換できます。一般的に、LiDAR フレーム内のポイントに LiDAR 外部行列を乗算すると、ポイントがワールド座標に変換されます。T_w_imu 規則は、IMU からワールド座標系への変換を指します (そのため、表記は T_destinationFrame_originFrame になります)。

次のコード例は、KITTI ポイントクラウドフレームをワールド座標系に変換する方法を示しています。

import pykitti
import numpy as np

basedir = '/Users/nameofuser/kitti-data'
date = '2011_09_26'
drive = '0079'

# 'frames' 引数はオプションです。デフォルト: なし、データセット全体をロードします。
# キャリブレーション、タイムスタンプ、および IMU データは自動的に読み取られます。
# カメラとベロダインのデータは、ジェネレーターを作成するプロパティを介して利用できます
# アクセスされたとき、またはランダムアクセスを提供するゲッターメソッド経由。
data = pykitti.raw(basedir, date, drive, frames=range(0, 50, 5))

# i はフレーム番号です
i = 0

# 顧客は LIDAR 外部を計算します
lidar_extrinsic_matrix = data.oxts[i].T_w_imu

# LIDAR スキャナーのベロダイン生ポイントクラウドは座標系を所有します
points = data.get_velo(i)

# lidar_extrinsic_matrix を使用して LIDAR からグローバルフレームにポイントを変換します
def generate_transformed_pcd_from_point_cloud(points, lidar_extrinsic_matrix):
    tps = []
    for point in points:
        transformed_points = np.matmul(lidar_extrinsic_matrix, np.array([point[0], point[1], point[2], 1], dtype=np.float32).reshape(4,1)).tolist()
        if len(point) > 3 and point[3] is not None:
            tps.append([transformed_points[0][0], transformed_points[1][0], transformed_points[2][0], point[3]])
       
    return tps
    
# 顧客は、lidar_extrinsic_matrix を使用して LIDAR からグローバルフレームにポイントを変換します
transformed_pcl = generate_transformed_pcd_from_point_cloud(points, lidar_extrinsic_matrix)

センサーフュージョンのためのビデオデータと LiDAR データの関連付け

KITTI は、LiDAR 外部行列とカメラ外部行列の両方を提供します。それらを使用してポーズデータを抽出します。次に、3D ポイントクラウドシーケンス入力マニフェストに必要な JSON 形式を使用して、このポーズデータをフォーマットします。

KITTI データセットの場合、pykitti Python モジュールを使用して KITTI データをロードできます。データセットで、.oxts[i].T_w_imu は i 番目のフレームの LiDAR 外部行列 (lidar_extrinsic_transform) を提供します。この変換を、JSON 形式の LiDAR の見出しと位置である変換と四元数に変換できます。次のコードを参照してください。

from scipy.spatial.transform import Rotation as R

# 外部行列をポーズのクオータニオンと位置に変換するユーティリティ
def convert_extrinsic_matrix_to_trans_quaternion_mat(lidar_extrinsic_transform):
    position = lidar_extrinsic_transform[0:3, 3]
    rot = np.linalg.inv(lidar_extrinsic_transform[0:3, 0:3])
    quaternion= R.from_matrix(np.asarray(rot)).as_quat()
    trans_quaternions = {
        "translation": {
            "x": position[0],
            "y": position[1],
            "z": position[2]
        },
        "rotation": {
            "qx": quaternion[0],
            "qy": quaternion[1],
            "qz": quaternion[2],
            "qw": quaternion[3]
            }
    }
    return trans_quaternions

同様に、カメラの外部を使用してカメラのポーズデータを抽出できます。inv(matmul(dataset.calib.T_cam0_velo、inv(dataset.oxts[i].T_w_imu))) によって i 番目のフレームの cam0Camera_extrinsic_transform を計算できます。これは、cam0 の見出しと位置に変換できます。次のコードを参照してください。

def convert_camera_inv_extrinsic_matrix_to_trans_quaternion_mat(camera_extrinsic_transform):
    position = camera_extrinsic_transform[0:3, 3]
    rot = np.linalg.inv(camera_extrinsic_transform[0:3, 0:3])
    quaternion= R.from_matrix(np.asarray(rot)).as_quat()
    trans_quaternions = {
        "translation": {
            "x": position[0],
            "y": position[1],
            "z": position[2]
        },
        "rotation": {
            "qx": quaternion[0],
            "qy": quaternion[1],
            "qz": quaternion[2],
            "qw": -quaternion[3]
            }
    }
    return trans_quaternions

カメラのキャリブレーション、組み込み、および歪曲

KITTI データセットは、各カメラのキャリブレーションパラメータを提供します。たとえば、data.calib.K_cam0 には、次のカメラ組み込み行列が含まれています。

            fx 0  cx
            0  fy cy
            0  0   1

入力マニフェストファイルの作成

KITTI データセット内の一連のフレームをワールド座標系に変換し、LiDAR およびカメラの外部行列からポーズ情報を抽出したら、センサーフュージョンデータを含む 3D ポイントクラウドシーケンスのマニフェストファイルを作成できます。次の関数を使用して、シーケンス入力マニフェストファイルのシーケンスファイルを自動的に作成できます。

def convert_to_gt():
    # 'frames' 引数はオプションです。デフォルト: なし、データセット全体をロードします。
    # キャリブレーション、タイムスタンプ、および IMU データは自動的に読み取られます。
    # カメラとベロダインのデータは、ジェネレーターを作成するプロパティを介して利用できます
    # アクセスされたとき、またはランダムアクセスを提供するゲッターメソッド経由。
    data = pykitti.raw(basedir, date, drive, frames=range(0, 50, 5))
    image_paths  = [data.cam0_files,  data.cam1_files, data.cam2_files, data.cam3_files]
    camera_extrinsic_calibrations = [data.calib.T_cam0_velo, data.calib.T_cam1_velo, data.calib.T_cam2_velo, data.calib.T_cam3_velo]
    camera_intrinsics = [data.calib.K_cam0, data.calib.K_cam1, data.calib.K_cam2, data.calib.K_cam3]
    seq_json = {}
    seq_json["seq-no"] = 1
    seq_json["prefix"] = 's3://pdx-groundtruth-lidar-test-bucket/pdx-groundtruth-sequences/kittiseq2/frames/'
    seq_json["number-of-frames"] = len(data)
    seq_json["frames"] = []
    default_position = {"x": 0, "y": 0, "z": 0}
    default_heading = {"qx": 0, "qy": 0, "qz": 0, "qw": 1}
    for i in range(len(data)):
        # 顧客は LIDAR 外部を計算します
        lidar_extrinsic_matrix = data.oxts[i].T_w_imu        
        # LIDAR スキャナーのベロダイン生ポイントクラウドは座標系を所有します
        points = data.get_velo(i)
        # 顧客は、lidar_extrinsic_matrix を使用して LIDAR からグローバルフレームにポイントを変換します
        transformed_pcl = generate_transformed_pcd_from_point_cloud(points, lidar_extrinsic_matrix)    
        # 顧客は、LiDAR Extrinsic から回転のクオータニオンと平行移動を計算します
        trans_quaternions = convert_extrinsic_matrix_to_trans_quaternion_mat(lidar_extrinsic_matrix)
        # 顧客は trans_quaternions を使用して GT エゴ車両のポーズを設定します
        ego_vehicle_pose = {}
        ego_vehicle_pose['heading'] = trans_quaternions['rotation']
        ego_vehicle_pose['position'] = trans_quaternions['translation']
        # 変換された pcl を書き込むためにファイルを開く
        with open(output_base+"/"+str(i)+'.txt', "w") as out:
            writer = csv.writer(out, delimiter=' ', quotechar='"', quoting=csv.QUOTE_MINIMAL)
            for point in transformed_pcl:
                writer.writerow((point[0], point[1], point[2], point[3]))
        frame = {}
        frame["frame-no"] = i
        frame["frame"] = str(i)+'.txt'
        frame["unix-timestamp"] = data.timestamps[i].replace(tzinfo=timezone.utc).timestamp()
        frame["ego-vehicle-pose"] = ego_vehicle_pose
        images = []
        image_dir_path = os.path.join(output_base, 'images')
        if not os.path.exists(image_dir_path):
            os.makedirs(image_dir_path)
        for j in range(len(image_paths)):
            # 画像をコピーします
            image_path = image_paths[j][i]
            image_suffix_path = 'images/frame_'+str(i)+'_camera_'+str(j)+'.jpg'
            copyfile(image_path, os.path.join(output_base, image_suffix_path))
            # 顧客はカメラの外部性がある場合、それらを使用してカメラ変換を計算します
            camera_transform= np.linalg.inv(np.matmul(camera_extrinsic_calibrations[j], np.linalg.inv(data.oxts[i].T_w_imu)))
            # 顧客はカメラの逆外部から四元数と平行移動を計算します
            cam_trans_quaternions = convert_camera_inv_extrinsic_matrix_to_trans_quaternion_mat(camera_transform)
            image_json = {}
            image_json["image-path"] = image_suffix_path
            image_json["unix-timestamp"] = frame["unix-timestamp"]
            image_json['heading'] = cam_trans_quaternions['rotation']
            image_json['position'] = cam_trans_quaternions['translation']
            image_json['fx'] = camera_intrinsics[j][0][0]
            image_json['fy'] = camera_intrinsics[j][1][1]
            image_json['cx'] = camera_intrinsics[j][0][2]
            image_json['cy'] = camera_intrinsics[j][1][2]
            image_json['k1'] = 0
            image_json['k2'] = 0
            image_json['k3'] = 0
            image_json['k4'] = 0
            image_json['p1'] = 0
            image_json['p2'] = 0
            image_json['skew'] = 0
            images.append(image_json)
        frame["images"]=images
        seq_json["frames"].append(frame)
    with open(output_base+'/mykitti-seq2.json', 'w') as outfile:
        json.dump(seq_json, outfile)

ラベリングジョブの作成

入力マニフェストファイルを作成したら、ノートブックを使用してラベル付けジョブを作成できます。(ノートブックの手順を使用して) ラベル付けジョブを作成するときにプライベートの作業チームを用いて、作業者ポータルで作業者タスクを表示し、作業者ラベル付け UI を操作できるようにします。

ラベル付けジョブの前処理時間は、タスクが作業者ポータルに表示されるまでにかかる時間です。これは、入力データのサイズ、ポイントクラウドの解像度、センサーフュージョンに使用されるデータ (追加されている場合) によって異なります。したがって、ノートブックを使用する場合、ラベル付けジョブが作業者ポータルに表示されるまでに数分かかることがあります。表示されたタスクを選択して [作業開始] を選択します。

作業者 UI の詳細については、3D ポイントクラウドオブジェクト追跡を参照してください。以下は、作業者のラベル付け UI で使用できる支援ラベル付けツールの一部です。

  • ラベルの自動入力 – 作業者がフレームに直方体を追加すると、その直方体がシーケンス内のすべてのフレームに自動的に追加されます。自動入力されたこれらのラベルは、作業者が他のフレームで同じオブジェクトの注釈を手動調整すると自動的に調整されます。
  • ラベルの補間 – 作業者が 2 つのフレームで単一のオブジェクトにラベルを付けた後、Ground Truth はそれらの注釈を使用して、2 つのフレーム間のオブジェクトの動きを補間します。
  • スナップ – 作業者はオブジェクトの周りに直方体を追加し、キーボードショートカットまたはメニューオプションを使用して、Ground Truth の自動フィットツールで直方体をオブジェクト境界の周りにぴったりとスナップさせることができます。
  • 地面に合わせる – 作業者が 3D シーンに直方体を追加した後、作業者は直方体を自動的に地面にスナップできます。たとえば、作業者はこの機能を使用して、直方体をシーン内の道路または歩道にスナップできます。
  • マルチビューのラベル付け – 作業者が 3D 立方体を 3D シーンに追加すると、サイドパネルに前面と 2 つの側面からの観点が表示され、オブジェクトの周囲で直方体をしっかり調整できます。作業者は 3D ポイントクラウドまたはサイドパネルのラベルを調整でき、調整は他のビューにリアルタイムで表示されます。
  • センサーフュージョン – センサーフュージョンのデータを提供する場合、作業者は 3D シーンと 2D 画像の注釈を調整でき、注釈はリアルタイムで他のビューに投影されます。

次の動画は補間を示しています。作業者は、シーケンスの最初と最後のフレームに 2 つの直方体を追加しただけです。手動で追加されたこれらの直方体は、左下のナビゲーションバーに赤いセグメントで表れます。間にあるすべてのラベル (ナビゲーションバーの青い領域) は、Ground Truth によって補間されます。

次の画像は、マルチビューのラベル付けとセンサーフュージョンを示しています。立方体が 3D ポイントクラウドの視覚化に追加されたら、3 つの側面図とカメラ画像で調整できます。

ラベルに加え、ラベル属性を追加して、各オブジェクトの追加メタデータを収集できます。次の動画では、「車」というラベルの付いた立方体が追加されています。このラベルには、オクルージョンとカラーの 2 つのラベル属性が関連付けられています。作業者は、ラベル属性ごとに単一の値を選択できます。

Ground Truth は、15 分ごとに自動で注釈を保存します。作業が完了したら、[送信] を選択します。タスクが完了すると、出力データは HumanTaskConfig で指定した Amazon Simple Storage Service (Amazon S3) バケットに残ります。

出力データ形式の詳細については、Ground Truth 出力データページの 3D ポイントクラウドオブジェクト追跡を参照してください。

まとめ

このチュートリアルでは、Ground Truth 3D ポイントクラウドラベル付けジョブの入力データ要件とオプションについて学習し、オブジェクト追跡ラベル付けジョブを作成しました。3D ポイントクラウドのラベル付けジョブ用に作成できる他のタスクタイプの詳細については、3D ポイントクラウドタスクのタイプを参照してください。また、KITTI チームのおかげで、このデータセットを使用して、SageMaker Ground Truth で使用する 3D ポイントクラウドデータを準備する方法を披露することができました。とても感謝しています。

[1] KITTI データセットには独自のライセンスが適用されます。  データセットの使用は、すべてライセンスの契約条件に準拠していることをご確認ください。


著者について

Vikram Madan は Amazon SageMaker Ground Truth のプロダクトマネージャーです。機械学習ソリューションの構築を容易にする製品の提供に、力を注いでいます。余暇には、長距離のランニングやドキュメンタリーの鑑賞などをして過ごしています。

 

 

 

Zahid Rahman は AWS AI の SDE であり、複雑な機械学習の問題を解決するために大規模な分散システムを構築しています。彼は主に、ビッグデータの問題を「分割して征服する」革新的な技術に焦点を当てています。

 

 

 

 

Talia Chopra は、機械学習と人工知能を専門とする AWS のテクニカルライターです。彼女は AWS の複数のチームと協力して、Amazon SageMaker、MxNet、AutoGluon を使用しているお客様向けの技術ドキュメントとチュートリアルを作成しました。余暇には、瞑想や自然の中の散歩を楽しんでいます。