三维点云处理05-FPS代码实现
基础知识点
- 最远点采样原理解释:
1.从原始点云中选取一个初始点作为最远点
2.设定我们希望获得的最远点的数量npoints
3.进行npoints次循
4.每次循环中计算原点点云中每个点到距离它最近的最远点的距离
5.然后从中选出距离最大的点作为下一个最远点
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/22d22d41d85b013b9ddf77c74776a3b3.png)
- 上图解释:
1.首先从原始点云中选择一个点作为初始点
2.然后计算原始点云中所有点到该初识最远点的距离,获得第二个最远点
3.然后计算原始点云中所有点到第二个最远点的距离,并与第一个最远点的距离进行比较,使用距离较小的更新距离矩阵(这里是因为FPS算法中每个点都是选择与它最近的最远点计算距离)
4.然后从距离矩阵中选择距离最远点集合距离最大的作为第三个最远点
5.以此类推,重复3,4 - 这里再贴一个大佬的FPS算法总结
1.输入点云有N个点,从点云中选取一个点P0作为起始点,得到采样点集合S={P0};
2.计算所有点到P0的距离,构成N为数组L,从中选择最大值对应的点作为P1,更新采样点集合S={P0,P1}
3.计算所有点到P1的距离,对于每一个点Pi,其到P1的距离如果小于当前L中的L[i],则更新L[i],也就是L[i] = d{Pi,P1},因此,可以看出距离矩阵L中存放的一直是每一个点到采样点集合S的最近距离(也就是每个点都与其最近的最远点计算距离)
4.选择距离矩阵L中最大值对应的点作为P2,更新采样点集合S={P0,P1,P2}
5.重复2-4步,一直采样到N个目标采样点为止
初始点如何选择
- 随机选择一个点,这种选择方式的缺点是每次FPS获得的结果都不同
- 选择距离点云重心的最远点,每次FPS的结果都相同,一般位于局部极值点,具有刻画能力
距离度量如何选择
- 欧式距离:主要对于点云,在3D空间均匀采样
- 测地距离:主要用于三角网格,在三角网格面上均匀采样
FPS代码实现
import torch
from torch.autograd import Variable
def farthest_point_sample(xyz,npoint):
'''
输入:
xyz: B C N
npoint:最远点采样的样本数
输出:
最远点采样的结果: B npoint
'''
xyz = xyz.transpose(2,1)
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
batch_indices = torch.arange(B,dtype=torch.long).to(device)
barycenter = torch.sum((xyz),1)
barycenter = barycenter / xyz.shape[1]
arycenter = barycenter.view(B,1,3)
dist = torch.sum((xyz - barycenter)**2, -1)
farthest = torch.max(dist,1)[1]
for i in range(npoint):
centroids[:,i] = farthest
centroid = xyz[batch_indices,farthest,:].view(B,1,3)
dist = torch.sum((xyz - centroid)**2,-1)
mask = dist < distance
distance[mask] = dist[mask]
farthest = torch.max(distance,-1)[1]
return centroids
if __name__ == '__main__':
sim_data = Variable(torch.rand(1,3,8))
centroid = farthest_point_sample(sim_data, 4)