コンテンツへスキップ
チュートリアル25分で読めます

KITTI の LiDAR 点群に 3D 直方体でラベルを付ける

Potato で KITTI の LiDAR スキャンにカメラ画像で確認しながらボックスを付け、アノテーター間の 3D IoU 一致度を測定し、KITTI devkit 形式のラベルファイルをエクスポートします。

Potato Team

自動運転やロボティクスのチームは、このチュートリアルに従って、Potato 2.13.1 で KITTI の LiDAR スキャンに 3D ボックスを描き、すべてのボックスをカメラ画像と照合し、二人のアノテーター間の一致度を測定し、KITTI のトラッキングラベルを編集可能なトラックとしてインポートし、KITTI のラベルファイルをエクスポートできます。点群は、LiDAR センサーが出力する 3D の点の集合で、各点はメートル単位の位置と反射強度を持ちます。直方体(キューボイド)は、中心、長さ、幅、高さ、向きを持つ、向き付きの 3D バウンディングボックスです。

実例には、KITTI 3D 物体ベンチマークの二つのスキャンと、KITTI トラッキングベンチマークの一つのシーケンスの最初の 10 フレームを使います。このページの数値は、それらのファイルに対して、スクリプト化された二人のアノテーターとヘッドレスブラウザで Potato 2.12.1 を実行した結果によるものです。インポートとエクスポートは、保存されたアノテーションに対して Potato 2.13.1 で再実行しており、ここに示すインポートとエクスポートの出力は 2.13.1 のものです。

KITTI のデータ

KITTI は、Velodyne LiDAR と四台のカメラを備えた車でカールスルーエ周辺を走行して記録されました(Geiger et al., 2013)。3D 物体ベンチマーク(Geiger et al., 2012)には、7,481 の学習用スキャンと 7,518 のテスト用スキャンがあり、それぞれに左のカラー画像とキャリブレーションファイルがあります。トラッキングベンチマークには、ラベル付きの学習用シーケンスが 21 あります。KITTI のサイトは、すべての KITTI データセットを CC BY-NC-SA 3.0 で公開しており、データは「made available for academic use only」であると述べています。KITTI のスキャンやラベルは商用の作業には使えず、CC BY-NC-SA は、共有する改変物に同じライセンスを適用することを求めています。このチュートリアルは KITTI のファイルを同梱しないため、KITTI のサイトにログインして、ご自身でファイルをダウンロードしてください。

物体ベンチマークのページから、Velodyne 点群(29 GB)、左のカラー画像(12 GB)、カメラのキャリブレーション行列(16 MB)、学習用ラベル(5 MB)をダウンロードします。トラッキングベンチマークのページからは、Velodyne 点群、カメラのキャリブレーション、学習用ラベルをダウンロードします。このチュートリアルが使うのは、学習用スキャン 000063 と 000151、およびトラッキングシーケンス 0000 のフレーム 000000 から 000009 だけで、次のように配置します。

text
kitti-lidar/
├── kitti_object/training/
│   ├── velodyne/000063.bin, 000151.bin
│   ├── image_2/000063.png, 000151.png
│   ├── calib/000063.txt, 000151.txt
│   └── label_2/000063.txt, 000151.txt
└── kitti_tracking/training/
    ├── velodyne/0000/000000.bin ... 000009.bin
    ├── calib/0000.txt
    └── label_02/0000.txt

KITTI の .bin スキャンは、ヘッダーのない 32 ビット浮動小数点数のリストで、点ごとに四つ(x、y、z、強度)あります。スキャン 000063 には 119,796 点、スキャン 000151 には 115,174 点があります。二つのスキャンについての KITTI のラベルには、八つの物体が載っています。

スキャンKITTI のラベルファイル内の物体備考
000063Car 2、Pedestrian 1、Van 1Van は 34.8 m 先にあります
000151Car 2、Cyclist 1、Pedestrian 1、DontCare 3Car の一台と Pedestrian は画像の端で切れています

このチュートリアルでは、KITTI のラベルが正解キーです。アノテーターは KITTI のラベルを目にすることはなく、下のテスト実行では、各アノテーターのボックスを KITTI のものと比較します。

Potato のインストール

点群ビューアーは、基本パッケージ以外に何も必要としません。

bash
pip install potato-annotation==2.13.1

Potato は .bin ファイルをサーバー上で読み込み、ビューアーの 3D ライブラリはパッケージ内に同梱されています。ヘッドレスブラウザのテストでは、アノテーションページは Potato サーバー以外のどのホストにもリクエストを送りませんでした。

プロジェクトフォルダー

最初のプロジェクト kitti-boxes は、物体ベンチマークの二つのスキャンを二人のアノテーターに与えます。各スキャンの .bin、.png、キャリブレーションファイルを media/ フォルダーにコピーし、データファイルに一行につき一つのスキャンを列挙します。

text
kitti-boxes/
├── config.yaml
├── data/
│   └── scans.jsonl
└── media/
    ├── velodyne/000063.bin, 000151.bin
    ├── image_2/000063.png, 000151.png
    └── calib/000063.txt, 000151.txt

point_cloud は media/ からの相対でスキャンを指定し、calibration は、KITTI のキャリブレーションファイルと左のカラー画像(KITTI のカメラ P2)を指定します。

json
{"id": "000063", "text": "KITTI 3D object training scan 000063", "point_cloud": "velodyne/000063.bin", "calibration": {"file": "calib/000063.txt", "images": {"P2": "image_2/000063.png"}}}
{"id": "000151", "text": "KITTI 3D object training scan 000151", "point_cloud": "velodyne/000151.bin", "calibration": {"file": "calib/000151.txt", "images": {"P2": "image_2/000151.png"}}}

アノテーターは KITTI の答えを必要としないため、label_2 ファイルはプロジェクトに入れません。

設定

下の設定は完全なもので、2.12.1 と 2.13.1 の両方で python -m potato.validate_cli config.yaml --strict を通ります。

yaml
annotation_task_name: KITTI 3D boxes, two annotators
task_dir: .
output_annotation_dir: annotation_output/
media_directory: media
data_files:
  - data/scans.jsonl
item_properties:
  id_key: id
  text_key: text
user_config:
  allow_all_users: true
  users: []
 
# Both annotators box every scan
num_annotators_per_item: 2
 
annotation_schemes:
  - annotation_type: spatial_annotation
    name: objects
    description: Put a 3D box around every car, van, pedestrian, and cyclist
    source_field: point_cloud
    calibration_field: calibration
    tools: [cuboid_3d]
    # KITTI's own class names, so the export writes the names unchanged
    labels:
      - {name: Car, color: "#FF6B6B", key_value: "1"}
      - {name: Van, color: "#4ECDC4", key_value: "2"}
      - {name: Pedestrian, color: "#FFD93D", key_value: "3"}
      - {name: Cyclist, color: "#6C8AE4", key_value: "4"}
    attributes:
      - name: occluded
        type: select
        options: [none, partly, largely, unknown]
        default: none
    default_box_height: 1.5
    fit_box_height: true

四つの設定には理由があります。

  • クラス名。 KITTI エクスポートは、各ボックスのクラス名をラベルファイルの type 列として書き出します。クラスを Car、Van、Pedestrian、Cyclist と名付けると、KITTI のツールが対応付けの手順なしで読み込める行が出力されます。
  • calibration_field。 キャリブレーションはビューアーの下のカメラパネルを有効にし、エクスポートは KITTI のカメラ座標を書き出すためにキャリブレーションを必要とします。キャリブレーションのない項目をエクスポートはスキップし、警告にその項目を挙げます。
  • occluded 属性。 四つの選択肢は、エクスポートで KITTI のオクルージョンコード 0 から 3 に対応します。設定には切り詰め(truncation)の属性がありません。エクスポートが、下のエクスポートのステップで説明するように、カメラ画像から切り詰めを測定するためです。
  • default_box_height と fit_box_height。 新しいボックスは高さ 1.5 m から始まり、これは二つのスキャンにある四台の車の 1.45 から 1.59 m に近い値です。fit_box_height: true を指定すると、ボックスの底面領域に少なくとも五つの点が含まれる場合は常に、ビューアーがボックスの上面と下面を、その領域内の LiDAR の点に合わせます。

ボックスの描画

プロジェクトフォルダーでサーバーを起動します。

bash
potato start config.yaml -p 8000

各アノテーターはサーバーのアドレスを開き、ユーザー名とパスワードで登録して、両方のスキャンを受け取ります。ビューアーは高さで色分けした点群を表示し、スキャン 000063 の全体が届くと、点群の下のステータス行に「119,796 points, all loaded」と表示されます。点群の下には、Top (X-Y)、Front (Y-Z)、Side (X-Z) の三つの正射影スラブパネル(それぞれ厚さ 2.0 m)と、左のカラー画像を表示するカメラパネルがあります。

c を押して 3D ボックスツールを選び、クラスの数字キー(Car は 1)を押してから、物体の地面上の足跡をドラッグします。ステータス行は、ボックスのサイズと位置を示してボックスを確認します。ブラウザテストでは、たとえば「Box added: 7.9 x 0.4 x 1.5 m at 34.3, -19.2」と表示されました。新しいボックスは水平で、LiDAR の軸に揃っています。q と e を押すと、選択したボックスを 5 度刻みで回転させ、Shift+q と Shift+e では 1 度刻みで回転させます。スラブパネルでは、矢印キーでボックスを動かし、Shift と矢印キーでその側の面を外側へ動かし、Alt と矢印キーで面を内側へ動かします。, と . のキーはスキャン上のボックスを順に移動し、Delete は選択したボックスを削除します。選択したボックスの occluded メニューは、下部の属性パネルにあります。

カメラパネルは、スキャンのキャリブレーションを通じて、すべてのボックスを左のカラー画像上に描画します。上から見て正しそうなボックスが、視線方向には短すぎることがあり、カメラ画像はその誤りをすぐに示します。「Next」をクリックする前に、カメラパネルですべてのボックスを確認してください。

クラスボタンは、次のボックスのクラスを設定します。Potato 2.13.1 からは、ボックスを選択している間にクラスボタンをクリックすると、そのボックスのクラス(シーケンスではトラック全体のクラス)が変わります。2.12.1 でのブラウザテストでは、クリックは待機中のクラスだけを変え、クラスが誤っているボックスは、削除して描き直す必要がありました。

このページの裏付けとなったテスト実行

スクリプト化された二人のアノテーターが、動作中のサーバーを通じて両方のスキャンにボックスを付け、ビューアーが送るのと同じリクエストで各スキャンを保存しました。各アノテーターは、すべての物体について KITTI 自身のラベルから出発しました。スクリプトは、Potato の KITTI 変換で各ラベルを LiDAR フレームに変換し、決まった方法でボックスを変更しました。

  • ana は、すべての中心を前方に 0.10 m、右に 0.05 m 動かし、すべての辺を 0.05 m 長くし、すべての向きを 2 度回し、KITTI のオクルージョンレベルをコピーしました。
  • ben は、すべての中心を後方に 0.25 m、左に 0.15 m 動かし、すべての辺を 8% 長くし、すべての向きを -6 度回し、スキャン 000063 の 34.8 m 先の Van を飛ばし、スキャン 000151 の Cyclist を Pedestrian と呼び、オクルージョンを none のままにしました。

固定された誤りによって、一致度の数値を KITTI のラベルと照合できます。人間の誤りは、二つのスクリプト化されたパターンよりもボックスごとのばらつきが大きくなります。

アノテーター間の一致度

ブラウザで /admin を開き、プロジェクトフォルダーの admin_api_key.txt にある管理者キーを入力してから、/admin/iaa を開きます。テスト実行では、レポートは両方のアノテーターについて両方のスキャンを一覧し、次の値を示しました。

text
mean_agreement                          0.272
mean_object_count_diff                  0.500
attributes.occluded.alpha              -0.174
attributes.occluded.percent_agreement   0.400

Potato は、各スキャンで二人のアノテーターのボックスを 3D の積集合を和集合で割った値(IoU)で対応付け、二つの回転したボックスの IoU を厳密に計算します。二つのボックスは、3D IoU が 0.25 以上の場合に同じ物体と数えられます。スキャンのスコアは、一致したペアの IoU の合計を、一致したペアの数と一致しなかったボックスの数の和で割ったものです。クラスが異なるペアは、そのペアの IoU の半分として数えられます。二つのスキャンのスコアは 0.239(000063)と 0.305(000151)で、レポートは二つのスコアの平均を示します。下の表は、それらのスコアの基になったペアと、各ボックスの KITTI のラベルに対する 3D IoU を示します。

スキャン物体ana と benana と KITTIben と KITTI
000063Car0.6640.8700.705
000063Car0.5320.8230.595
000063Pedestrian0.25 未満、不一致0.5760.237
000063Vanben はボックスを描かず0.8860.000
000151Car0.6570.8640.698
000151Cyclist0.556、クラスが異なる0.8060.609
000151Pedestrian0.25 未満、不一致0.6320.307
000151Car0.5930.8460.647

二人の歩行者は、小さな物体に対して 3D IoU がいかに厳しいかを示しています。歩行者のボックスは幅 0.5 から 1.0 m で、ana と ben の中心は 0.40 m 離れています。二つのボックスが共有する体積は一致と見なすには小さすぎ、それぞれのボックスは一致しない物体として数えられます。長さ 3.2 から 4.5 m の車で同じ 0.40 m のずれは、それでも 0.53 から 0.66 で一致しました。occluded のアルファ -0.174 は、五つの一致したボックスを対象としています。Ben の一律の none は、ana のコピーした KITTI のレベルと、五つのうち二つで一致しました。

mean_agreement の値は偶然補正されておらず、レポートにはペアごとやアノテーターごとの内訳もありません。3D ボックス、時間区間、エージェントトレースの一致度は、対応付けをさらに詳しく説明しています。

KITTI ラベルファイルのエクスポート

kitti_3d エクスポートは、スキャンごとに一つの KITTI ラベルファイルを書き出し、複数のアノテーターが作業を保存している場合は、アノテーターごとのフォルダーに書き出します。

bash
python -m potato.export -c config.yaml -f kitti_3d -o export/
text
export/ana/label_2/000063.txt
export/ana/label_2/000151.txt
export/ben/label_2/000063.txt
export/ben/label_2/000151.txt

各行は KITTI の 15 個のフィールドを持ち、スキャン 000151 についての ana のファイルは次のとおりです。

text
Car 0.95 0 -0.87 0.00 199.35 312.43 369.00 1.55 1.83 3.74 -3.12 1.69 3.45 -1.60
Cyclist 0.00 1 -1.63 990.09 145.93 1031.72 217.23 1.77 0.83 1.76 10.57 0.91 18.52 -1.11
Pedestrian 0.84 0 -0.99 1210.27 127.60 1223.00 228.51 1.77 0.60 0.98 11.62 0.84 12.81 -0.25
Car 0.00 1 -0.43 845.53 161.27 1005.56 210.34 1.50 1.80 4.28 10.08 0.91 22.52 0.00

Potato はボックスを、LiDAR フレームのメートル単位で、回転はクォータニオンとして保存します。KITTI の 3D フィールドは、レクティファイされた基準カメラのフレームにあります。エクスポートは、スキャンのキャリブレーションファイルの R0_rect と Tr_velo_to_cam を通じて各ボックスを変換し、位置をボックスの中心からボックスの底面の中心へ移し、向きを rotation_y として書き出します。KITTI は向きしか保存しないため、エクスポートはピッチとロールを捨て、1 度を超えて傾いていたボックスの数を警告で報告します。

変換を確認するため、三人目のスクリプト化されたアノテーターが、両方のスキャンで KITTI のラベルをそのまま保存し、エクスポートされたファイルを KITTI の label_2 ファイルとフィールドごとに比較しました。

フィールドPotato が書き出す内容KITTI のファイルとの比較
typeボックスのクラス名一致
truncatedボックスのカメラ投影のうち画像の外にある割合0.01 以内(画像の端で切れた二つの物体で 0.96 と 0.88、KITTI は 0.96 と 0.87)
occludedコード 0 から 3 としての occluded 属性一致
alpharotation_y から物体への方向を引いたもの0.05 rad 以内
2D ボックスP2 を通じて投影され、画像にクリップされた 3D ボックス5.7 px 以内
h, w, lボックスのサイズ一致
x, y, zカメラ座標での底面の中心一致
rotation_yカメラ座標での向き一致
score書き出されません該当なし

2D ボックスは、画像上に描かれたボックスではなく直方体の投影であり、スキャン 000063 の歩行者では、投影が KITTI の手描きのボックスより広くなります(左端で 5.7 px)。画像の端で切れた物体では、Potato 2.13.1 は最後のピクセルでボックスをクリップするため、スキャン 000151 の歩行者は KITTI のファイルと同じく 1223.00 で終わります。Potato 2.12.1 は画像の幅でクリップし、1224.00 と書き出していました。Potato には DontCare の領域タイプがないため、エクスポートは DontCare の行を書き出しません。KITTI の物体ラベルとエクスポートはどちらも小数点以下 2 桁を使うため、3D フィールドは変わらずに戻りました。

KITTI ラベルのインポート

potato import -f kitti は、KITTI の label_2 ファイルを 2D 画像ボックスのプロジェクトに読み込みます。インポートは、各物体の寸法、位置、rotation_y を読み取り専用の属性として保持し、2D ボックスだけが編集できるという警告を表示します。Potato 2.13.1 には、KITTI の 3D 物体ラベルを一つのスキャン上に直方体として置くインポーターはありません。

KITTI のトラッキングラベルは直方体として取り込まれます。potato import -f kitti_tracking は、label_02/、velodyne/、calib/ を持つトラッキングフォルダーを読み込み、シーケンスごとに一つの項目を作り、ラベル付きのフレームごとに一つのキーフレームを置きます。kitti-lidar フォルダーからインポートを実行します。

bash
potato import -i kitti_tracking/training -f kitti_tracking -o tracking-0000
text
INFO: Marked 31 imported annotation(s) as source='import' (kitti_tracking)
WARNING: Left out 17 DontCare row(s): they mark regions KITTI excludes from evaluation, not objects.
Imported 1 sequence(s), 4 track(s), 31 keyframe(s), 3 categor(ies) into tracking-0000
 
Run it:
  potato start tracking-0000/config.yaml -p 8000

テスト実行では、ダウンロードした 10 個のスキャンに合わせて、フレーム 0 から 9 のラベル行を残しました。10 フレームには四つのトラックがあり、フレーム 0 から Van、Cyclist、Pedestrian があり、フレーム 5 から二台目の Van があります。インポーターは、シーケンスのキャリブレーションファイルを通じて、すべてのボックスを KITTI のカメラフレームから LiDAR フレームに変換し、スキャンがフレーム番号を飛ばしているシーケンスは除外します。Potato はスキャンの順序でフレームに番号を付けるためです。スキームの名前は objects です。Potato 2.12.1 は、コマンドに --schema-name objects を加えない限り、スキームを image_annotation と名付けていました。

インポーターは tracking-0000/config.yaml、data/training.json、README を書き出します。生成された設定は media_directory をデータセットのフォルダーに向け直し、インポートされたトラックを、出発点としてすべてのアノテーターに表示します。下の設定は、生成されたものに四つの変更を加えたもので、完全であり、バリデーターを通ります。

yaml
annotation_task_name: KITTI tracking 0000, two annotators
task_dir: .
output_annotation_dir: annotation_output/
media_directory: ../kitti_tracking/training
data_files:
  - data/training.json
item_properties:
  id_key: id
  text_key: notes
user_config:
  allow_all_users: true
  users: []
num_annotators_per_item: 2
pre_annotation:
  enabled: true
  field: predictions
  allow_modification: true
annotation_schemes:
  - annotation_type: spatial_annotation
    name: objects
    description: Correct the imported tracks
    source_field: point_cloud
    calibration_field: calibration
    tools: [cuboid_3d]
    labels:
      - {name: Van, color: "#4ECDC4", key_value: "1"}
      - {name: Pedestrian, color: "#FFD93D", key_value: "2"}
      - {name: Cyclist, color: "#6C8AE4", key_value: "3"}
    attributes:
      - name: occluded
        type: select
        options: [none, partly, largely, unknown]
        default: none
        per_keyframe: true
      - name: truncated
        type: select
        options: [none, partly, fully]
        default: none
        per_keyframe: true

変更点は、タスク名、num_annotators_per_item: 2、そして各クラスの色とキーです。KITTI はすべてのフレームについてオクルージョンと切り詰めを記録し、インポーターは各フレームの値を書き込むため、2.13.1 のインポーターは両方の属性に per_keyframe: true も書き込みます。per_keyframe がないと、あるフレームでの属性の変更がトラックのすべてのキーフレームに適用され、Potato 2.12.1 ではこの設定を手で追加する必要があります。Potato 2.12.1 のバリデーターは、pre_annotation が Potato 3.0 で削除される予定であるという注意も表示していましたが、2.13.1 は注意を表示しません。

トラックの修正

前と同じように tracking-0000 でサーバーを起動します。点群の下のフレームバーには「Frame 1 of 10 (3 keyframes)」と表示され、[ と ] でフレームを移動します。トラックのボックスは、そのトラックのキーフレームにだけ保存され、二つのキーフレームの間のフレームでは、ビューアーがボックスを補間し(中心とサイズは線形に、回転は最短弧に沿って)、点線の縁でボックスを描画します。補間されたボックスを動かす、サイズを変える、回転させると、そこに新しいキーフレームができます。f は選択したボックスを次のフレームにキーフレームとしてコピーし、Delete は現在のフレームでの選択したボックスのキーフレームを削除し、「Delete track」ボタンはトラック全体を削除します。Potato は、キーフレーム間で物体を追ってボックスを動かすことはありません。すべてのキーフレームは、アノテーターが置いたか、インポートされたボックスです。

トラッキングのキャリブレーションファイルは画像を指定しないため、カメラパネルは写真なしでボックスの投影を表示します。Potato のキャリブレーションは、項目についてカメラごとに一つの画像を指定するため、シーケンスは各フレーム自身の写真を表示できません。

シーケンスでの一致度とエクスポート

さらに二人のスクリプト化されたアノテーターが、インポートされたトラックを保存しました。eli は、インポートされた 31 個のキーフレームすべてを変更せずに保存しました。dana は、各トラックのキーフレームをフレーム 0、3、6、9 とトラックの最初と最後のフレームに残し、他の 17 個を削除したため、Potato は間のフレームのボックスを補間します。/admin/iaa は、補間されたボックスを埋めてシーケンスをフレームごとに採点し、トラックの同一性の尺度を加えます。

text
mean_agreement                          0.991
n_frames                                10
identity.mota                           1.0
identity.idf1                           1.0
identity.id_switches                    0
attributes.occluded.alpha               1.0
attributes.truncated.alpha              0.745

補間されたボックスは、この区間の道路では KITTI のラベルに近いままでした。同じフレームでの KITTI のボックスと比べて、dana のエクスポートされたボックスは、中心誤差の平均が 0.005 m、最大が 0.051 m で、3D IoU は最低で 0.876、平均で 0.991 でした。キーフレームの間で曲がったりブレーキをかけたりする車両は、より大きな誤差を残すことがあるため、動きが変わる箇所にキーフレームを追加してください。

トラッキングのキャリブレーションファイルは画像サイズを記録していないため、KITTI の画像のサイズをエクスポートに渡します。

bash
python -m potato.export -c config.yaml -f kitti_3d -o export/ --option image_width=1242 --option image_height=375

エクスポートは export/eli/label_02/0000.txt と export/dana/label_02/0000.txt を KITTI のトラッキング形式で書き出し、15 個の物体フィールドの前にフレーム番号とトラック ID を置き、すべてのトラックのすべてのフレームについて一行を出力します。画像サイズがない場合、エクスポートは 2D ボックスをクリップせずに書き出し、その旨を警告で伝えます。eli のファイルの最初の三行は次のとおりです。

text
0 0 Van 0 0 -1.788236 297.306825 163.588132 455.254746 294.245211 2.000000 1.823255 4.433886 -4.552284 1.858523 13.410495 -2.115488
0 1 Cyclist 0 0 -1.952163 739.947686 163.364720 931.778054 374.000000 1.739063 0.824591 1.785241 1.640400 1.675660 5.776261 -1.675458
0 2 Pedestrian 0 0 -2.540723 1088.811242 167.172676 1220.919879 324.237147 1.714062 0.767881 0.972283 6.301919 1.652419 8.455685 -1.900245

KITTI の label_02 ファイルと比較すると、eli の 31 行は、トラック、type、切り詰め、オクルージョン、寸法、位置、rotation_y で一致し、変更されていないボックスは KITTI のものに対して 3D IoU 1.000 で戻りました。Potato 2.13.1 は、KITTI のトラッキングラベルと同じく小数点以下 6 桁を書き出し、誰かがボックスを編集しない限り、インポートされたボックス自身の切り詰めを保持します。Potato 2.12.1 は小数点以下 2 桁を書き出していたため、変更されていないボックスは 3D IoU が 0.979 以上にとどまっていました。Potato 2.12.1 はまた、ボックスの投影から切り詰めを測定し、31 行のうち 13 行で KITTI が 0 のところに 1 を書き出していました。それは、10 フレームすべてでボックスが画像の端の下に投影される Cyclist と、フレーム 1 から 3 の Pedestrian です。2D ボックスは KITTI の手描きのボックスと最大 28 px 異なり、それはフレーム 1 の 8.2 m 先の Pedestrian でした。

LiDAR 直方体のための他のツール

CVAT Community は MIT ライセンスでセルフホスト型で、点群に直方体を描き、フレーム間で直方体のトラックを補間します。CVAT の 3D エクスポートは Kitti Raw Format 1.0 と Sly Point Cloud Format 1.0 で、CVAT の KITTI 1.0 形式は 2D 画像を対象としています。CVAT Online の Solo と Team プランは、月払いでユーザーあたり月額 33 ドル、年払いで 23 ドルです。Segments.ai は、PCD、PLY、KITTI バイナリなどの形式の点群を読み込み、補間付きで点群シーケンスにラベルを付け、Segments.ai の Fusion プランはセンサーフュージョンのインターフェースを加えます。Segments.ai はすべてのプランを見積もりで価格設定し、Core プランの点群を 500,000 点に制限し、無料の学術ライセンスを提供しています。Supervisely には無料の Community プランと、月額 199 ユーロからの Pro プランがあります。料金ページは、直方体トラッキングと直方体の自動調整を Supervisely の点群機能に挙げており、Supervisely のアプリカタログには、Import KITTI 3D と Export to KITTI 3D のアプリがあります。Xtreme1 は、LF AI & Data Foundation がホストする Apache-2.0 のツールで、3D 直方体、LiDAR とカメラのフュージョン、フレーム系列のトラッキングを備えます。バージョン 0.9.3 は 2026 年 9 月 28 日に公開され、BasicAI がエンタープライズ版を提供しています。価格と機能は、2026 年 10 月 29 日に各ツール自身のページで確認しました。

これらのツールの多くは、Xtreme1 の OpenPCDet 連携のように、モデルで直方体を配置または調整しますが、Potato には 3D ボックスのためのモデルがありません。Potato は、同じスキャンに複数のアノテーターが取り組み、ボックスの一致度を求める調査や、KITTI への変換をスクリプトではなくツールで行いたいチームに適しています。点群アノテーションツールの比較は、これらのツールを Potato と並べて、さらに詳しく比較しています。

LiDAR ラベル付けにおける Potato の限界

  • モデル支援のボックスやトラッキングはありません。 ボックスはアノテーターまたはインポートから得られ、トラックはキーフレーム間を補間によってのみ動きます。
  • 単一の KITTI スキャンの 3D インポートはありません。 -f kitti は KITTI の 2D ボックスを、-f kitti_tracking はシーケンスを読み込みます。
  • 偶然補正のない一致度。 /admin/iaa は、スキームごとに一つの平均 3D IoU スコアを示し、ペアごとやアノテーターごとの内訳はありません。
  • 投影された 2D ボックス。 エクスポートの 2D ボックスは 3D ボックスから作られ、KITTI の手描きのボックスより広くなります。

次に読むもの

参考文献

  1. Geiger, A., Lenz, P., & Urtasun, R. (2012). Are we ready for autonomous driving? The KITTI vision benchmark suite. 2012 IEEE Conference on Computer Vision and Pattern Recognition, 3354-3361. https://doi.org/10.1109/cvpr.2012.6248074
  2. Geiger, A., Lenz, P., Stiller, C., & Urtasun, R. (2013). Vision meets robotics: The KITTI dataset. The International Journal of Robotics Research, 32(11), 1231-1237. https://doi.org/10.1177/0278364913491297