目录
1. 概念
迭代最远距离采样,在点云论文PointNet++和PF-Net中用于对点云数据下采样。
(1)随机选择一个点作为已选择采样点;
(2)计算未选择采样点集中每个点与已选择采样点集之间的最小距离作为到采样点集的距离;
(3)将距离最大的那个点加入已选择采样点集,然后更新distance,一直循环迭代下去,直至获得了目标数量的采样点。
2. 图例说明
如下所示,5个点,如果采样3个点,则依次采样1,5,4. 其中distance是每个点到各自采样点的距离,dist是所有点和当前采样点的距离。
3. 代码实现
来自PF-Net
def farthest_point_sample(xyz, npoint, RAN=True):
"""
下采样,提取npoint个点作为骨架点
Input:
xyz: pointcloud data, [B, N, C]. eg. (8,512,3)
npoint: number of samples. eg. 64
Return:
centroids: sampled pointcloud index, [B, npoint]
"""
device = xyz.device
B, N, C = xyz.shape
centroid_idx = torch.zeros(B, npoint, dtype=torch.long).to(device) # (b,64). 全0。存放已选择采样点集的索引
distance = torch.ones(B, N).to(device) * 1e10 # (b,512). 超大值。保存的是点云中每个点到已采样点集合中的最小值。
if RAN: # 是否随机选择一个点作为已选择采样点
farthest_idx = torch.randint(0, 1, (B,), dtype=torch.long).to(device) # (b,) 填充全0. 这里代码应该是写错了。
else: # 不随机,直接填充全1
farthest_idx = torch.randint(1, 2, (B,), dtype=torch.long).to(device) # (b,) 填充全1. 选择一个初始点作为已选择采样点
batch_indices = torch.arange(B, dtype=torch.long).to(device) # (b,). val=[0,1,2,...]
for i in range(npoint): # 画个图就能理解
centroid_idx[:, i] = farthest_idx # (b,512). (b). 将距离最大的那个点的索引加入已选择采样点集
centroid = xyz[batch_indices, farthest_idx, :].view(B, 1, 3) # 当前采样点集坐标. (b,3)->(b,1,3)
dist = torch.sum((xyz - centroid) ** 2, -1) # 计算每个点和当前采样点之间的距离. xyz(b,512,3). centroid(b,1,3). (b,512)
mask = dist < distance # (b,512). 所有的点和已选择采样点的距离,是否比之前的更近
distance[mask] = dist[mask] # 更新为更近的distance. 存放所有点和各自采样点之间的距离
farthest_idx = torch.max(distance, -1)[1] # (b,512)->(b,1). 即当前点云中找到距离采样点最远的索引
return centroid_idx # (b,64)