🌊

3D物体検出ライブラリOpenPCDetを使ってみた

2023/03/17に公開約4,200字

OpenPCDetとは

OpenPCDet とは、OpenMMLabという中国系の研究グループ?が作成した3D物体検出のオープンソースライブラリで、いくつかの物体検出手法が実装されており、学習済みモデルも利用できる。インストールも簡単にできるが、2023/03現在ではCPUのみのPCにはインストールできない模様。

OpenPCDetでは物体検出手法を構成する様々なモジュールが実装されており、実際の物体検出手法を実装する際には、どのモジュールをどんな設定で使うのかというconfigだけを書けばだいたい完了する。新たな手法を試してみるときに、多くの場合は既存手法の一部を変更するだけなので、そのモジュールだけを新たに実装するだけで済みそうだ。

あまりドキュメントが整備されていない点が不便なので、自分の備忘録として記事を書くことにした。PV-RCNNという手法を例としてOpenPCDetの実装方法を説明するため、まずPV-RCNNの概要について説明する。

PV-RCNN

PV-RCNN: Point-Voxel Feature Set Abstraction for 3D Object Detection

PV-RCNNとは、高い物体検出精度を比較的少ない計算量で実現した手法で、voxel-baseと点群baseの物体検出手法の良いとこ取りをしたような手法である。

まず点群に対してFarthest Point Sampling (FPS)により点群を均等にサンプリングし、各点の特徴量を計算する。特徴量計算の際には、点の周辺情報を取り込むことが高い精度を達成するために必要であるが、点ごとに周囲の点を探すという処理を行うと計算量が多くなってしまう問題がある。PV-RCNNでは、元の点群をVoxel化(H x W x L x D)し、それに対して3D CNNを適用することで求めた周辺情報を含んだ特徴量を点ごとの特徴量の計算に使うことで、低計算量で高い精度を実現している。具体的には、Voxelを3D CNNした際の入力層、中間層、出力層それぞれについて、各点の位置に対応するVoxelと、その周囲のVoxelを探し、それらのVoxelの特徴量をMLP+Max poolingで変換して、点の特徴量に追加していく。Voxelから計算される特徴量だけでなく、最初にFPSでサンプリングした点に対して、PointNet++のように周囲の点を探し、MLP+Max poolingで計算した特徴量を追加し、次に説明する鳥瞰図特徴量も線形補間して追加することで、さらに特徴量を増やす。FPSでサンプリングした点は背景に対応する点も含んでいるので、特徴量から重要度を推定し、特徴量に掛け合わせることによって、背景からの点の影響を緩和する。この重要度は点ごとに背景か否かのラベルを推定しているようなもので、正解BBoxに点が含まれるか否かで正解を作って学習させている。

次に、Voxelに対して3層の3D CNNを適用した結果をz軸方向に繋ぐことで、H/8 x W/8 x L/8 x D'の特徴量を H/8 x W/8 x LD'/8の鳥瞰図特徴量に変換し、それに対して画像の物体検出と同じように、予め設定したAnchor boxの修正量とクラスラベル推定を行う。
Anchor boxはクラスごとにサイズを決め、向きは0度と90度の2つを用意するため、クラス数をCとすると、2 * C * H/8 * W/8個のAnchor boxのパラメータを推定する。

最後に、今求めたBounding Box(BBox)(Anchor boxを修正したもの)の特徴量を、点ごとの特徴量から計算する。具体的には、Bounding Box内に6 x 6 x 6のグリッド点を設定し、各グリッド点の周囲にある点を(BBoxの内外問わず)集めてきて、MLP+Max poolingで固定長に変換し、全てのグリッド点の特徴をつなぎ合わせる。この特徴量をMLPで変換することで、各クラスごとのスコア(C次元)とBBoxのパラメータ(C x 7)を求め直す。最終的な出力は、スコアが最も高いクラスのBBoxのパラメータとなる。

OpenPCDetの使い方

OpenPCDetではconfigを書くことによって手法を実装することができるが、使うデータセットごとに点群が分布する範囲が異なったりするためconfigも異なる。例えば、kitti_modelsにはKittiデータセットを使う場合のconfigが格納されている。

PV-RCNNを例に使い方を説明する。PV-RCNNの本体は pv_rcnn.py、Kittiデータセットを使う場合のconfigは pv_rcnn.yaml である。

pv_rcnn.pyは Detector3DTemplateの派生クラスであり、pv_rcnn.py自体にはほとんど内容がない。pv_rcnn.pyからわかることは、self.build_networks()という関数でself.module_listを作成し、推論や学習時は、batchをself.module_listの各モジュールに対して渡して処理をさせ、学習時はself.get_training_loss()でlossを計算、推論時はself.post_processing()で後処理をしているということだ。batchはdict形式になっているため、batch内のどのkeyに対して操作をするかを変えることで複雑な処理を行うことができる。

detector3d_template.pyで定義されたDetector3DTemplateを見てみる。build_networks()では、module_topology = ['vfe', 'backbone_3d', 'map_to_bev_module', 'pfe', 'backbone_2d', 'dense_head', 'point_head', 'roi_head']というリストから1つずつmodule名を読み込んで、build_[module名]()という関数を呼んでいる。build_[module名]()では、configの中にmodule名に関する設定が書かれていなければ無視し、書かれていれば設定に従ってモジュールを作成し、model_info_dict['module_list']に追加&self.add_moduleで自身にも追加している。すべてのモジュールを作成した後に、model_info_dict['module_list']を返しているので、pv_rcnn.pyのself.module_listにはこれが代入される。

module_topologyの各要素について説明する。

  • vfe (Voxel Feature Extraction)
    • 点群をvoxel化する際の各voxelの特徴量を計算する
    • PV-RCNNにおいては、Voxel内に含まれる各点の特徴量の平均を計算するだけ
  • backbone_3d
    • voxelから特徴量を計算する
    • PV-RCNNでは3層の3D CNNを用いる
  • map_to_bev_module
    • backbone_3dを適用した特徴量を鳥瞰図に変換する
    • LxHxWxD (L,H,Wが高さ、幅、奥行き方向のvoxel数で、Dが各voxelの特徴量の次元)から 鳥瞰図 H x W x D'に変換し、
      画像と同じように扱えるようにする
  • backbone_2d
    • 鳥瞰図から特徴量を計算する
    • 多くの手法では、map_to_bev_moduleで鳥瞰図に変換した後は2D物体検出と同じような処理が行われる
  • pfe (Point Feature Extraction)
    • 点群をvoxel化せずに、各点ごとの特徴量を計算する
    • PV-RCNNにおいては、点ごとの特徴量をVoxelから計算する部分に対応する
  • dense_head
    • 2-stage物体検出における1st stageの役割で、Anchor boxのパラメータとクラスラベルを推定
  • point_head
    • PV-RCNNにおいては、各点の重要度のようなもの(背景か否か)を計算する部分に対応する
  • roi_head
    • 2-stage物体検出において、1st stageで提案された領域(ROI)の特徴量を計算し、クラススコアとBounding boxのパラメータを再計算する

まとめ

今回はPV-RCNNを例にOpenPCDetの使い方について説明した。一見簡単に実装できるようになっているように見えるが、実際のところはなかなか大変そうではある。

Discussion

ログインするとコメントできます