Removing outliers using a StatisticalOutlierRemoval filter

StatisticalOutlierRemoval(統計的外れ値削除)フィルタを使用した外れ値の削除

出典: http://pointclouds.org/documentation/tutorials/statistical_outlier.php#statistical-outlier-removal

このチュートリアルでは、外れ値のようなノイズの多い測定値を統計的分析技術を用いて点群データセットからを削除する方法を学習する。

YouTubeのビデオ: https://youtu.be/RjQPp2_GRnI

背景

レーザスキャンは、典型的には様々な密度の点群データセットを生成する。そこで疎らではあるが測定誤差が、結果を破壊的にする異常値をもたらす。このことは、表面の法線や曲率の変化などの局所点群の特性の推定を複雑にし、誤った値につながり、点群の位置合わせに失敗する可能性をもたら。これらの不規則性のいくつかは、各点の近傍について統計分析を行い、特定の基準を満たさないものをトリミングすることによって解決することができる。我々の疎な外れ値の除去方法は、入力データセット内の点間距離の分布の計算に基づいている。各点について、すべての近隣点までの平均距離を計算する。得られた分布が平均と標準偏差を有するガウス分布であると仮定することにより、平均距離がグローバル距離平均と標準偏差によって定義される閾値の外にあるすべての点は異常値とみなされ、データセットから削除される。

次の図は、疎な外れ値の解析と削除の効果を示すものである。元のデータセットを左側に、結果を右側に表示する。この図は、フィルタリングの前後の点近傍における平均$k$最近傍距離を示す。

C++コード

まず https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_lms400.pcd をダウンロードせよ。次に以下のコードを statistical_removal.cpp としてセーブしコンパイルせよ。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>

int
main (int argc, char** argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);

  // Fill in the cloud data
  pcl::PCDReader reader;
  // Replace the path below with the path where you saved your file
  reader.read<pcl::PointXYZ> ("table_scene_lms400.pcd", *cloud);

  std::cerr << "Cloud before filtering: " << std::endl;
  std::cerr << *cloud << std::endl;

  // Create the filtering object
  pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
  sor.setInputCloud (cloud);
  sor.setMeanK (50);
  sor.setStddevMulThresh (1.0);
  sor.filter (*cloud_filtered);

  std::cerr << "Cloud after filtering: " << std::endl;
  std::cerr << *cloud_filtered << std::endl;

  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.pcd", *cloud_filtered, false);

  sor.setNegative (true);
  sor.filter (*cloud_filtered);
  writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *cloud_filtered, false);

  return (0);
}

実行ファイルができたら以下を実行せよ:

$ ./statistical_removal

その結果、次のようなものが表示される:

Cloud before filtering:
header:
seq: 0
stamp: 0.000000000
frame_id:
points[]: 460400
width: 460400
height: 1
is_dense: 0

Cloud after filtering:
header:
seq: 0
stamp: 0.000000000
frame_id:
points[]: 429398
width: 429398
height: 1
is_dense: 0