PCL点云滤波去噪

为什么要对点云滤波?

一般下面这几种情况需要进行点云滤波处理:
(1)  点云数据密度不规则需要平滑
(2) 因为遮挡等问题造成离群点需要去除
(3) 大量数据需要下采样
(4) 噪声数据需要去除

     点云中的噪声点对后续操作的影响比较大。就像盖房子一样,地基有很多瑕疵,如果不加以处理最终可能会导致整个房子坍塌的。不过别担心,PCL中有一个专门的点云滤波模块,可以将噪声点去除,还可以进行点云压缩等操作,非常灵活实用,例如:双边滤波,统计滤波,条件滤波,随机采样一致性滤波等。这样才能够更好的进行配准,特征提取,曲面重建,可视化等后续应用处理。PCL中关于点云滤波的所有函数都在这里:

http://docs.pointclouds.org/trunk/group__filters.html

一般来说,滤波对应的方案有如下几种:
(1)按照给定的规则限制过滤去除点
(2) 通过常用滤波算法修改点的部分属性
(3)对数据进行下采样

1.点云下采样:

      点云的数目越大,储存、操作都是个大问题!通过按一定的规则从里面抽取有代表性的样本,可以代替原来的样本,节省计算开销,这个下采样PCL中有专门的类,叫做

class  pcl::ApproximateVoxelGrid< PointT >

       比较适合对海量的点云在处理前进行数据压缩,而且可以在特征提取等处理中选择合适的体素(voxel)大小等参数,提高算法效率。该函数对输入的点云数据创建一个三维体素栅格,每个体素内用体素中所有点的重心来近似显示体素中其他点,这样该体素内所有点都用一个重心点最终表示。它的优点是可以在下采样的时候保存点云的形状特征。

关键代码:

pcl::VoxelGrid<PointT> downSampled;  //创建滤波对象
downSampled.setInputCloud (cloud);            //设置需要过滤的点云给滤波对象
downSampled.setLeafSize (0.01f, 0.01f, 0.01f);  //设置滤波时创建的体素体积为1cm的立方体,三个参数表示体素栅格叶大小,分别表示体素在XYZ方向的尺寸
downSampled.setDownsampleAllData(bool downsample)//设置是否对所有的字段进行下采样
downSampled.filter (*cloud_downSampled);           //执行滤波处理,存储输出

setDownsampleAllData的意思是:点云有不同的类型,比如 PointXYZ,有的是PointXYZRGB,还有其他类型,也就是一个点包含多种不同信息,比如空间位置XYZ,颜色信息RGB,或者强度信息等,如果想要对所有信息(字段)下采样则设置为true,只对XYZ下采样的话设置为false。下采样结果如下图所示。

2.去除点云的离群点

       离群点对应的英文是outliers,也叫外点,就是明显偏离“群众”的点,比如我们用激光扫描一面平坦的墙壁,正常情况下得到的应该是差不多也位于同一个平面的点云,但是由于设备测量误差等原因,会产生少量脱离群众的空间点,离本来的墙壁过远,我们就叫这部分点为离群点。离群点会使局部点云特征(如表面法线或曲率变化)的估计复杂化,从而导致错误的值,从而可能导致点云配准失败。列举两个常用的去除离群点的类:StatisticalOutlierRemoval 、RadiusOutlierRemoval

2.1   StatisticalOutlierRemoval 

顾名思义,使用统计分析技术,从一个点云数据中集中移除测量噪声点。对每个点的邻域进行统计分析,剔除不符合一定标准的邻域点。具体来说:

1.对于每个点,计算它到所有相邻点的平均距离。假设得到的分布是高斯分布,我们可以计算出一个均值 μ 和一个标准差 σ;

2.这个邻域点集中所有点与其邻域距离大于μ + std_mul * σ 区间之外的点都可以被视为离群点,并可从点云数据中去除。std_mul 是标准差倍数的一个阈值,可以自己指定。

pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;   //创建滤波器对象
sor.setInputCloud (cloud);                           //设置待滤波的点云
sor.setMeanK (50);                               //设置在进行统计时考虑的临近点个数
sor.setStddevMulThresh (1.0);                      //设置判断是否为离群点的阀值,用来倍乘标准差,也就是上面的std_mul
sor.filter (*cloud_filtered);                    //滤波结果存储到cloud_filtered

     如上代码所示,先创建统计分析滤波器,然后设置滤波器输入是 cloud,也就是我们待处理的点云,然后设置对每个点分析的临近点的个数设置为50 ,并将标准差的倍数设置为1,  这意味着如果一个点的距离超出了平均距离加上一个标准差以上,则该点被标记为离群点,并将它移除。最后统计分析滤波后,输出的结果就是cloud_filtered。

2.2  RadiusOutlierRemoval

      一个比较简单常用的方法就是根据空间点半径范围临近点数量来滤波,对应的类名是 RadiusOutlinerRemoval,这个很容易理解,它的滤波思想非常直接,就是在点云数据中,设定每个点一定半径范围内周围至少有足够多的近邻,不满足就会被删除。比如你指定了一个半径d,然后指定该半径内至少有1个邻居,那么下图中只有黄色的点将从点云中删除。如果指定了半径内至少有2个邻居,那么黄色和绿色的点都将从点云中删除。

                                                 

pcl::RadiusOutlierRemoval<pcl::PointXYZ> pcFilter;  //创建滤波器对象
pcFilter.setInputCloud(cloud);             //设置待滤波的点云
pcFilter.setRadiusSearch(0.8);               // 设置搜索半径
pcFilter.setMinNeighborsInRadius(2);      // 设置一个内点最少的邻居数目
pcFilter.filter(*cloud_filtered);        //滤波结果存储到cloud_filtered

2.3  FastBilateralFilter、BilateralFilter

       双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点 。双边滤波器的好处是可以做边缘保存。对于双边滤波不只用在图像,很多时候也会在处理点云数据的时候使用,对点云数据进行光滑处理

        双边 滤 波 算 法主要用于对点云数据的小尺度起伏噪声进行平滑光顺。双边滤波应用于三维点云数据去噪,既有效地对空间三维模型表面进行降噪,又可以保持点云数据中的几何特征信息,避免三维点云数据被过渡光滑。在点云模型中设点p 的k 邻域点集及单位法向量分别为Nk与ni ,双边滤波可以定义为:

                                                

                    

                             

    WC,WS 分别表示双边滤波函数的空间域和频率域权重函数,它们分别控制着双边滤波的平滑程度和特征保持程度。’<n,pj-pi>为n与pj-pi的内积,nj,ni 为点 的 法 向量。

                      

 pcl::PointCloud<pcl::PointXYZ>::Ptr xyz (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::FastBilateralFilter<pcl::PointXYZ> fbf;
  fbf.setInputCloud (xyz);
  fbf.setSigmaS (sigma_s);//设置双边滤波器用于空间邻域/窗口的高斯的标准偏差

  fbf.setSigmaR (sigma_r);//设置高斯的标准偏差用于控制相邻像素由于强度差异而下降多少(在我们的情况下为深度)
  pcl::PointCloud<pcl::PointXYZ> xyz_filtered;
  fbf.filter (xyz_filtered);

注意:能使用双边滤波的点云必须得包含强度字段。现有的points类型中,只有PointXYZI和PointXYZINormal有强度信息。FastBilateralFilter只适用于有序点云。

from:https://mp.weixin.qq.com/s/9pxff6LwcecDHsx4kI34sw

猜你喜欢

转载自blog.csdn.net/qq_30815237/article/details/86294496
今日推荐