《Neural Pose Transfer by Spatially Adaptive Instance Normalization》

概括: 对identity mesh 做pose transfer, 实际上是让提供目标pose的human mesh 学到identity的style。关键在于要让生成的mesh的点的顺序和identity mesh的一致而不是pose mesh。

 《Neural Pose Transfer by Spatially Adaptive Instance Normalization》_第1张图片

传统的做法是学习在同一个pose下,不同identity style 之间的correspondence,利用correspondence 去算displacement。

《Neural Pose Transfer by Spatially Adaptive Instance Normalization》_第2张图片

做法:这里用PointNet提取点的特征,把每个vertex当做一个point , 但是注意,mesh和point cloud还是不同的,在mesh里我们还需要考虑face, 也就是每个面上的顶点,点与点的连接方式会影响我们的最后结果。

input data中包含identity mesh和pose mesh,用mesh = pymesh.load_mesh读出来是(6890,3) ,也就是6890个点,3通道代表坐标,mesh.faces 还可以得到这个human body的面(13776,3),一共13776个面,这里的3通道指的是组成一个面的3个连接点的index。

对于pose_mesh,文章里用到两种处理方式, 这里贴出代码可以直观一点。

class PoseFeature(nn.Module):
    def __init__(self, num_points = 6890):
        super(PoseFeature, self).__init__()

        self.conv1 = torch.nn.Conv1d(3, 64, 1)
        self.conv2 = torch.nn.Conv1d(64, 128, 1)
        self.conv3 = torch.nn.Conv1d(128, 1024, 1)

        self.norm1 = torch.nn.InstanceNorm1d(64)
        self.norm2 = torch.nn.InstanceNorm1d(128)
        self.norm3 = torch.nn.InstanceNorm1d(1024)

        ### torch.nn.InstanceNorm1d [N,C,L] -> [N,C,L]
        self.num_points = num_points

    def forward(self, x): # B, 3,6890

        x = F.relu(self.norm1(self.conv1(x)))
        x = F.relu(self.norm2(self.conv2(x)))
        x = F.relu(self.norm3(self.conv3(x)))
############# model_maxpool
        x,_ = torch.max(x, 2) #归一化 B 1024 1
        x = x.view(-1, 1024)
        x = x.view(-1, 1024, 1).repeat(1, 1, self.num_points)  # B 1024 6890

        return x

一种处理方式是在### model__maxpool 上面就结束了,在这一步就把x=F.relu(xxx) 作为最终结果return, 一种处理方式是加上下面三行代码,用torch.max 先对dim=2 归一化,然后再复制6890个,这样子做应该是为了证明无论所有点的Order如何,都不影响最终的结果,因为都是取最大的那个点再复制。

需要注意的是,不同于我们在图像上做2维卷积,会对图像的大小进行改变,随着叠加卷积层,特征图会越来越小(如果不考虑Padding的话),而在3d上做1维卷积,用的都是kernel=1的卷积核,不会改变大小,整个过程只改变了通道数。

后面的decoder是参考图像上spade的方法,之前也有介绍过,就不详述了。

你可能感兴趣的:(3D,点云,pytorch)