🚗

LiDARデータによる物体検出を試してみた-Part2

2022/10/02に公開

今回の内容

前回の記事でPointPilllarsの動作確認を行った。
次のステップとしてUnity上で自作のLiDARを実装して点群データを取得できるようにしたい。
https://zenn.dev/gyabi/articles/739131bae9a57e

今回は実装に入る前にPointPilllarsと前回使用したKittiDataSetについて深堀し、実装する際の要件を抽出する。

PointPillars

アルゴリズムそのものは理解しきっていない+既に良く解説されている記事が存在するのでリンクを張っておく。
https://aru47.hatenablog.com/entry/2020/03/07/152831
https://qiita.com/chin_self_driving_car/items/362772f5078c0cbe4c0d

ここでは前回利用したGitHubリポジトリで実装されているPointPilllarsの入出力形式についてまとめる。

入力形式

  • (N,4)のfloat型点群配列 ※Nは点群数に依存
  • コード上は上記の形式のnumpy配列をそのままtorchでTensorに変換して入力していた。
  • N=2の場合のデータ構造の例は以下のようになる。

[[X座標1、Y座標1、Z座標1、反射率1]、[X座標2、Y座標2、Z座標2、反射率2]]

※注意:今回Kittiから取得した座標データをそのまま利用しており以下の座標系に従っている

https://www.cvlibs.net/datasets/kitti/setup.php

出力形式

  • 以下の構造のDict型オブジェクト ※Dは検出数に依存
キー 形式 説明
lidar_bboxes (D,7) 各検出オブジェクトの3Dバウンディングボックス
labels (D) 各検出オブジェクトのラベル
scores (D) 各検出オブジェクトに対する推論スコア

lidar_bboxesについて
lidar_bboxesでは各検出オブジェクトの3Dバウンディングボックスを出力する。
各要素は以下のようになる。

0~2 3~5 6
検出オブジェクト中心座標 バウンディングボックスの矩形長さ 物体角度
x,y,zにそれぞれ対応 x,y,zにそれぞれ対応 -

また、リポジトリ内では可視化の前にデータ形式を(D,8,3)に変形していた。(bbox3d2cornersメソッド)
上記はバウンディングボックスの各頂点の3次元座標に対応する。

PointPillarsを最低限動かすための仕様

Unity

上記座標系に合わせたfloat型点群配列を取得可能

KittiDataSet

まずKittiDataSetについての論文はこちら。
https://www.cvlibs.net/publications/Geiger2013IJRR.pdf

PointCloudデータ

形式としてはPointPilllarsの入力と全く同じで以下となる。

  • (N,4)のfloat型点群配列 ※Nは点群数に依存
    座標系もまったく同様で以下となる。(というかKittiでPointPillarsを学習させているので当たり前。。)

データセットでは上記のデータをバイナリファイルで提供していた。

次にLiDARデバイス側のスペック依存の部分を以下に示す。

  • 仕様デバイス:HDL-64E
  • 回転:10Hz
  • 垂直視野:26.9
  • 垂直解像度:64
  • 角度分解能:0.08度
  • 1サイクル取得点群:平均10万ポイント

ちなみにメモとして16チャネルのVelodyneLiDARのマニュアル(P54で座標系について触れている)と実際にKittiで使用しているモデルの出てくる資料を張っておく
VelodyneLiDARのデータ構造
https://velodynelidar.com/wp-content/uploads/2019/12/63-9243-Rev-E-VLP-16-User-Manual.pdf
座標系はkittiに使われているものは以下
https://www.jstage.jst.go.jp/article/jacc/54/0/54_0_156/_pdf/-char/ja

CameraImageデータ

カメラ自体は4台取り付けて取得したらしい(RGBとモノクロのそれぞれステレオ)
ちなみに3D物体検出ではP0~P3のカメラのうちP2を利用している。
画像は1382 x 512 pixels

Calibデータ

Kittiでは各データについてLiDAR座標をカメラ内の画像座標に変換するためのキャリブレーションデータを提供している。以下に内容を纏める。

  • P0~P3:4台のカメラそれぞれに対応するプロジェクション行列(射影行列)
    ちなみにプロジェクション行列は同次座標系を使用する
    →3次元座標にwを追加することで行列演算で平行移動を可能にしたもの
    →各値からwを除算することで3次元座標に変換できる
    https://xr-hub.com/archives/12124

  • R0_Rect:修正回転行列→複数のカメラ画像が同じ平面上に配置されるらしい
    https://medium.com/test-ttile/kitti-3d-object-detection-dataset-d78a762b5a4

  • Tr_velo_to_cam:LiDAR座標系からカメラ座標系への変換行列?(おそらく回転情報も含む?)
    https://www.cvlibs.net/datasets/kitti/setup.php

  • Tr_imu_to_velo:IMU座標系からLiDAR座標系への変換行列?

KittiDataSet同様に可視化するための仕様

Unity側で映像出力する場合
Python

  • 特になし

Unity

  • 上記LiDARスペックにあう点群データを取得可能
  • 検出したバウンディングボックスデータからカメラ座標へ変換可能(またはバウンディングボックスを直接生成)

Python側で映像出力する場合
Python

  • Unity側のカメラキャリブレーションデータを反映させて射影変換し映像に検出結果を重畳可能

Unity

  • 上記LiDARスペックにあう点群データを取得可能
  • 同時に自信のカメラとLiDARの位置情報からキャリブレーションデータを生成可能

まとめ

上記内容から以下の仕様を満たす疑似LiDARをUnity上に実装していこうと思う。
(今回はリアルタイム性は一旦考えない)

Unity
1.座標系をPointPillarsに合わせた点群データを取得可能
2.何かしらの形式でファイル保存可能
3.検出データからバウンディングボックスを生成して可視化可能

Ex1.回転周波数、チャネル数、垂直画角、水平画角を調整可能
Ex2.LiDARの座標からカメラ内画像データに変換するためのキャリブレーション行列取得可能(PointPillar側の座標系に合わせる)
※Exの内容については理想形であり、今回は動作の確認を目的とするので実施しない

Python
1.csvに格納された点群データからPointPillarsを起動可能
2.検出した結果を別途ファイルに格納して保存可能

Discussion