基於統計分析的StatisticalOutlierRemoval濾波器
該濾波器主要用於移除離羣點,那麼什麼樣的點是離羣點呢?計算點雲中每個點與其所有臨近點的平均距離,並假設其結果爲一形狀由均值和標準差決定的高斯分佈,若有某點平均距離在標準範圍(由全局距離平均值和方差定義)之外,則定義爲離羣點,並將其從數據集中去除掉,這也是本濾波器的內在處理邏輯,即對每個點的鄰域進行一個統計分析。
激光掃描通常會產生密度不均勻的點雲數據,另外,測量中的誤差也會產生稀疏的離羣點。
代碼如下
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h> i
nt 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>);
pcl::PCDReader reader; // 定義讀取對象
reader.read<pcl::PointXYZ>("table_scene_lms400.pcd", *cloud); // 讀取點雲文件
std::cerr << "Cloud before filtering: " << std::endl; std::cerr << *cloud << std::endl;
/*創建濾波器,對每個點分析的臨近點的個數設置爲50 ,並將標準差的倍數設置爲1 這意味着如果一 個點的距離超出了平均距離一個標準差以上,則該點被標記爲離羣點,並將它移除,存儲起來*/
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; //創建濾波器對象
sor.setInputCloud(cloud); //設置待濾波的點雲
sor.setMeanK(50); //設置在進行統計時考慮查詢點臨近點數
sor.setStddevMulThresh(1.0); //設置判斷是否爲離羣點的閥值 sor.filter(*cloud_filtered);
//執行濾波處理保存內點到在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);
//使用同樣的參數再次調用該濾波器,但是利用函數setNegative設置使輸出取外點,以獲取離羣點,並存儲
sor.setNegative(true);
sor.filter(*cloud_filtered);
writer.write<pcl::PointXYZ>("table_scene_lms400_outliers.pcd", *cloud_filtered, false);
return (0);
}
參見https://github.com/mariusmuja/flann/issues/386