点云滤波介绍及统计滤波实现

1 点云为什么需要滤波

    在获取点云数据时,由于设备的精度、周围环境等因素,点云数据中将不可避免的出现一些噪点,只有在滤波预处理中将噪点、离群点、孔洞按照后续处理定制,才能更好的进行配准,特征提取,曲面重建等操作。
    我们可以很明显的看到下图的右下方有很多离散的点,而这些噪声点对于我们后续的操作完全没有任何意义,甚至会产生不利的影响。
pcd点云可视化

1.1 哪些情况需要滤波

  • 点云数据密度不均匀
  • 因为遮挡等问题造成离群点需要去除
  • 大量数据需要下采样
  • 噪声数据需要去除

2 几种现有的滤波方法及其适用领域

2.1 直通滤波

    对于在空间分布有一定空间特征的点云数据,比如使用线结构光扫描的方式采集点云,沿z向分布较广,但x,y向的分布处于有限范围内。此时可使用直通滤波器,确定点云在x或y方向上的范围,可较快剪除离群点,达到第一步粗处理的目的。(在Z轴方向除去多余的点)。

2.2 体素滤波

    体素的概念类似于像素,使用AABB包围盒将点云数据体素化,一般体素越密集的地方信息越多,噪音点及离群点可通过体素网格去除。另一方面如果使用高分辨率相机等设备对点云进行采集,往往点云会较为密集。过多的点云数量会对后续分割工作带来困难。体素滤波器可以达到向下采样同时不破坏点云本身几何结构的功能。

2.3 统计滤波

    考虑到离群点的特征,则可以定义某处点云小于某个密度,既点云无效。计算每个点到其最近的k个点平均距离。则点云中所有点的距离应构成高斯分布。给定均值与方差,可剔除3∑之外的点。

2.4 条件滤波

    条件滤波器通过设定滤波条件进行滤波,有点分段函数的味道,当点云在一定范围则留下,不在则舍弃。

2.5 半径滤波

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

3 统计滤波的实现

    第二节所列出的5种滤波方法在pcl库中都有相应封装好的函数,直接进行调用就能对pcd文件进行滤波操作。
    下面是统计滤波具体实现代码(cpp源文件):

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>	//统计滤波器头文件

//统计滤波器
int 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>(argv[1], *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);                    	//存储
  
	std::cerr << "Cloud after filtering: " << std::endl;
	std::cerr << *cloud_filtered << std::endl;
	
	//保存滤波后的点云
	pcl::PCDWriter writer;
	writer.write<pcl::PointXYZ>("after_filter.pcd", *cloud_filtered, false);
 
	//sor.setNegative(true);
	//sor.filter(*cloud_filtered);
	//writer.write<pcl::PointXYZ>("1_outliers.pcd", *cloud_filtered, false);
 
	return (0);
}

    本人所使用的编译环境为Ubuntu16.04 + ros-kinetic(ros自带pcl1.7)+ roboware(IDE),所以只需要在CMakeLists.txt中进行库的调用就能使用pcl库了。这里强烈推荐使用roboware,它能帮我们自动生成相应的CMakeLists文件,很方便我们进行库文件管理,节省很多开发时间。考虑到普适性,这里给出适用于只安装了pcl库的版本。
    CMakeLists.txt文件代码:

cmake_minimum_required( VERSION 2.8 )

PROJECT(statisticalOutlierRemoval)

set( CMAKE_BUILD_TYPE "Release" )

find_package(PCL 1.7 REQUIRED COMPONENTS)

include_directories(${PCL_INCLUDE_DIRS})

link_directories(${PCL_LIBRARY_DIRS})

add_definitions(${PCL_DEFINITIONS})


add_executable(statisticalOutlierRemoval
  statisticalOutlierRemoval.cpp
)

target_link_libraries(statisticalOutlierRemoval
  ${PCL_LIBRARIES}
)

写好两个文件(cpp源文件与CMakeLists文件)后放入同一文件夹下
源文件
然后执行如下操作:

mkdir build
cd build
cmake …
make

生成相应的可执行文件如下图:
在这里插入图片描述
在此文件夹下打开终端执行该文件:

./statisticalOutlierRemoval 1.pcd

在这里插入图片描述
通过终端的显示我们可以看到有将近1W个点被过滤掉,最后我们通过以下命令进行可视化(终端路径不变):

pcl_viewer 1.pcd
pcl_viewer after_filter.pcd

在这里插入图片描述
    通过对比我们可以发现,在经过统计滤波操作后,原图片中大量的离散的噪点被去除掉,虽然剩下的点云仍然有我们不需要也不希望存在的部分,但是过滤掉一些噪点仍然有助于我们后续的处理。
    如果该文章对您有帮助,请顺便点个赞,如果文中有错误的地方,请提出并指正!

  • 10
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值