点云处理系列 - 点云滤波(三)

1. 为什么要滤波?

通常我们获取的点云数据中包含噪声,噪声会影响点云的特征提取、配准和语义处理。

点云需要处理的主要情况包括:

  • 数据量过大,不易于处理,需要进行下采样

  • 通常由遮挡引起的离群点,需要去除

  • 点云数据的密度不均匀需要平滑

  • 噪声数据需要去除

在获取点云数据时,由于设备精度、操作者经验、环境因素等带来的影响,点云数据中将不可避免地出现一些噪声点。这便需要我们对点云进行后处理。

在点云的处理流程中,滤波处理作为预处理的第一步,往往对后续处理管道影响最大,只有在滤波预处理中将噪声点、离群点、空洞等按照后续处理定制,才能更好地进行配准、特征提取、曲面重建、可视化等。

PCL中的点云处理模块提供了很多灵活实用的滤波处理算法,例如双边滤波、高斯滤波、条件滤波、直通滤波、基于随机采样一致性滤波等。

PCL中总结了几种需要进行点云滤波处理的情况,这几种情况如下:

  • (1)点云数据密度不规则需要平滑;

  • (2)因为遮挡等问题造成离群点需要去除;

  • (3)大量数据需要进行下采样;

  • (4)噪音数据需要去除。

对应的方法主要如下:

  • (a) 按具体给定的规则限制过滤去除点。

  • (b)通过常用滤波算法修改点的部分属性。

  • ©对数据进行下采样。

PCL中对常规的滤波手段进行了良好地封装,主要的滤波器有直通滤波、体素法滤波、统计滤波、条件滤波等。组合使用完成任务,效果更佳。

1、如果是线结构光的采集方式得到的点云,则沿z向的分布较广,但沿x、y方向的分布则处于有限的范围内。此时,可采用直通滤波,确定x或者y方向的范围,快速裁剪离群点。

2、如果使用高分辨率相机等设备对点云进行采集,则点云往往较为密集。过多的点云数据对后续的分割工作带来困难。体素法滤波可以达到下采样的同时不破坏点云本身几何结构的功能。

3、统计滤波器用于去除明显的离群点(离群点往往由噪声引入)。噪声信息属于无用信息,信息量较小。所以离群点表达的信息可以忽略不计。考虑到离群点的特征,则可以定义某处点云小于某个密度,既点云无效。计算每个点到其最近的k个点平均距离。则点云中所有点的距离应构成高斯分布。给定均值与方差,可剔除3∑之外的点。

4、半径滤波器与统计滤波器相比更加简单粗暴。以某点为中心画一个圆计算落在该圆中点的数量,当数量大于给定值时,则保留该点,数量小于给定值则剔除该点。此算法运行速度快,依序迭代留下的点一定是最密集的,但是圆的半径和圆内点的数目都需要人工指定。

接下来,以demo的形式简单介绍一下PCL中关于直通滤波和体素法滤波的功能及函数使用方法。

2. 直通滤波

直通滤波功能:指定字段,指定坐标范围进行剪裁,可以选择保留范围内的点或者范围外的点。

//相关的头文件声明
#include <iostream> //标准C++库中输入输出类相关头文件
#include <pcl/io/pcd_io.h> //pcd读写类相关头文件
#include "pcl/point_cloud.h"
#include <pcl/point_types.h> //PCL中支持的点类型头文件
#include<pcl/common/common.h>
#include <pcl/filters/passthrough.h>

int main()
{
//创建一个PointCloud<PointXYZ> boost 共享指针并进行实例化
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

//滤波后的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);

//pcd文件路径
std::string pcd_in = "../rops_cloud.pcd";
std::string pcd_out = "../rops_cloud_passthroughed.pcd";
if (pcl::io::loadPCDFile<pcl::PointXYZ>(pcd_in,*cloud)==-1)
//打开点云文件
{
PCL_ERROR("Couldn't read file test_pcd.pcd\n");
return(-1);
}

pcl::PointXYZ minPt, maxPt;
pcl::getMinMax3D(*cloud,minPt,maxPt);

// 创建滤波器对象
pcl::PassThrough<pcl::PointXYZ> pass; //设置滤波器对象
pass.setInputCloud(cloud);//设置输入点云
pass.setFilterFieldName("z"); //设置过滤时所需要的点云类型的z字段
pass.setFilterLimits(minPt.z+0.2, maxPt.z - 0.1); //设置在过滤字段上的范围
pass.setFilterLimitsNegative(false); //设置保留范围内的还是过滤掉范围内的
pass.filter(*cloud_filtered); //执行滤波

//将数据存储到磁盘
pcl::io::savePCDFileASCII(pcd_out,*cloud_filtered);

return (0);
}

直通滤波的演示效果图,如下图所示(gif 原图,详见:https://zhuanlan.zhihu.com/p/64226544?utm_source=wechat_session )。

在这里插入图片描述

在这里插入图片描述

3. 体素法滤波

体素法滤波,即减少点的数量,减少点云数据,并同时保持点云的形状特征,在提高配准、曲面重建、形状识别等算法速度中非常实用。 PCL实现的VoxelGrid类通过输入的点云数据创建一个三维体素栅格(可把体素栅格想象为微小的空间三维立方体的集合),然后在每个体素(即三维立方体)内,用体素中所有点的重心来近似显示体素中其他点,这样该体素内所有点就用一个重心点最终表示,对于所有体素处理后得到过滤后的点云。 优缺点:这种方法比用体素中心来逼近的方法更慢,但它对于采样点对应曲面的表示更为准确。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>

int main (int argc, char** argv)
{
    pcl::PCLPointCloud2::Ptr
    cloud(new pcl::PCLPointCloud2());
    pcl::PCLPointCloud2::Ptr
    cloud_filtered(new pcl::PCLPointCloud2());

    // 填入点云数据
    pcl::PCDReader reader; //点云读取对象
    
    // 把路径改为自己存放文件的路径,或者将该文件与生成的可执行文件放在同一目录下
    reader.read ("../table_scene_lms400.pcd", *cloud); // 读取点云文件中的数据到cloud对象

    std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height << " data points (" << pcl::getFieldsList(*cloud) << ")." <<std::endl;

    pcl::VoxelGrid<pcl::PCLPointCloud2> sor; // 创建滤波器对象
    sor.setInputCloud (cloud); //给滤波器对象设置需要过滤的点云
    sor.setLeafSize (0.01f, 0.01f, 0.01f); //设置滤波时创建的体素大小为1cm立方体
    sor.filter (*cloud_filtered); //执行滤波处理

    std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points (" << pcl::getFieldsList (*cloud_filtered) << ").";

    //将数据写入磁盘
    pcl::PCDWriter writer;
    writer.write ("../table_scene_lms400_downsampled.pcd", *cloud_filtered, Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), false);
    return (0);
    
}

以上代码运行结果如下图1. 将点云结果放在CloudCampare中对比显示如图2.

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Adunn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值