目录
1. 斜面距离出自
2. 公式:
3. 步骤:
H. Fan, S. Hao, and L. Guibas, “A point set generation network for 3D object reconstruction from a single image,” CVPR, 2017.
CD计算 用于测量点云S1和S2之间的平均最近平方距离。
(1)取s1中的一个点,计算该点和s2中的所有点之间的距离,取最小距离值作为该点和s2之间的距离;
(2)再取s1中的其他点,依次计算点和s2之间的距离,直至取完s1中的点,再除以s1点的个数求得s1中的点到s2的平均距离;
(3)同样的步骤,求s2中的点到s1的平均距离;
(4)将两个平均距离相加,得到CD距离。
def array2samples_distance(array1, array2):
"""
CD distance of single point cloud
arguments:
array1: the array, size: (num_point, num_feature). (512,3)
array2: the samples, size: (num_point, num_feature). (512,3)
returns:
distances: each entry is the distance from a sample to array1
"""
num_point1, num_features1 = array1.shape
num_point2, num_features2 = array2.shape
expanded_array1 = array1.repeat(num_point2, 1) # (512*512,1)
# (512,3) -> (512,1,3) -> (512,512,3) -> (512*512,3)
expanded_array2 = torch.reshape(torch.unsqueeze(array2, 1).repeat(1, num_point1, 1), (-1, num_features2))
# expanded_array1: (512,1), expanded_array2: (512*512,3)
distances = (expanded_array1 - expanded_array2) * (expanded_array1 - expanded_array2)
# distances = torch.sqrt(distances)
distances = torch.sum(distances, dim=1) # s1中的点和s2中的点两两之间的平方距离
distances = torch.reshape(distances, (num_point2, num_point1)) #
distances = torch.min(distances, dim=1)[0]
distances = torch.mean(distances)
return distances
def chamfer_distance_numpy(array1, array2):
"""
batch.
Parameters
----------
array1: (b,512,3)
array2: (b,512,3)
Returns
-------
"""
batch_size, num_point, num_features = array1.shape
dist = 0
for i in range(batch_size): # 每次求一个点云的CD值,最后求平均值。
av_dist1 = array2samples_distance(array1[i], array2[i])
av_dist2 = array2samples_distance(array2[i], array1[i])
dist = dist + (0.5 * av_dist1 + 0.5 * av_dist2) / batch_size # 等于(a1+b1)+(a2+b2)+(a3+b3)+../32
return dist * 100
class PointLoss(nn.Module):
def __init__(self):
super(PointLoss, self).__init__()
def forward(self, array1, array2):
"""
Parameters
----------
array1: (b,512,3)
array2: (b,512,3)
Returns
-------
"""
return chamfer_distance_numpy(array1, array2)
criterion_PointLoss = PointLoss().to(device)
# fake: (b,1,512,3) -> (b,512,3), real_center: (b,1,512,3) -> (b,512,3)
CD_LOSS = criterion_PointLoss(torch.squeeze(fake, 1), torch.squeeze(real_center, 1))