目录
最远点采样(Farthest Point Sampling, FPS)是一种在点云处理、计算机图形学和机器学习中常用的采样方法。该方法旨在从一个较大的数据集中选取一个较小的子集,同时尽可能保持原始数据集的结构特征。最远点采样特别适用于需要减少数据点数量以提高处理速度或降低计算复杂度的场景,同时又不希望损失太多原始数据集的关键信息。
最远点采样的基本原理
最远点采样的基本思想是:从数据集中选择一个起始点,然后迭代地选择距离当前已选点集最远的点。这种方法能够确保采样点在空间中相对均匀地分布,从而最大程度地保留数据集的几何结构。
FPS具体实施细节
随着迭代,数组𝑳中元素会越来越小,相当于记录着某个样本中每个点距离所有已出现的采样点的最小距离。
最远点采样的特点
- 空间覆盖性:最远点采样能够较好地覆盖整个数据集的空间,使采样点分布更加均匀。
- 效率与准确性的平衡:通过控制采样点的数目,可以在处理速度和保留数据集特征之间找到一个平衡点。
- 适用性广:最远点采样不依赖于数据的具体特征,可以广泛应用于不同的领域和任务中,如三维点云的下采样、机器学习中的数据预处理等。
应用场景
- 三维点云处理:在处理大规模三维点云数据时,直接处理可能因数据量过大而导致的计算资源消耗巨大。使用最远点采样可以有效减少点的数量,简化计算过程,同时保留了点云的主要结构特征。
- 深度学习:在深度学习模型的训练过程中,对输入数据进行下采样可以减少模型的计算负担,加快训练速度。最远点采样因其良好的空间分布性,被用于从大规模数据集中选取有代表性的子集作为网络输入。
- 数据可视化:在大规模数据集的可视化中,直接渲染可能会因数据量过大而导致性能问题。最远点采样可以用于选取具有代表性的数据点进行可视化,同时尽可能保持整体数据的分布特征。
有两个问题:
1、初始点的选择:
随机选择一个点(每次结构不同);
选择距离点云重心的最远点(每次结果相同,一边位于局部极值点,具有刻画能力)。
2、距离度量
欧氏距离:主要对于点云,在3D空间中均匀采样;
测地距离:主要对于三角网络,在三角网格面上进行均匀采样。
FPS相比于随机采样能够更好的覆盖点云集主要有以下原因:
1、最大化最小距离:FPS每次选择当前未被选择点中距离已选点最远的点作为新的采样点,确保了新添加的点能够尽可能远离已有的采样点。(这样能使采样点均匀且广泛地分布在整个数据集中,从而最大化地覆盖整个点云集)
2、避免局部过度采样:随机采样可能导致某些区域被过度采样(特别是在采样不均匀的情况下)。相比之下,FPS因每次只寻找最远点,所以他能更有效地探索那些被较少采样的区域。
3、保留数据结构:在点云和复杂几何形状的处理中,FPS能够较好地保留数据的边缘和形状,这对于后续的数据处理和分析非常有帮助。
4、FPS不依赖先验数据,因此适应性更强。
总结
FPS是一种在点云、图像处理或其他数据集中用于抽样的算法。目的是从一个大的数据集中选出一组代表性强的点,这些点彼此之间的最小距离尽可能大。
适合减少数据量,同时尽可能的保留原始数据集中的结构和特征。
最远点采样以其简单高效、适用性广的特点,在数据处理和机器学习等多个领域发挥着重要作用。通过合理选择采样点数目,最远点采样既可以保证数据处理的效率,又能在较大程度上保留数据的重要特征,是处理大规模数据集的有效工具之一。
代码实现
def farthest_point_sample(xyz, npoint):
"""
Input:
xyz: pointcloud data, [B, N, C]
npoint: number of samples
Return:
centroids: sampled pointcloud index, [B, npoint]
"""
device = xyz.device
B, N, C = xyz.shape
centroids = torch.zeros(B, npoint, dtype=torch.long).to(device)
distance = torch.ones(B, N).to(device) * 1e10
farthest = torch.randint(0, N, (B,), dtype=torch.long).to(device)
batch_indices = torch.arange(B, dtype=torch.long).to(device)
for i in range(npoint):
# 更新第i个最远点
centroids[:, i] = farthest
# 取出这个最远点的xyz坐标
centroid = xyz[batch_indices, farthest, :].view(B, 1, 3)
# 计算点集中的所有点到这个最远点的欧式距离
dist = torch.sum((xyz - centroid) ** 2, -1)
# 更新distances,记录样本中每个点距离所有已出现的采样点的最小距离
mask = dist < distance
distance[mask] = dist[mask]
# 从更新后的distances矩阵中找出距离最远的点,作为最远点用于下一轮迭代
farthest = torch.max(distance, -1)[1]
return centroids
参考内容: