官方文档:https://pcl-tutorials.readthedocs.io/en/latest/statistical_outlier.html#statistical-outlier-removal
理论:
激光扫描通常会生成不同点密度的点云数据集。此外,测量误差会导致稀疏的异常值,从而进一步破坏结果。这会使局部点云特征(例如表面法线或曲率变化)的估计复杂化,从而导致错误的值,进而可能导致点云配准失败。通过对每个点的邻域进行统计分析,并对不符合特定条件的部分进行修整,可以解决其中一些不规则现象
稀疏离群值的消除基于输入数据集中点到邻居距离的分布的计算。对于每个点,我们计算从它到所有相邻点的平均距离。通过假设结果分布是具有均值和标准差的高斯分布,可以将其平均距离在由全局距离均值和标准差定义的区间之外的所有点视为离群值并从数据集中进行修剪。
代码实现:
#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/statistical_outlier_removal.h>
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
using namespace std;
/**
*
*/
int main(int argc, char *argv[]) {
PointCloud::Ptr cloud(new PointCloud);
PointCloud::Ptr cloud_filtered(new PointCloud);
pcl::PCDReader reader;
reader.read<PointT>("./data/table_scene_lms400_downsample.pcd", *cloud);
// 创建统计学离群点移除过滤器
pcl::StatisticalOutlierRemoval<PointT> sor;
sor.setInputCloud(cloud);
// 设置过滤邻域K
sor.setMeanK(50);
// 设置标准差的系数, 值越大,丢掉的点越少
sor.setStddevMulThresh(1.0f);
sor.filter(*cloud_filtered);
// 保存去掉离群点之后的点云
pcl::PCDWriter writer;
writer.write("./data/table_scene_lms400_inliers.pcd", *cloud_filtered);
// 取反
sor.setNegative(true);
sor.filter(*cloud_filtered);
// 保存被去掉离群点
writer.write("./data/table_scene_lms400_outliers.pcd", *cloud_filtered);
}
结果:
双屏对比
pcl_viewer -multiview 1 table_scene_lms400.pcd table_scene_lms400_inliers.pcd
显示: