本文主要是介绍【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 datapcl::PCDReader reader;reader.read("16line.pcd", *cloud);std::cerr << "Cloud before filtering: " << cloud->points.size() << std::endl;// Create the filtering objectpcl::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 objectpcl::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);
实验结果可视化
下面简单贴出直通滤波过滤的结果点云:
下面图片点云过滤是上一张图片的全局剩余的点云,这里在代码中的pass.setFilterLimitsNegative(true);就是这个功能作用,是否保存滤波的限制范围内的点云,默认为false,保存限制范围点云,true时候是相反。
在查阅学习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 datapcl::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 objectpcl::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-axispass.setInputCloud(cloud_filtered2);pass.setFilterFieldName("y");pass.setFilterLimits(-5.0, 5.0);pass.filter(*cloud_filtered3);// filter range Z-axispass.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轴的范围,还是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
这篇关于【pcl入门教程滤波系列】之passThrough滤波的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!