PCL点云滤波汇总:算法原理 + 代码实现

目录

    • 1 PassThrough 直通滤波器
      • 1.1 官网描述
      • 1.2 算法原理
      • 1.3 代码实现
    • 2 VoxelGrid 体素滤波器
      • 2.1 官网描述
      • 2.2 算法原理
      • 2.3 代码实现
    • 3 UniformSampling 均匀采样
      • 3.1 官网描述
      • 3.2 算法原理
      • 3.3 代码实现
    • 4 StatisticalOutlierRemoval 统计滤波器
    • 5 RadiusOutlierRemoval 半径滤波器
    • 6 ConditionRemoval 条件滤波器
    • 7 ExtractIndices 索引提取
    • 8 ProjectInliers 投影滤波器
    • 9 ModelOutlierRemoval 模型滤波器
    • 10 空间裁剪滤波
      • 10.1 CropHull滤波器
      • 10.2 CropBox 滤波器
      • 10.3 BoxClipper3D滤波器
      • 10.4 Clipper3D滤波器
    • 11 BilateralFilter 双边滤波器
    • 12 GaussianKernel 高斯滤波

  PCL中点云滤波模块提供了很多灵活实用的滤波处理算法,例如:直通滤波、统计滤波、双边滤波、高斯滤波、基于随机采样一致性滤波等。同时,PCL中总结了几种需要进行点云滤波处理的情况,如下:

  1. 点云数据密度不规则需要平滑
  2. 因遮挡等问题噪声的离群点需要去除
  3. 数据冗余需要下采样
  4. 噪声数据需要去除

对应的方法如下:

  1. 按具体给定的规则过滤点
  2. 通过滤波算法修改点的部分属性
  3. 点云数据下采样

下面对PCL各种滤波方法做一些归纳总结,方便日后使用。

1 PassThrough 直通滤波器

1.1 官网描述

PCL官网对PassThrough滤波器的描述为:

  PassThrough passes points in a cloud based on constraints for one particular field of the point type.

1.2 算法原理

  对指定的某一维度进行滤波,去掉用户指定字段范围内(或外)的点

PassThrough滤波器所需头文件为

#include 

1.3 代码实现

流程:读入点云→创建滤波器对象→设置滤波字段范围→执行滤波→保存滤波结果

#include 
#include 
#include 

using namespace std;

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>);	//滤波后点云
	
	///读入点云
	cout << "->正在读入点云..." << endl;
	if (pcl::io::loadPCDFile("1.pcd", *cloud) < 0)
	{
     
		PCL_ERROR("点云文件不存在!\n");
		return -1;
	}
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	///直通滤波
	cout << "->正在进行直通滤波..." << endl;
	pcl::PassThrough<pcl::PointXYZ> pass;	// 创建滤波器对象
	pass.setInputCloud(cloud);				//设置输入点云
	pass.setFilterFieldName("z");			//设置滤波所需字段z
	pass.setFilterLimits(-1.0, 0.0);		//设置Z字段过滤范围
	pass.setFilterLimitsNegative (true);	//默认false,保留范围内的点云;true,保存范围外的点云
	pass.filter(*cloud_filtered);			//执行滤波,保存滤波后点云

	///保存滤波后点云
	if (1)
	{
     
		cout << "->正在保存点云...\n";
		if (cloud_filtered->empty())
		{
     
			PCL_ERROR("保存点云为空!\n");
			return -1;
		}
		else
		{
     
			pcl::io::savePCDFileBinary("filter.pcd", *cloud_filtered);
			cout << "\t\t<保存点云信息>\n" << *cloud_filtered << endl;
		}
	}
	
	return 0;
}

2 VoxelGrid 体素滤波器

2.1 官网描述

PCL官网对VoxelGrid 滤波器的描述为:

  VoxelGrid assembles a local 3D grid over a given PointCloud, and downsamples + filters the data
  The VoxelGrid class creates a 3D voxel grid (think about a voxel grid as a set of tiny 3D boxes in space) over the input point cloud data. Then, in each voxel (i.e., 3D box), all the points present will be approximated (i.e., downsampled) with their centroid. This approach is a bit slower than approximating them with the center of the voxel, but it represents the underlying surface more accurately.

2.2 算法原理

  对点云数据创建一个三维体素栅格(微小的空间三维立方体的集合),用每个体素重心近似代替体素中的其他点。这种方法比用体素中心来逼近的方法更慢,但它对于采样点对应曲面的表示更为准确。

VoxelGrid 滤波器所需头文件为

#include 

2.3 代码实现

流程:读入点云→创建滤波器对象→设置体素大小→执行滤波→保存滤波点云

#include 
#include 
#include 

using namespace std;

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>);	//滤波后点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("1.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	///体素滤波器点云下采样
	cout << "->正在体素下采样..." << endl;
	pcl::VoxelGrid<pcl::PointXYZ> vox;		//创建滤波器对象
	vox.setInputCloud(cloud);				//设置待滤波点云
	vox.setLeafSize(0.05f, 0.05f, 0.05f);	//设置体素大小
	vox.filter(*cloud_filtered);			//执行滤波,保存滤波结果于cloud_filtered

	///保存下采样点云
	cout << "->正在保存下采样点云..." << endl;
	pcl::PCDWriter writer;
	writer.write("sub.pcd", *cloud_filtered, true);
	cout << "\t\t<保存点云信息>\n" << *cloud_filtered << endl;

	return 0;
}

3 UniformSampling 均匀采样

3.1 官网描述

PCL官网对UniformSampling的描述为:

  UniformSampling assembles a local 3D grid over a given PointCloud, and downsamples + filters the data.
  The UniformSampling class creates a 3D voxel grid (think about a voxel grid as a set of tiny 3D boxes in space) over the input point cloud data. Then, in each voxel (i.e., 3D box), all the points present will be approximated (i.e., downsampled) with the closest point to the center of the voxel.

3.2 算法原理

  对点云数据创建一个三维体素栅格,然后,在每个体素保留一个最接近体素中心的点,代替体素中所有点。

UniformSampling 均匀采样所需头文件为

#include 

3.3 代码实现

流程:读入点云→创建滤波器对象→设置滤波球体半径→执行滤波→保存滤波点云

#include 
#include 
#include 

using namespace std;

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>);	//滤波后点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("1.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	///均匀采样
	cout << "->正在均匀采样..." << endl;
	pcl::UniformSampling<pcl::PointXYZ> unif;	//创建滤波器对象
	unif.setInputCloud(cloud);					//设置待滤波点云
	unif.setRadiusSearch(0.05f);				//设置滤波球体半径
	unif.filter(*cloud_filtered);				//执行滤波,保存滤波结果于cloud_filtered

	///保存下采样点云
	cout << "->正在保存采样点云..." << endl;
	pcl::PCDWriter writer;
	writer.write("UniformSampling.pcd", *cloud_filtered, true);
	cout << "\t\t<保存点云信息>\n" << *cloud_filtered << endl;

	return 0;
}

4 StatisticalOutlierRemoval 统计滤波器

4.1 官网描述

PCL官网对StatisticalOutlierRemoval 滤波器的描述为:

  StatisticalOutlierRemoval uses point neighborhood statistics to filter outlier data.
  The algorithm iterates through the entire input twice: During the first iteration it will compute the average distance that each point has to its nearest k neighbors. The value of k can be set using setMeanK(). Next, the mean and standard deviation of all these distances are computed in order to determine a distance threshold. The distance threshold will be equal to: mean + stddev_mult * stddev. The multiplier for the standard deviation can be set using setStddevMulThresh(). During the next iteration the points will be classified as inlier or outlier if their average neighbor distance is below or above this threshold respectively.The neighbors found for each query point will be found amongst ALL points of setInputCloud(), not just those indexed by setIndices(). The setIndices() method only indexes the points that will be iterated through as search query points.

4.2 算法原理

  对每一点的邻域进行统计分析,基于点到所有邻近点的距离分布特征,过滤掉一些不满足要求的离群点。该算法对整个输入进行两次迭代:在第一次迭代中,它将计算每个点到最近k个近邻点的平均距离,得到的结果符合高斯分布。接下来,计算所有这些距离的平均值 μ 和标准差 σ 以确定距离阈值 thresh_d ,且 thresh_d = μ + k·σ。 k为标准差乘数。在下一次迭代中,如果这些点的平均邻域距离分别低于或高于该阈值,则这些点将被分类为内点或离群点。

StatisticalOutlierRemoval 统计滤波器所需头文件为

#include 

4.3 代码实现
流程:读入点云→创建滤波器对象→设置离群点阈值→执行统计滤波→保存滤波点云

#include 
#include 
#include 

using namespace std;

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>);	//滤波后点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("1.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	///统计滤波
	cout << "->正在进行统计滤波..." << endl;
	pcl::StatisticalOutlierRemoval<pcl::PointXYZ> SO;	//创建滤波器对象
	SO.setInputCloud(cloud);							//设置待滤波点云
	SO.setMeanK(50);									//设置查询点近邻点的个数
	SO.setStddevMulThresh(1.0);							//设置标准差乘数,来计算是否为离群点的阈值
	//SO.setNegative(true);								//默认false,保存内点;true,保存滤掉的离群点
	SO.filter(*cloud_filtered);							//执行滤波,保存滤波结果于cloud_filtered

	///保存下采样点云
	cout << "->正在保存滤波点云..." << endl;
	pcl::PCDWriter writer;
	writer.write("StatisticalOutlierRemoval.pcd", *cloud_filtered, true);
	cout << "\t\t<保存点云信息>\n" << *cloud_filtered << endl;

	return 0;
}

5 RadiusOutlierRemoval 半径滤波器

5.1 官网描述

PCL官网对RadiusOutlierRemoval 半径滤波器的描述为:

  RadiusOutlierRemoval filters points in a cloud based on the number of neighbors they have.
  Iterates through the entire input once, and for each point, retrieves the number of neighbors within a certain radius. The point will be considered an outlier if it has too few neighbors, as determined by setMinNeighborsInRadius(). The radius can be changed using setRadiusSearch().The neighbors found for each query point will be found amongst ALL points of setInputCloud(), not just those indexed by setIndices(). The setIndices() method only indexes the points that will be iterated through as search query points.

5.2 算法原理
  对整个输入迭代一次,对于每个点进行半径R邻域搜索,如果邻域点的个数低于某一阈值,则该点将被视为噪声点并被移除。

RadiusOutlierRemoval 半径滤波器所需头文件为

#include 

5.3 代码实现
流程:读入点云→创建半径滤波器对象→设置离群点阈值→执行下采样→保存采样结果

#include 
#include 
#include 

using namespace std;

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>);	//滤波后点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("1.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	///半径滤波
	cout << "->正在进行半径滤波..." << endl;
	pcl::RadiusOutlierRemoval<pcl::PointXYZ> RR;	//创建滤波器对象
	RR.setInputCloud(cloud);						//设置待滤波点云
	RR.setRadiusSearch(0.02);						//设置查询点的半径范围
	RR.setMinNeighborsInRadius(5);					//设置判断是否为离群点的阈值,即半径内至少包括的点数
	//RR.setNegative(true);							//默认false,保存内点;true,保存滤掉的外点
	RR.filter(*cloud_filtered);						//执行滤波,保存滤波结果于cloud_filtered

	///保存下采样点云
	cout << "->正在保存滤波点云..." << endl;
	pcl::PCDWriter writer;
	writer.write("RadiusOutlierRemoval.pcd", *cloud_filtered, true);
	cout << "\t\t<保存点云信息>\n" << *cloud_filtered << endl;

	return 0;
}

6 ConditionRemoval 条件滤波器

6.1 官网描述

PCL官网对ConditionRemoval 条件滤波器的描述为:

  ConditionalRemoval filters data that satisfies certain conditions.
  A ConditionalRemoval must be provided a condition. There are two types of conditions: ConditionAnd and ConditionOr. Conditions require one or more comparisons and/or other conditions.
  A comparison has a name, a comparison operator, and a value.
  An ConditionAnd will evaluate to true when ALL of its encapsulated comparisons and conditions are true.
  An ConditionOr will evaluate to true when ANY of its encapsulated comparisons and conditions are true.
  Depending on the derived type of the comparison, the name can correspond to a PointCloud field name, or a color component in rgb color space or hsi color space.

6.2 算法原理

  筛选满足特定条件的点云数据。有两种类型的条件:

  1. ConditionAnd: 所有条件都要满足
  2. ConditionOr: 满足一个条件即可

  可以设置一个或多个条件对象,并为条件对象添加比较算子。条件比较算子包含三项:

  1. 名称:对应于点云XYZ字段名称、RGB颜色空间、HSI颜色空间中的颜色分量等。
  2. 比较运算符:GT、GE、LT、LE、EQ
运算符 含义
GT greater than 大于
GE greater than or equal 大于等于
LT less than 小于
LE less than or equal 小于等于
EQ equal 等于

比较运算符源码

switch (this->op_)
  {
     
    case pcl::ComparisonOps::GT :
      return (compare_result > 0);
    case pcl::ComparisonOps::GE :
      return (compare_result >= 0);
    case pcl::ComparisonOps::LT :
      return (compare_result < 0);
    case pcl::ComparisonOps::LE :
      return (compare_result <= 0);
    case pcl::ComparisonOps::EQ :
      return (compare_result == 0);
    default:
      PCL_WARN ("[pcl::FieldComparison::evaluate] unrecognized op_!\n");
      return (false);
  }
  1. 值:即要比较的名称的数值

ConditionRemoval 条件滤波器所需头文件为

#include 

6.3 代码实现

流程:读入点云→创建条件对象→添加比较算子→创建条件限定下的滤波器对象→执行滤波→保存滤波结果

#include 
#include 
#include 

using namespace std;

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>);	//滤波后点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("1.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	///条件滤波
	cout << "->正在进行条件滤波..." << endl;
	/*创建条件限定下的滤波器*/
	pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());//创建条件定义对象range_cond
	//为条件定义对象添加比较算子
	range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new	
		pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::GT, -1.0)));//添加在x字段上大于-1.0的比较算子
	range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new	
		pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::LT, 0.0)));//添加在x字段上小于0.0的比较算子
	pcl::ConditionalRemoval<pcl::PointXYZ> CR;	//创建滤波器对象
	CR.setCondition(range_cond);				//用条件定义对象初始化
	CR.setInputCloud(cloud);					//设置待滤波点云
	//CR.setKeepOrganized(true);				//设置保持点云的结构
	//CR.setUserFilterValue(5);					//将过滤掉的点用(5,5,5)代替
	CR.filter(*cloud_filtered);					//执行滤波,保存滤波结果于cloud_filtered

	///保存滤波点云
	cout << "->正在保存滤波点云..." << endl;
	pcl::PCDWriter writer;
	writer.write("ConditionalRemoval.pcd", *cloud_filtered, true);
	cout << "\t\t<保存点云信息>\n" << *cloud_filtered << endl;
	
	return 0;
}

setKeepOrganized(true) 解释:

保持点云结构,即有序点云经过滤波后,仍能够保持有序性。

  • setKeepOrganized默认false,即直接将滤除的点删除,从而可能改变点云的组织结构。is_dense: 1
    PCL点云滤波汇总:算法原理 + 代码实现_第1张图片
  • 若设置为true,再通过setuserFilterValue设置一个指定的值,被滤除的点将会被该值代替;不进行setuserFilterValue设置,则默认用nan填充被滤除的点。is_dense: 0;
    PCL点云滤波汇总:算法原理 + 代码实现_第2张图片
    这有更多关于结构点云的内容

7 ExtractIndices 索引提取

7.1 官网描述

PCL官网对ExtractIndices 索引提取的描述为:

ExtractIndices extracts a set of indices from a point cloud.

7.2 算法原理

  从原始点云中提取一组索引对应的点云子集,前提是要获取点云索引集合。

ExtractIndices 索引提取所需头文件为

#include 

7.3 代码实现

流程:读入点云→平面分割获取索引集合→创建点云索引提取对象→执行索引提取→保存提取点云

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

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>);	//提取的平面点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("1.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	///ExtractIndices滤波
	/*点云分割*/
	cout << "->正在进行点云平面子集提取..." << endl;
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());	//创建分割时所需要的模型系数对象coefficients
	pcl::PointIndices::Ptr inliers(new pcl::PointIndices());				//创建存储内点的点索引集合对象inliers
	pcl::SACSegmentation<pcl::PointXYZ> seg;								//创建分割对象
	seg.setOptimizeCoefficients(true);										//可选,对估计的模型参数进行优化处理
	seg.setModelType(pcl::SACMODEL_PLANE);									//设置分割模型类别
	seg.setMethodType(pcl::SAC_RANSAC);										//设置随即参数估计方法
	seg.setMaxIterations(1000);												//设置最大迭代次数
	seg.setDistanceThreshold(0.01);											//设置判断是否为模型内点的距离阈值

	/*平面点云提取*/
	int i = 0;
	int nr_points = (int)cloud->points.size();
	//当还有30%原始点云数据时
	while (cloud->points.size() > 0.3 * nr_points)
	{
     
		///从点云中分割最大平面组成部分
		seg.setInputCloud(cloud);//设置输入点云,待分割
		seg.segment(*inliers, *coefficients);//引发分割实现:存储分割结果到点集合inliers;存储平面模型系数coefficients
		if (inliers->indices.size() == 0)
		{
     
			PCL_ERROR("不能从给定的点云数据集中提取出平面模型!\n");
			break;
		}
		
		pcl::ExtractIndices<pcl::PointXYZ> extract;	//创建点云提取对象
		extract.setInputCloud(cloud);				//设置输入点云
		extract.setIndices(inliers);				//设置分割后的内点inliers为需要提取的点集
		extract.setNegative(false);					//设置提取内点而非外点,默认false
		extract.filter(*cloud_filtered);			//提取点集并存储到 cloud_filtered
		cout << "平面点集" << i+1 << "点的个数为:" << cloud_filtered->points.size() << endl;
		std::stringstream ss;
		ss << "plane_" << i << ".pcd";
		pcl::PCDWriter writer;
		writer.write<pcl::PointXYZ>(ss.str(), *cloud_filtered, true);
		///提取剩余的点,用于进一步的平面提取
		extract.setNegative(true);			//提取外点
		extract.filter(*cloud_filtered);	//提取点集并存储到 cloud_filtered
		cloud.swap(cloud_filtered);			//将cloud替换为cloud_filtered
		i++;
	}

	return 0;
}

8 ProjectInliers 投影滤波器

8.1 官网描述

PCL官网对ProjectInliers 投影滤波器的描述为:

  ProjectInliers uses a model and a set of inlier indices from a PointCloud to project them into a separate PointCloud.

8.2 算法原理

  将点投影到一个参数化模型上,这个参数化模型可以是平面、圆球、圆柱、锥形等进行投影滤波。

ProjectInliers 投影滤波器所需头文件为

#include 

8.3 代码实现

参数化模型投影点云,以平面投影为例:读入点云→创建参数化模型→设置模型系数→执行投影滤波→保存投影点云

#include 
#include 
#include 
#include 

using namespace std;

int main(int argc, char** argv)
{
     
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);			//原始点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);//投影点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("1.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	///参数化模型投影
	cout << "->正在平面模型投影..." << endl;
	//创建 x+y+z=0 平面
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
	coefficients->values.resize(4);	//设置模型系数的大小
	coefficients->values[0] = 1.0;	//x系数
	coefficients->values[1] = 1.0;	//y系数
	coefficients->values[2] = 1.0;	//z系数
	coefficients->values[3] = 0.0;	//常数项
	//投影滤波
	pcl::ProjectInliers<pcl::PointXYZ> proj;//创建投影滤波器对象
	proj.setModelType(pcl::SACMODEL_PLANE);	//设置对象对应的投影模型
	proj.setInputCloud(cloud);				//设置输入点云
	proj.setModelCoefficients(coefficients);//设置模型对应的系数
	proj.filter(*cloud_projected);			//执行投影滤波,存储结果于cloud_projected

	///保存滤波点云
	cout << "->正在保存投影点云..." << endl;
	pcl::PCDWriter writer;
	writer.write("proj_PLANE.pcd", *cloud_projected, true);
	cout << "\t\t<保存点云信息>\n" << *cloud_projected << endl;

	return 0;
}

9 ModelOutlierRemoval 模型滤波器

9.1 官网描述

PCL官网对ModelOutlierRemoval 模型滤波器的描述为:

  ModelOutlierRemoval filters points in a cloud based on the distance between model and point.
  Iterates through the entire input once, automatically filtering non-finite points and the points outside the model specified by setSampleConsensusModelPointer() and the threshold specified by setThreholdFunctionPointer().

9.2 算法原理

  根据点到模型的距离,设置距离阈值过滤非模型点

9.3 代码实现

流程:读入点云→设置模型系数→创建模型滤波器对象→执行模型滤波→保存滤波结果

#include 
#include 
#include 
#include 

using namespace std;

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>);	//滤波点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("2.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	cout << "->正在模型滤波..." << endl;
	//设置模型系数
	pcl::ModelCoefficients model_coeff;
	model_coeff.values.resize(4);
	model_coeff.values[0] = 1.0; 
	model_coeff.values[1] = 1.0; 
	model_coeff.values[2] = 1.0; 
	model_coeff.values[3] = 0.0;
	///模型滤波
	pcl::ModelOutlierRemoval<pcl::PointXYZ> filter;	//创建模型滤波器对象
	filter.setModelCoefficients(model_coeff);		//为模型对象添加模型系数
	filter.setThreshold(0.1);						//设置判断是否为模型内点的阈值
	filter.setModelType(pcl::SACMODEL_PLANE);		//设置模型类别
	filter.setInputCloud(cloud);					//输入待滤波点云
	filter.setNegative(false);						//默认false,提取模型内点;true,提取模型外点
	filter.filter(*cloud_filtered);					//执行模型滤波,保存滤波结果于cloud_filtered

	///保存滤波点云
	cout << "->正在保存滤波点云..." << endl;
	pcl::PCDWriter writer;
	writer.write("ModelOutlierRemoval.pcd", *cloud_filtered, true);
	cout << "\t\t<保存点云信息>\n" << *cloud_filtered << endl;

	return 0;
}

10 空间裁剪滤波

10.1 CropHull滤波器

10.1.1 官网描述

PCL官网对CropHull滤波器的描述为:

CropHull filters points that lie inside or outside a 3D closed surface or 2D closed polygon, as generated by the ConvexHull or ConcaveHull classes.

10.1.2 算法原理

  获取点云在 3D 封闭曲面上或 2D 封闭多边形内或外部的点。

所需头文件为

#include 

10.1.3 代码实现

流程:读入点云→设置封闭范围顶点→创建凸包对象→执行CropHull滤波→保存滤波点云

#include 
#include 
#include 
#include 

using namespace std;

int main(int argc, char** argv)
{
     
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);			//原始点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr boundingbox(new pcl::PointCloud<pcl::PointXYZ>);	//封闭区域顶点
	pcl::PointCloud<pcl::PointXYZ>::Ptr surface_hull(new pcl::PointCloud<pcl::PointXYZ>);	//描述凸包形状的点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr objects(new pcl::PointCloud<pcl::PointXYZ>);		//提取的封闭区域内部点云

	///读入点云数据
	cout << "->正在读入点云..." << endl;
	pcl::PCDReader reader;
	reader.read("1.pcd", *cloud);
	cout << "\t\t<读入点云信息>\n" << *cloud << endl;

	cout << "->正在提取封闭区域内部点云..." << endl;
	///设置封闭范围顶点
	boundingbox->push_back(pcl::PointXYZ(-0.04, -0.6, -1.3));
	boundingbox->push_back(pcl::PointXYZ(0.8, -0.5, -1.5));
	boundingbox->push_back(pcl::PointXYZ(-0.014, 0.3, -1.4));
	boundingbox->push_back(pcl::PointXYZ(-0.5, 0.1, -1.1));

	///构造凸包
	pcl::ConvexHull<pcl::PointXYZ> hull;//创建凸包对象
	hull.setInputCloud(boundingbox);	//设置输入点云:封闭区域顶点点云
	hull.setDimension(2);				//设置凸包维度
	std::vector<pcl::Vertices> polygons;//设置Vertices类型的向量,用于保存凸包顶点
	hull.reconstruct(*surface_hull, polygons);//计算凸包结果

	///CropHull滤波
	pcl::CropHull<pcl::PointXYZ> CH;//创建CropHull滤波对象
	CH.setDim(2);					//设置维度,与凸包维度一致
	CH.setInputCloud(cloud);		//设置需要滤波的点云
	CH.setHullIndices(polygons);	//输入封闭区域的顶点
	CH.setHullCloud(surface_hull);	//输入封闭区域的形状
	CH.filter(*objects);			//执行CropHull滤波,存储结果于objects

	///保存点云
	cout << "->正在保存点云..." << endl;
	pcl::PCDWriter writer;
	writer.write("polygons.pcd", *boundingbox, true);
	cout << "\t\t<封闭区域顶点点云信息>\n" << *boundingbox << endl;
	writer.write("surface_hull.pcd", *surface_hull, true);
	cout << "\t\t<封闭形状点云信息>\n" << *surface_hull << endl;
	writer.write("objects.pcd", *objects, true);
	cout << "\t\t<提取的点云信息>\n" << *objects << endl;

	return 0;
}

需要注意的是setDimension()和CH.setDim()的维度应保持一致

  • 当维度设置为2时,封闭区域为2D封闭多边形,只有X和Y两个维度。因此,该封闭多边形在三维空间中表示为垂直于XOY面的竖直曲面。得到的是曲面内部或外部的点云。
  • 当维度设置为3时,封闭区域为3D封闭曲面,仅得到位于该封闭曲面上的点。

10.2 CropBox 滤波器

10.2.1 官网描述

PCL官网对CropBox 滤波器的描述为:

CropBox is a filter that allows the user to filter all the data inside of a given box.

10.2.2 算法原理

  给出一个包围盒,获取包围盒内部点云。

CropBox 所需头文件

#include 

10.2.3 代码实现

...

10.3 BoxClipper3D滤波器

10.3.1 官网描述

PCL官网对BoxClipper3D滤波器的描述为:

Implementation of a box clipper in 3D. Actually it allows affine transformations, thus any parallelepiped in general pose. The affine transformation is used to transform the point before clipping it using the unit cube centered at origin and with an extend of -1 to +1 in each dimension.

10.3.2 算法原理

BoxClipper3D所需头文件

#include 

10.3.3 代码实现

...

10.4 Clipper3D滤波器

10.4.1 官网描述

PCL官网对Clipper3D的描述为

Base class for 3D clipper objects.

10.4.2 算法原理

Clipper3D所需头文件为

#include 

10.4.3 代码实现

...

11 BilateralFilter 双边滤波器

11.1 官网描述

PCL官网对BilateralFilter 双边滤波器的描述为:

A bilateral filter implementation for point cloud data.

11.2 算法原理

  双边滤波是一种非线性滤波器,它可以达到保持边缘、降噪平滑的效果。采用加权平均的方法,用周边像素亮度值的加权平均代表某个像素的强度,所用的加权平均基于高斯分布。

BilateralFilter 滤波所需头文件为

#include 

12 GaussianKernel 高斯滤波

12.1 官网描述

PCL官网对GaussianKernel 双边滤波器的描述为:

Class GaussianKernel assembles all the method for computing, convolving, smoothing, gradients computing an image using a gaussian kernel.

以上滤波全部使用 1.pcd 点云文件进行实验
提取码:pdx6

你可能感兴趣的:(PCL,点云滤波)