方法簡述
class Convlayer(fluid.dygraph.Layer): def __init__(self, point_scales): super(Convlayer, self).__init__() self.point_scales = point_scales self.conv1 = Conv2D(1, 64, (1, 3)) self.conv2 = Conv2D(64, 64, 1) self.conv3 = Conv2D(64, 128, 1) self.conv4 = Conv2D(128, 256, 1) self.conv5 = Conv2D(256, 512, 1) self.conv6 = Conv2D(512, 1024, 1) self.maxpool = Pool2D(pool_size=(self.point_scales, 1), pool_stride=1) self.bn1 = BatchNorm(64, act='relu') self.bn2 = BatchNorm(64, act='relu') self.bn3 = BatchNorm(128, act='relu') self.bn4 = BatchNorm(256, act='relu') self.bn5 = BatchNorm(512, act='relu') self.bn6 = BatchNorm(1024, act='relu') def forward(self, x): x = fluid.layers.unsqueeze(x, 1) x = self.bn1(self.conv1(x)) x = self.bn2(self.conv2(x)) x_128 = self.bn3(self.conv3(x)) x_256 = self.bn4(self.conv4(x_128)) x_512 = self.bn5(self.conv5(x_256)) x_1024 = self.bn6(self.conv6(x_512)) x_128 = fluid.layers.squeeze(input=self.maxpool(x_128), axes=[2]) x_256 = fluid.layers.squeeze(input=self.maxpool(x_256), axes=[2]) x_512 = fluid.layers.squeeze(input=self.maxpool(x_512), axes=[2]) x_1024 = fluid.layers.squeeze(input=self.maxpool(x_1024), axes=[2]) L = [x_1024, x_512, x_256, x_128] x = fluid.layers.concat(L, 1) return x
class Latentfeature(fluid.dygraph.Layer): def __init__(self, num_scales, each_scales_size, point_scales_list): super(Latentfeature, self).__init__() self.num_scales = num_scales self.each_scales_size = each_scales_size self.point_scales_list = point_scales_list self.Convlayers1 = Convlayer(point_scales=self.point_scales_list[0]) self.Convlayers2 = Convlayer(point_scales=self.point_scales_list[1]) self.Convlayers3 = Convlayer(point_scales=self.point_scales_list[2]) self.conv1 = Conv1D(prefix='lf', num_channels=3, num_filters=1, size_k=1, act=None) self.bn1 = BatchNorm(1, act='relu') def forward(self, x): outs = [self.Convlayers1(x[0]), self.Convlayers2(x[1]), self.Convlayers3(x[2])] latentfeature = fluid.layers.concat(outs, 2) latentfeature = fluid.layers.transpose(latentfeature, perm=[0, 2, 1]) latentfeature = self.bn1(self.conv1(latentfeature)) latentfeature = fluid.layers.squeeze(latentfeature, axes=[1]) return latentfeature
class Conv1D(fluid.dygraph.Layer): def __init__(self, prefix, num_channels=3, num_filters=1, size_k=1, padding=0, groups=1, act=None): super(Conv1D, self).__init__() fan_in = num_channels * size_k * 1 k = 1. / math.sqrt(fan_in) param_attr = ParamAttr( name=prefix + "_w", initializer=fluid.initializer.Uniform( low=-k, high=k)) bias_attr = ParamAttr( name=prefix + "_b", initializer=fluid.initializer.Uniform( low=-k, high=k)) self._conv2d = fluid.dygraph.Conv2D( num_channels=num_channels, num_filters=num_filters, filter_size=(1, size_k), stride=1, padding=(0, padding), groups=groups, act=act, param_attr=param_attr, bias_attr=bias_attr) def forward(self, x): x = fluid.layers.unsqueeze(input=x, axes=[2]) x = self._conv2d(x) x = fluid.layers.squeeze(input=x, axes=[2]) return x
class PFNetG(fluid.dygraph.Layer): def __init__(self, num_scales, each_scales_size, point_scales_list, crop_point_num): super(PFNetG, self).__init__() self.crop_point_num = crop_point_num self.latentfeature = Latentfeature(num_scales, each_scales_size, point_scales_list) self.fc1 = Linear(input_dim=1920, output_dim=1024, act='relu') self.fc2 = Linear(input_dim=1024, output_dim=512, act='relu') self.fc3 = Linear(input_dim=512, output_dim=256, act='relu') self.fc1_1 = Linear(input_dim=1024, output_dim=128 * 512, act='relu') self.fc2_1 = Linear(input_dim=512, output_dim=64 * 128, act='relu') self.fc3_1 = Linear(input_dim=256, output_dim=64 * 3) self.conv1_1 = Conv1D(prefix='g1_1', num_channels=512, num_filters=512, size_k=1, act='relu') self.conv1_2 = Conv1D(prefix='g1_2', num_channels=512, num_filters=256, size_k=1, act='relu') self.conv1_3 = Conv1D(prefix='g1_3', num_channels=256, num_filters=int((self.crop_point_num * 3) / 128), size_k=1, act=None) self.conv2_1 = Conv1D(prefix='g2_1', num_channels=128, num_filters=6, size_k=1, act=None) def forward(self, x): x = self.latentfeature(x) x_1 = self.fc1(x) # 1024 x_2 = self.fc2(x_1) # 512 x_3 = self.fc3(x_2) # 256 pc1_feat = self.fc3_1(x_3) pc1_xyz = fluid.layers.reshape(pc1_feat, [-1, 64, 3], inplace=False) pc2_feat = self.fc2_1(x_2) pc2_feat_reshaped = fluid.layers.reshape(pc2_feat, [-1, 128, 64], inplace=False) pc2_xyz = self.conv2_1(pc2_feat_reshaped) # 6x64 center2 pc3_feat = self.fc1_1(x_1) pc3_feat_reshaped = fluid.layers.reshape(pc3_feat, [-1, 512, 128], inplace=False) pc3_feat = self.conv1_1(pc3_feat_reshaped) pc3_feat = self.conv1_2(pc3_feat) pc3_xyz = self.conv1_3(pc3_feat) # 12x128 fine pc1_xyz_expand = fluid.layers.unsqueeze(pc1_xyz, axes=[2]) pc2_xyz = fluid.layers.transpose(pc2_xyz, perm=[0, 2, 1]) pc2_xyz_reshaped1 = fluid.layers.reshape(pc2_xyz, [-1, 64, 2, 3], inplace=False) pc2_xyz = fluid.layers.elementwise_add(pc1_xyz_expand, pc2_xyz_reshaped1) pc2_xyz_reshaped2 = fluid.layers.reshape(pc2_xyz, [-1, 128, 3], inplace=False) pc2_xyz_expand = fluid.layers.unsqueeze(pc2_xyz_reshaped2, axes=[2]) pc3_xyz = fluid.layers.transpose(pc3_xyz, perm=[0, 2, 1]) pc3_xyz_reshaped1 = fluid.layers.reshape(pc3_xyz, [-1, 128, int(self.crop_point_num / 128), 3], inplace=False) pc3_xyz = fluid.layers.elementwise_add(pc2_xyz_expand, pc3_xyz_reshaped1) pc3_xyz_reshaped2 = fluid.layers.reshape(pc3_xyz, [-1, self.crop_point_num, 3], inplace=False) return pc1_xyz, pc2_xyz_reshaped2, pc3_xyz_reshaped2 # center1 ,center2 ,fine
訓練
def farthest_point_sample_numpy(xyz, npoint, RAN=True): B, N, C = xyz.shape centroids = np.zeros((B, npoint)) distance = np.ones((B, N)) * 1e10 if RAN: farthest = np.random.randint(low=0, high=1, size=(B,)) else: farthest = np.random.randint(low=1, high=2, size=(B,)) batch_indices = np.arange(start=0, stop=B) for i in range(npoint): centroids[:, i] = farthest centroid = xyz[batch_indices, farthest, :].view().reshape(B, 1, 3) dist = np.sum((xyz - centroid) ** 2, -1) mask = dist < distance distance[mask] = dist[mask] farthest = np.argmax(distance, -1) return centroids.astype('int64')
def chamfer_distance(array1, array2): batch_size, num_point, num_features = array1.shape dist = 0 for i in range(batch_size): av_dist1 = array2samples_distance(array1[i], array2[i]) av_dist2 = array2samples_distance(array2[i], array1[i]) dist = dist + (av_dist1 + av_dist2) / batch_size return dist def array2samples_distance(array1, array2): num_point, num_features = array1.shape expanded_array1 = fluid.layers.expand(array1, [num_point, 1]) array2_expand = fluid.layers.unsqueeze(array2, [1]) expanded_array2 = fluid.layers.expand(array2_expand, [1, num_point, 1]) expanded_array2_reshaped = fluid.layers.reshape(expanded_array2, [-1, num_features], inplace=False) distances = (expanded_array1 - expanded_array2_reshaped) * (expanded_array1 - expanded_array2_reshaped) distances = fluid.layers.reduce_sum(distances, dim=1) distances_reshaped = fluid.layers.reshape(distances, [num_point, num_point]) distances = fluid.layers.reduce_min(distances_reshaped, dim=1) distances = fluid.layers.mean(distances) return distances
dset = PartDataset(root=root, classification=True, class_choice=None, num_point=opt.pnum, mode='train') train_loader = fluid.io.DataLoader.from_generator(capacity=10, iterable=True) train_loader.set_sample_list_generator(dset.get_reader(opt.batchSize), places=place)
實驗結論
個人心得