PCL中基于统计的点云去噪
PCL中进行点云去噪的方法比较多,其中一种基于统计学的方法比较新颖,其函数为StatisticalOutlierRemoval。其原理是将输入数据中每个点到临近点的距离分布情况进行计算,得到各点到它所有临近点的平均距离。假设得到的结果是一个高斯分布,其形状由均值和标准差决定,平均距离在标准范围之外,就被定义为离群点而将其从数据集中删除。
去噪统计效果图可参考如下:
其实现的关键代码进行说明:
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; // 创建去噪对象
sor.setInputCloud(cloud); // 设置需要进行去噪的点云对象
sor.setMeanK(m); // 设置 m 为在进行统计时考虑查询点邻近点数
sor.setStddevMulThresh(1.0); // 设置距离阈值,其公式是 mean + global stddev_mult * global stddev,即mean+1.0*stddev
sor.filter(*cloud_filtered); // 执行去噪计算并保存点到 cloud_filtered
最后附上完整代码,以及不同参数设置时,滤波效果截图
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/visualization/pcl_visualizer.h>
void
main()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("E:\\table_scene_lms400.pcd", *cloud);
pcl::visualization::PCLVisualizer viewer1("Cloud before filtering");
viewer1.setBackgroundColor(0, 0, 0);//黑色背景
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> before_color(cloud, 0, 255, 0);
viewer1.addPointCloud<pcl::PointXYZ>(cloud, before_color, "before filter");
// Create the filtering object
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
sor.setInputCloud(cloud);
sor.setMeanK(50);//近邻点个数50
sor.setStddevMulThresh(0.5);//当判断点的k近邻平均距离(mean distance)大于全局的0.5倍标准差+平均距离(global distances mean and standard)
/*\brief Get the standard deviation multiplier for the distance threshold calculation.
\details The distance threshold will be equal to: mean + stddev_mult * stddev.
Points will be classified as inlier or outlier if their average neighbor distance is below or above this threshold respectively.
*/
/*
By assuming that the resulted distribution is Gaussian with a mean and a standard deviation,
all points whose mean distances are outside an interval defined by
the global distances mean and standard deviation can be considered as outliers and trimmed from the dataset.
*/
sor.filter(*cloud_filtered);
pcl::visualization::PCLVisualizer viewer2("After before filtering");
viewer2.setBackgroundColor(0, 0, 0);//黑色背景
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> after_color(cloud_filtered, 255, 0, 0);
viewer2.addPointCloud<pcl::PointXYZ>(cloud_filtered, after_color, "after filter");
while (!viewer1.wasStopped() || !viewer2.wasStopped())
{
viewer1.spinOnce(1);
viewer2.spinOnce(1);
}
}
其中绿色点云是未进行滤波,红色点云是不同参数滤波后的图。
sor.setStddevMulThresh(0.5);
参数设置过小,导致边界点部分被剔除
sor.setStddevMulThresh(1);参数设置恰当,提取效果理想
sor.setStddevMulThresh(10);参数设置过小,导致部分离群点未被剔除