PCL 最远点采样

一、算法原理

1、算法概述

  Farthest Point Sampling (FPS):顾名思义,也就是每次采样的时候都选择离之前采样得到的 k − 1 k-1 k1个点距离最远的点。 F P S FPS FPS能够比较好地保证采样后的点具有较好的覆盖率,因而在点云分割领域被广泛地使用(e.g., PointNet++, PointCNN, PointConv, PointWeb)。然而,FPS的计算复杂度是 ,计算量与输入点云的点数呈平方相关。这表明从FPS可能不适合用来处理大规模点云。举例来说,当输入一个具有百万量级点的大场景点云时,使用FPS将其降采样到原始规模的10%需要多达200秒。

2、实现流程

  1. 从点云中随机挑选一个点作为初始点;
  2. 迭代计算距离已选点的距离之和最远的点,将其选入FPS集合。
    在这里插入图片描述
FPS算法示意图

3、参考文献

[1] Hu Q , Yang B , Xie L , et al. RandLA-Net: Efficient Semantic Segmentation of Large-Scale Point Clouds[J]. 2019.

二、代码实现

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h> 

using namespace std;

// 获取最远采样点的索引
template<typename PointT> inline int
getMaxDistanceIdx(const pcl::PointCloud<PointT>& cloud, const Eigen::Vector3f& pivot_pt3)
{
    
    
	float max_dist = -FLT_MAX;
	int max_idx = -1;
	float dist;

	for (std::size_t i = 0; i < cloud.size(); ++i)
	{
    
    
		pcl::Vector3fMapConst pt = cloud[i].getVector3fMap();
		dist = (pivot_pt3 - pt).norm();
		if (dist > max_dist)
		{
    
    
			max_idx = int(i);
			max_dist = dist;
		}
	}
	return max_idx;
}


int main(int argc, char** argv)
{
    
    
	// ---------------------------加载点云数据--------------------------------------
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPCDFile<pcl::PointXYZ>("data//dragon1.pcd", *cloud);
	cout << "从点云数据中读取" << cloud->points.size() << "个点" << endl;
	// 输入采样点的个数
	int sample_num = 9000; 
	// ----------------------------最远点采样---------------------------------------

	if (sample_num >= cloud->points.size())
	{
    
    
		PCL_ERROR("采样点个数大于原始点云的点数,无法进行采样!!!");
		std::exit;
	}

	pcl::PointCloud<pcl::PointXYZ>::Ptr sample_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	// 随机选取一个点
	pcl::IndicesPtr indices(new pcl::Indices(cloud->size()));
	const auto nr_points = indices->size();
	srand((unsigned)time(NULL));
	auto* index = &(*indices)[rand() % nr_points];
	Eigen::Vector3f samplePoint = cloud->points[*index].getVector3fMap();
	cloud->erase(cloud->begin() + *index);
	sample_cloud->push_back(cloud->points[*index]);
	// 遍历获取彼此距离最远的点
	for (int j = 0; j < sample_num - 1; ++j)
	{
    
    
		const Eigen::Vector3f pivot_pt31 = sample_cloud->points[j].getVector3fMap();
		int max_idx = getMaxDistanceIdx(*cloud, pivot_pt31);
		cloud->erase(cloud->begin() + max_idx);
		sample_cloud->push_back(cloud->points[max_idx]);
	}
	// 保存结果
	pcl::io::savePCDFileBinary("FPSsample.pcd", *sample_cloud);
	
	return (0);
}

三、结果展示

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_36686437/article/details/122419772
pcl