基于统计分析的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