pcl:点云滤波

1、体素滤波下采样

简介:在建图时,从多个视野扫描的点云会存在重复情况,近似点会占用大量空间,并占用较大时间复杂度,对空间中数据进行下采样,优化时间复杂度。

作用:处理大数据点云时,例如点云批准,花费时间巨大,通过体素滤波选取体素中心点代替目标点云,减少匹配时间,实现更快速的曲面重建。

#include <pcl/filters/voxel_grid.h>

//点云下采样
pcl::PointCloud<pcl::PointXYZ>::Ptr downSample(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, double leaf) {
	pcl::VoxelGrid<pcl::PointXYZ> sor;
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_new(new pcl::PointCloud<pcl::PointXYZ>);

	sor.setInputCloud(cloud);
	sor.setLeafSize(leaf, leaf, leaf);  //大小为2*2*2
	sor.filter(*cloud_new);
	return cloud_new;
}

 2、统计滤波

        统计滤波器主要用于去除明显离群点。 离群点特征在空间中分布稀疏。定义某处点云小于某个密度,既点云无效。计算每个点到其最近的k个点平均距离。则点云中所有点的距离应构成高斯分布。根据给定均值与方差,可剔除方差之外的点。对于图中那些离点云规模较聚集的区域,简称为离群点,统计滤波对这些离群点的处理比较好。

#include <pcl/filters/statistical_outlier_removal.h>//统计滤波器支持头文件    

// 去除离群点
pcl::PointCloud<pcl::PointXYZ>::Ptr remove_leave_Point(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,int K=50,double eps=2.0) {
	pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;//创建对象
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_new(new pcl::PointCloud<pcl::PointXYZ>);
	sor.setInputCloud(cloud);  //输入点云
	sor.setMeanK(K); //临近点
	sor.setStddevMulThresh(eps); //离群点阈值
	sor.filter(*cloud_new);
	return cloud_new;
}

首先,遍历点云,计算每个点与其最近的k个邻居点之间的平均距离;其次,计算所有平均距离的均值μ与标准差σ,则距离阈值dmax可表示为dmax=μ+α×σ,α是一个常数,可称为比例系数,它取决于邻居点的数目;最后,再次遍历点云,剔除与k个邻居点的平均距离大于dmax的点。

看着统计滤波的时间比较长,想要用kdtree实现,没想到它的底层就是kdtree实现,这里有我写的kdtree版本的统计滤波,先放这里,以后再做性能优化,通过手写kdtree实现统计滤波和上面算法时间复杂度差不多大。

//基于kdtree 去除离去点
pcl::PointCloud<pcl::PointXYZ>::Ptr remove_leave_Point_KdTree(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, int K = 50, double eps = 2.0) {
	pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
	kdtree.setInputCloud(cloud);        //设置搜索空间
	vector<float> vis(cloud->size());
	double average = 0;
	for (int i = 0; i < cloud->size(); i++) {
		//int K = 2;
		std::vector<int> ptIdxByKNN(K);      //存储查询点近邻索引
		std::vector<float> ptKNN(K); 		//存储近邻点对应距离平方
		kdtree.nearestKSearch(cloud->points[i], K, ptIdxByKNN, ptKNN); //执行K近邻搜索
		vis[i] = 0;
		for (int j = 0; j < K; j++) {
			vis[i] += ptKNN[j];
		}
		vis[i] = vis[i] / K * 1.0;
		average += vis[i];
	}
	average = average / (1.0*vis.size());
	double dmax = 0;
	double rou = 0;
	for (int i = 0; i < vis.size(); i++) {
		rou = (vis[i] - average)*(vis[i] - average);
	}
	rou = sqrt(rou*1.0 / vis.size());
	dmax = average + eps * rou;
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_new(new pcl::PointCloud<pcl::PointXYZ>);
	for (int i = 0; i < cloud->size(); i++) {
		if (vis[i]<dmax) {
			cloud_new->push_back(cloud->points[i]);
		}
	}
	cout <<" 新点云"<< cloud_new->size() << endl;
	return cloud_new;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C++PCL库进行点云滤波的示例代码: ```cpp #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::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>); // 从PCD文件中读取点云数据 pcl::PCDReader reader; reader.read<pcl::PointXYZ> ("input_cloud.pcd", *cloud); std::cout << "PointCloud before filtering: " << cloud->width * cloud->height << " data points." << std::endl; // 创建一个体素网格滤波器对象 pcl::VoxelGrid<pcl::PointXYZ> sor; sor.setInputCloud (cloud); sor.setLeafSize (0.01f, 0.01f, 0.01f); // 设置体素大小 sor.filter (*cloud_filtered); std::cout << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl; // 保存滤波后的点云数据到PCD文件中 pcl::PCDWriter writer; writer.write<pcl::PointXYZ> ("output_cloud.pcd", *cloud_filtered, false); return (0); } ``` 在该示例中,我们首先使用pcl::PCDReader从PCD文件中读取点云数据,然后创建pcl::VoxelGrid滤波器对象并设置体素大小。最后,我们将点云数据传递给滤波器,并保存滤波后的点云数据到PCD文件中。 请注意,该示例仅仅使用了最基本的点云滤波器,PCL库中还有很多其他的滤波器可以使用,具体可以参考PCL官方文档。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值