【pcl入门教程滤波系列】之passThrough滤波

简介

  最近开始接触点云的数据处理模块,点云做分割、检测、识别之前需要做大量的预处理操作。直通滤波算作最为简单、粗暴的一种滤波方式,就是直接对点云的X、Y、Z轴的点云坐标约束来进行滤波,可以约束只在Z轴,或者XYZ三个坐标轴共同约束来达到点云滤波效果。下面直接上代码进行简单解释:

代码示例

  下面这段代码是直通滤波最为频繁使用的函数:该简单示例通过读取pcd点云数据进行操作,最后保存为pcd文件。通过使用cloudcompare软件来进行查看直通滤波后的效果。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.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>);

	// Fill in the cloud data
	pcl::PCDReader reader;
	reader.read("16line.pcd", *cloud);
	std::cerr << "Cloud before filtering: " << cloud->points.size() << std::endl;
	// Create the filtering object
	pcl::PassThrough<pcl::PointXYZ> pass; // 声明直通滤波
	pass.setInputCloud(cloud); // 传入点云数据
	pass.setFilterFieldName("z"); // 设置操作的坐标轴
	pass.setFilterLimits(0.0, 3.0); // 设置坐标范围
	// pass.setFilterLimitsNegative(true); // 保留数据函数
	pass.filter(*cloud_filtered);  // 进行滤波输出

	std::cerr << "Cloud after filtering: " << cloud_filtered->points.size() << std::endl;

	// save filterd data 
	pcl::PCDWriter writer;
	writer.write("16line_filtered.pcd", *cloud_filtered, false);

	return 0;
}

设置过滤x或者y轴方向的部分代码:

	// Create the filtering object
	pcl::PassThrough<pcl::PointXYZ> pass;
	pass.setInputCloud(cloud);
	pass.setFilterFieldName("x");
	pass.setFilterLimits(-5.0, 5.0);
	// pass.setFilterLimitsNegative(true);
	pass.filter(*cloud_filtered2);


	pass.setInputCloud(cloud_filtered2);
	pass.setFilterFieldName("y");
	pass.setFilterLimits(-5.0, 5.0);
	pass.filter(*cloud_filtered3);
实验结果可视化

下面简单贴出直通滤波过滤的结果点云:

原始点云可视化
x轴点云范围限制[-5.0, 5.0]

下面图片点云过滤是上一张图片的全局剩余的点云,这里在代码中的pass.setFilterLimitsNegative(true);就是这个功能作用,是否保存滤波的限制范围内的点云,默认为false,保存限制范围点云,true时候是相反。

x轴点云范围限制[-5.0, 5.0]
y轴点云范围限制[-5.0, 5.0]

  在查阅学习pcl直通滤波的过程中,发现网上所说 的关于不仅限于对单一坐标轴的过滤,其实主要就是再一次进行目标坐标轴过滤即可,通过重复使用直通滤波就可以进行三维区间的滤波。下面贴上代码部分,只是简单的增加一些变量和重复操作,并无特别复杂的地方:

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.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>);

	// Fill in the cloud data
	pcl::PCDReader reader;
	reader.read("16line.pcd", *cloud);

	std::cerr << "Cloud before filtering: " << cloud->points.size() << std::endl;

	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered2(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered3(new pcl::PointCloud<pcl::PointXYZ>);

	// Create the filtering object
	pcl::PassThrough<pcl::PointXYZ> pass;
	pass.setInputCloud(cloud);
	pass.setFilterFieldName("x");
	pass.setFilterLimits(-5.0, 5.0);
	// pass.setFilterLimitsNegative(true);
	pass.filter(*cloud_filtered2);
	// filter range Y-axis
	pass.setInputCloud(cloud_filtered2);
	pass.setFilterFieldName("y");
	pass.setFilterLimits(-5.0, 5.0);
	pass.filter(*cloud_filtered3);
    // filter range Z-axis
	pass.setInputCloud(cloud_filtered3);
	pass.setFilterFieldName("z");
	pass.setFilterLimits(-0.5, 3.0);
	pass.filter(*cloud_filtered);

	std::cerr << "Cloud after filtering: " << cloud_filtered->points.size() << std::endl;

	// save filterd data 
	pcl::PCDWriter writer;
	writer.write("16line_filtered.pcd", *cloud_filtered, false);

	return 0;
}
xy轴点云范围限制[-5.0, 5.0]

  通过简单添加直通滤波的几行代码,就可以选择是只是过滤XY轴的范围,还是XYZ三维空间的范围。其实就是接着上一次直通滤波的结果进行下一个坐标轴的过滤。

xyz轴点云范围限制
源码部分功能浅析

具体函数模块功能主要介绍:

pcl::PassThrough官方API接口有两种数据结构模式供你使用(在声明直通滤波时候):PointT或者是pcl::PCLPointCloud2

官方给出的示例:

    * pcl::PassThrough<PointType> ptfilter (true); // Initializing with true will allow us to extract the removed indices
    * ptfilter.setInputCloud (cloud_in);
    * ptfilter.setFilterFieldName ("x");
    * ptfilter.setFilterLimits (0.0, 1000.0);
    * ptfilter.filter (*indices_x);
    * // The indices_x array indexes all points of cloud_in that have x between 0.0 and 1000.0
    * indices_rem = ptfilter.getRemovedIndices ();
    * // The indices_rem array indexes all points of cloud_in that have x smaller than 0.0 or larger than 1000.0
    * // and also indexes all non-finite points of cloud_in
    * ptfilter.setIndices (indices_x);
    * ptfilter.setFilterFieldName ("z");
    * ptfilter.setFilterLimits (-10.0, 10.0);
    * ptfilter.setNegative (true);
    * ptfilter.filter (*indices_xz);
    * // The indices_xz array indexes all points of cloud_in that have x between 0.0 and 1000.0 and z larger than 10.0 or smaller than -10.0
    * ptfilter.setIndices (indices_xz);
    * ptfilter.setFilterFieldName ("intensity");
    * ptfilter.setFilterLimits (FLT_MIN, 0.5);
    * ptfilter.setNegative (false);
    * ptfilter.filter (*cloud_out);
    * // The resulting cloud_out contains all points of cloud_in that are finite and have:
    * // x between 0.0 and 1000.0, z larger than 10.0 or smaller than -10.0 and intensity smaller than 0.5.
小结

  直通滤波比较简单粗暴的滤除点云的方式,实际运用中一般是作为第一步来进行点云的初步筛选与限制。可能你会觉得使用直通滤波不太智能化,要是对多个坐标轴进行滤波要操作多次的过程,那么你可以选择使用条件滤波来满足你的需求。下一篇就会介绍条件滤波。

参考

https://pcl-tutorials.readthedocs.io/en/pcl-1.11.0/passthrough.html#passthrough

  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!以下是一个简单的示例代码,演示了如何使用PCL库进行点云滤波: ```cpp #include <iostream> #include <pcl/point_types.h> #include <pcl/filters/passthrough.h> int main() { // 创建点云对象 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(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 = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f); } std::cout << "点云原始大小:" << cloud->size() << std::endl; // 创建滤波器对象 pcl::PassThrough<pcl::PointXYZ> pass; pass.setInputCloud(cloud); pass.setFilterFieldName("z"); pass.setFilterLimits(0.0, 1.0); // 设置过滤范围 // 执行滤波操作 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); pass.filter(*cloud_filtered); std::cout << "滤波后大小:" << cloud_filtered->size() << std::endl; return 0; } ``` 这个示例首先创建了一个包含随机生成的点云数据的PointCloud对象,然后使用PassThrough滤波器对点云进行过滤。在示例中,我们设置了z轴方向上的过滤范围为0.0到1.0之间的点云将会被保留下来,其他的点云将会被过滤掉。最后,输出了滤波后点云的大小。 请确保您已经正确安装了PCL库,并在编译时链接了相应的库文件。希望这能帮到您!如有更多问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值