PCL(Point Cloud Library)のVoxelGridを利用するときの注意点について書きました。

【PCL】VoxelGrid実装時の注意点

点群をダウンサンプリングしたいときに便利なのが、PCLのVoxelGridです。

先日、このVoxelGridを使ってダウンサンプリングを実装しているときに、”あること”に気づかずに、上手くいきませんでした。

この記事では、私がやってしまったミスをご紹介していきます。

そもそもVoxelGridとは

PCLのVoxelGridは、空間をボクセルで区切り、各ボクセル内の点群を、その点群の重心で近似する機能があります。この機能によって、点の数を減らすこと(ダウンサンプリング)ができ、計算コストを減らすためなどに使われます。

▶︎VoxelGridの公式チュートリアル

誤った実装(私のミス)

私がミスに気づかずに、実際に悩まされた実装を以下でご紹介します。一見間違っているように見えませんし、コンパイルも通ります。ただし、これでは上手く機能しません。

やろうとしたこと

ポインターの引数として渡された点群をダウンサンプリングする関数を実装しようとしました。

ソースコード

void Downsampling(pcl::PointCloud<pcl::PointXYZ>::Ptr pc, float leafsize)
{
	pcl::VoxelGrid<pcl::PointXYZ> vg;
	vg.setInputCloud(pc);
	vg.setLeafSize(leafsize, leafsize, leafsize);
	vg.filter(*pc);	//<-ここがNG
}

症状

点の数は減りましたが、原点付近にランダムに散乱する点群が出力されました。

解説

この実装でマズイところは、入力として渡す(setInputCloud)点群と、出力を取得する(filter)点群が同じであるところです。

正しい実装

上記のミスを踏まえて実装し直した関数を以下でご紹介します。この関数では期待通りに点群がダウンサンプリングされました。

ソースコード

void Downsampling(pcl::PointCloud<pcl::PointXYZ>::Ptr pc, float leafsize)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr tmp (new pcl::PointCloud<pcl::PointXYZ>);
	pcl::VoxelGrid<pcl::PointXYZ> vg;
	vg.setInputCloud(pc);
	vg.setLeafSize(leafsize, leafsize, leafsize);
	vg.filter(*tmp);
	*pc = *tmp;
}

解説

入力として渡す点群と、出力を取得する点群を別にする必要があるようです。よって、いったん仮の点群(tmp)に出力してから、それをコピーするように実装しました。

まとめ

  • ×:入力点群と出力先点群が同じ
  • ○:いったん別の点群に出力してコピーする

ダウンサンプリングの関連記事

【PCL】VoxelGridとApproximateVoxelGridの違い

さいごに

PCLのVoxelGridに関して、私が実際にやってしまったミスを通して、実装時の注意点をまとめてみました。参考になれば幸いです。


以上です。

Ad.