PCL学习笔记——点云滤波(一)

版权声明:转载请注明出处,谢谢! https://blog.csdn.net/weixin_44420419/article/details/88848845

本文主要借鉴于博主Being_young的文章https://blog.csdn.net/u013019296/article/details/70052319

一. 直通滤波PassThrough

对指定某一维度直接进行筛选过滤,实际上是一个空间切割,也就是只保留设定范围内的点,超出边界的就过滤掉了。

代码如下:

#include <iostream>
#include <ctime>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
int
main(int argc, char** argv)
{
	srand(time(0));
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
	//填入点云数据
	cloud->width = 5;   //设置点云宽度或数量,此处为数量
	cloud->height = 1;  //设置点云高度或标准,此处为无序点云
	cloud->points.resize(cloud->width * cloud->height);
	for (size_t i = 0; i < cloud->points.size(); ++i)  //填充数据,由随机数产生
	{
		cloud->points[i].x = rand() / (RAND_MAX + 1.0f) - 0.5;    
		cloud->points[i].y = rand() / (RAND_MAX + 1.0f) - 0.5;
		cloud->points[i].z = rand() / (RAND_MAX + 1.0f) - 0.5;
	}
	std::cerr << "Cloud before filtering: " << std::endl;  //打印数据
	for (size_t i = 0; i < cloud->points.size(); ++i)
		std::cerr << "    " << cloud->points[i].x << " "
		<< cloud->points[i].y << " "
		<< cloud->points[i].z << std::endl;
	/************************************************************************************
  创建直通滤波器的对象,设立参数,滤波字段名被设置为Z轴方向,可接受的范围为(0.0,1.0)
  即将点云中所有点的Z轴坐标不在该范围内的点过滤掉或保留,这里是过滤掉,由函数setFilterLimitsNegative设定
  ***********************************************************************************/
	// 创建滤波器对象
	pcl::PassThrough<pcl::PointXYZ> pass;
	pass.setInputCloud(cloud);              //设置输入点云
	pass.setFilterFieldName("z");           //设置过滤时所需要点云类型的Z字段
	pass.setFilterLimits(0.0, 1.0);         //设置在过滤字段的范围
	pass.setFilterLimitsNegative(false);    //设置保留(false)范围内还是过滤掉(true)范围内(对范围取反)
	pass.filter(*cloud_filtered);           //执行滤波,保存过滤结果在cloud_filtered

	std::cerr << "Cloud after filtering: " << std::endl;  //打印结果
	for (size_t i = 0; i < cloud_filtered->points.size(); ++i)
		std::cerr << "    " << cloud_filtered->points[i].x << " "
		<< cloud_filtered->points[i].y << " "
		<< cloud_filtered->points[i].z << std::endl;

	return (0);
}

(此处感谢CSDN博主Being_young)

其中滤波器对象为:

pcl::PassThrough<pcl::PointXYZ> pass;
	pass.setInputCloud(cloud);              //设置输入点云
	pass.setFilterFieldName("z");           //设置过滤时所需要点云类型的Z字段
	pass.setFilterLimits(0.0, 1.0);         //设置在过滤字段的范围
	pass.setFilterLimitsNegative(false);    //设置保留(false)范围内还是过滤掉(true)范围内(对范围取反)
	pass.filter(*cloud_filtered);           //执行滤波,保存过滤结果在cloud_filtered

这里cloud就是需要过滤的点云,cloud_filtered就是过滤后的点云,使用setFilterFieldName来设置过滤Z轴,用setFilterLimits来设置范围,也就是只保留z坐标在0-1之间的点,其他的全部不要了。

注意此行代码:

pass.setFilterLimitsNegative(false); 

代表了是否显示被过滤掉的点,如果设置为true则将被过滤,设置为false则范围内将被保留,默认是false(即保留时可以直接注释掉此行代码)。

运行结果如下:
如图所示

二. 使用VoxelGrid滤波器对点云进行下采样

使用体素化网格方法实现下采样,即减少点的数量 减少点云数据,并同时保存点云的形状特征,在提高配准,曲面重建,形状识别等算法速度中非常实用,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());

	//点云对象的读取,对应的pcd文件放在与程序名相同的文件内
	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) << ").";

	/******************************************************************************
	创建一个叶大小为1cm的pcl::VoxelGrid滤波器,
	**********************************************************************************/
	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("squ4r filter.pcd", *cloud_filtered, Eigen::Vector4f::Zero(), Eigen::Quaternionf::Identity(), false);
	
	return (0);
}


运行结果如下(程序运行时间较长,耐心等待):
在这里插入图片描述
原点云数据为460400个,滤波后为41049个,而实际效果可以发现点的密度大小与整齐程度不同,虽然处理后的数据量大大减小,但是很明显所含有的形状特征和空间结构信息与原始点云差不多(可视化还不会,所以没有效果图。。)。

未完待续。

猜你喜欢

转载自blog.csdn.net/weixin_44420419/article/details/88848845