本文主要借鉴于博主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);
}
其中滤波器对象为:
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个,而实际效果可以发现点的密度大小与整齐程度不同,虽然处理后的数据量大大减小,但是很明显所含有的形状特征和空间结构信息与原始点云差不多(可视化还不会,所以没有效果图。。)。
未完待续。