草图三维模型生成论文阅读整理

论文终于接收啦!给草图研究做个收尾就去投实习!

仅为个人整理,如有错误,欢迎指出!因为想给论文找创新点,所以需要大量阅读论文,部分论文会精读到实现的步骤,部分论文就记录一下思路。

目前基于大模型和深度学习的三维重建任务可以简单分类为text23D,也就是文本控制转三维模型,一般使用语言模型提取文本的特征,然后去噪概率扩散模型生成多视角图像,最后再用NeRF进行三维重建,例如Dreamfusion、Magic3D,这是一个多阶段过程;然后是2D23D,2D23D任务可以分为多视角图像和单视角图像,多视角图像目前已经比较成熟了,比如NeRF系列和传统的colmap等方法,单视角图像我看的论文分为无监督和有监督两种,无监督就是用DM从单视角图像先训练出多视角图像,再用NeRF训练出三维模型,生成的三维模型是从图像来的新的三维模型,所以是无监督的;有监督则是先从原有的三维模型提取多个视角图像,这些视角图像进行单独训练NeRF或者SDF,最后生成三维模型再和原模型进行损失函数计算;然后就是文本和图像结合生成三维模型,手绘草图生成三维模型等等。

从我目前的理解来看,基于NeRF的方法数据集一般只有图像,所以应该是无监督的,从草图开始进行NeRF的三维重建是不现实的,因为草图没有必要的光影信息,而且一般是单视角,重建效果肯定很差,所以用有监督的方法,比如3DDiffusion这种,目前的方法大部分基于ShapeNet的数据集,这个数据集大部分是比较简单固定的形状,比如椅子、桌子、飞机这些,目前是已经有从ShapeNet生成草图的方法了,数据集属于是直接可以获得。

1、Sketch2Model: View-Aware 3D Modeling from Single Free-Hand Sketches

这篇文章是21年的CVPR,把它放在开头主要有两个目的,一个是数据集,它利用了ShapeNet-Synthetic(ShapeNet-合成)和ShapeNet-Sketch以及Existing sketch datasets
三个数据集,后续一些研究都是建立在这几个数据集上的。所以我们先看一下这两个数据集

ShapeNet-Synthetic:我们使用合成草图来训练我们的模型。我们使用Kar等人[18]提供的渲染图像创建合成数据集。它包含来自ShapeNet[1]的13个类别的对象渲染。来自每个对象的20个不同视图的图像以224x224分辨率渲染。我们使用精明的边缘检测器提取每个渲染图像的边缘图,与从3D形状中提取轮廓相比,该检测器不需要3D地面实况。我们直接使用边缘图作为合成草图,并使用该数据集进行训练和评估,在与[22]中相同的训练/测试分割下。合成草图简单来说就是从ShapeNet三维模型开始投影然后提取边缘图构成的。

ShapeNet-Sketch:是采集的手绘草图,我们的ShapeNet草图数据集总共包含1300个徒手草图及其相应的地面实况3D模型。我们仅将此数据集用于评估。

ShapeNetshapenet数据集可以去官网看并且下载,似乎是要注册的

sketch2model - Google 云端硬盘我们这里只关注shapenet的草图数据集,可以从Sketch2Model的github上下载

bennyguo/sketch2model: PyTorch implementation of Sketch2Model: View-Aware 3D Modeling from Single Free-Hand Sketches, CVPR2021. (github.com)

二是作者开源了详细代码,我们可以学习到草图生成三维模型的整体代码,包括数据集读取,模型训练,验证指标等。我们首先看一下模型的整体结构,Sketch2Model的核心思想就是视点感知,将视角信息融入到模型生成中来。

所以我们可以看到模型的输入主要有两点,分别是草图I,以及草图所代表的特定视角V,通常的做法如上图a所示通过对草图进行编码解码,然后再输入视角V来完成渲染。作者则进一步提出了b的框架,看起来非常复杂,但我们只要抓住编码器解码器就可以理解,首先是输入草图,其通过编码器将草图特征编码进了视角空间Zv和形状空间Zs两个,Zs其实就是a中的Z,而Zv则是新的。具体做法是先通过一个编码器(ResNet18)编码输入草图特征,再接一个由MLP构成的编码器,将草图特征分别编码进Zs和Zv

class Encoder(nn.Module):
    def __init__(self, dim_in, dim_hidden, dim_s, dim_v, normalize=True):
        super(Encoder, self).__init__()
        self.fc1 = nn.Linear(dim_in, dim_hidden)
        self.fc2 = nn.Linear(dim_hidden, dim_hidden)
        self.fc_s = nn.Linear(dim_hidden, dim_s)
        self.fc_v = nn.Linear(dim_hidden, dim_v)
        self.normalize = normalize

    def forward(self, x):
        x = F.relu(self.fc1(x), inplace=True)
        x = F.relu(self.fc2(x), inplace=True)
        zs = F.relu(self.fc_s(x), inplace=True)
        zv = F.relu(self.fc_v(x), inplace=True)
        if self.normalize:
            zs = F.normalize(zs, dim=1)
            zv = F.normalize(zv, dim=1)
        return zs, zv

Zs根据a中的技术路线,可以直接通过Decode得到mesh,而Zv其实很关键,因为并不是所有草图都能自带视角信息,尤其是手绘草图,所以作者设置了一个Dv(ViewDecoder)来解码Zv预测草图视角,并和合成草图的自带真实视角信息进行比较,那么当我们输入一个没有视角信息的草图时,就可以通过这一步生成这个草图的视角信息,同时为了加强视角信息的作用,作者将其编码后和Zs一起输入进解码器生成mesh。

那么整体流程推理如下,首先就是ResNet18提取草图特征,编码器编码特征到Zs和Zv_pred,然后解码Zv_pred得到预测的V,编码V得到视角信息,和Zs一起解码得到预测的mesh。

            ft = self.feature_extractor(image[:,:self.opt.dim_in])
            zs, zv_pred = self.encoder(ft)
            view_pred = self.view_decoder(zv_pred)
            zv_recon = self.view_encoder(view_pred)
            z = self.decoder(zs, zv_recon)
            vertices, faces = self.mesh_decoder(z)
            return {
                'vertices': vertices,
                'faces': faces,
                'view_pred': view_pred
            }

在训练过程中,作者还通过随机一个视角,来解决如果在没有任何其他约束的情况下进行训练,则可能会发生一种常见的退化,即M直接从Zs生成,完全忽略Zv。我们提出了一种随机视图强化训练策略来解决这个问题。 

            """Training / Validation / Testing"""
            ft = self.feature_extractor(image[:,:self.opt.dim_in])
            zs, zv_pred = self.encoder(ft)
            view_pred = self.view_decoder(zv_pred)
            zv_recon = self.view_encoder(view_pred)
            zv = self.view_encoder(view)
            view_recon = self.view_decoder(zv)
            z = self.decoder(zs, zv) # teacher forcing
            z_pred = self.decoder(zs, zv_recon)
            vertices, faces = self.mesh_decoder(z)
            vertices_pred, faces_pred = self.mesh_decoder(z_pred)
            sd_score = self.shape_discriminator(vertices.view(N, -1))
            rv = {
                'vertices': vertices,
                'faces': faces,
                'vertices_pred': vertices_pred,
                'faces_pred': faces_pred,
                'view_pred': view_pred,
                'view_recon': view_recon,
                'zv_pred': zv_pred,
                'zv': zv,
                'zv_recon': zv_recon,
                'sd_score': sd_score
            }
            
            if view_rand is not None:
                """Training"""
                zv_rand = self.view_encoder(view_rand)
                z_rand = self.decoder(zs, zv_rand)
                vertices_rand, faces_rand = self.mesh_decoder(z_rand)
                sd_score_rand = self.shape_discriminator(vertices_rand.view(N, -1))
                rv.update({
                    'vertices_rand': vertices_rand,
                    'faces_rand': faces_rand,
                    'zv_rand': zv_rand,
                    'sd_score_rand': sd_score_rand
                })

这篇文章还有一个重要的点就是损失函数的设计,首先是IoU,指的是生成模型的投影图和输入草图轮廓的IoU。

def iou(pred, target, eps=1e-6):
    dims = tuple(range(pred.ndimension())[1:])
    intersect = (pred * target).sum(dims)
    union = (pred + target - pred * target).sum(dims) + eps
    return (intersect / union).sum() / intersect.nelement()


class IoULoss(nn.Module):
    def __init__(self, opt):
        super().__init__()
        self.opt = opt
    
    def forward(self, pred, target):
        return 1 - iou(pred[:, 3], target[:, 3])


class MultiViewIoULoss(nn.Module):
    def __init__(self, opt):
        super().__init__()
        self.opt = opt
    
    def forward(self, pred, target_a, target_b):
        return (
            1 - iou(pred[0][:, 3], target_a[:, 3]) +
            1 - iou(pred[1][:, 3], target_a[:, 3]) +
            1 - iou(pred[2][:, 3], target_b[:, 3]) +
            1 - iou(pred[3][:, 3], target_b[:, 3])
        ) / 4.

随后是flatten loss and and laplacian loss来作为mesh的shape regularization loss

class LaplacianLoss(nn.Module):
    def __init__(self, opt):
        super().__init__()
        self.opt = opt
        self.template_mesh = sr.Mesh.from_obj(opt.template_path)
        self.loss = sr.LaplacianLoss(
            self.template_mesh.vertices[0].cpu(),
            self.template_mesh.faces[0].cpu()
        ).to(opt.device)

    def forward(self, v):
        return self.loss(v).mean()


class FlattenLoss(nn.Module):
    def __init__(self, opt):
        super().__init__()
        self.opt = opt
        self.template_mesh = sr.Mesh.from_obj(opt.template_path)
        self.loss = sr.FlattenLoss(
            self.template_mesh.faces[0].cpu()
        ).to(opt.device)
    
    def forward(self, v):
        return self.loss(v).mean()

 接着是视角预测的损失函数,也就是Dv,使用L2,很好理解,就是预测的视角和真实视角做损失函数

接着是Ev的损失函数,使用真实的V作为输入

最后是两个鉴别器的损失函数,鉴别器是GAN里的内容,后面有机会再展开讲吧

最终的损失函数,

这里我们再来着重关注一下验证指标,作者用了两个最重要的指标Voxel IoU和Chamfer Distance,因为我们自己的论文也需要指标测试,voxel_iou_pred意思是用预测的视角三维重建的结果

 self.val_loss_names = ['voxel_iou', 'voxel_iou_pred']
self.test_loss_names = ['voxel_iou', 'voxel_iou_pred']
def voxel_iou(pred, target):
    return ((pred * target).sum((1, 2, 3)) / (0 < (pred + target)).sum((1, 2, 3))).mean()
voxel_gt = self.data_voxel.cpu().numpy()
faces = srf.face_vertices(self.out_vertices, self.out_faces) * 31. / 32. + 0.5
voxel = srf.voxelization(faces, 32, False).cpu().numpy().transpose(0, 2, 1, 3)[...,::-1]
faces_pred = srf.face_vertices(self.out_vertices_pred, self.out_faces_pred) * 31. / 32. + 0.5
voxel_pred = srf.voxelization(faces_pred, 32, False).cpu().numpy().transpose(0, 2, 1, 3)[...,::-1]
iou, iou_pred = voxel_iou(voxel, voxel_gt), voxel_iou(voxel_pred, voxel_gt)

 至于Chamfer Distance我并没有看到,这里记录一下Pytorch3D里的计算


def chamfer_distance(
    x,
    y,
    x_lengths=None,
    y_lengths=None,
    x_normals=None,
    y_normals=None,
    weights=None,
    batch_reduction: Union[str, None] = "mean",
    point_reduction: Union[str, None] = "mean",
    norm: int = 2,
    single_directional: bool = False,
    abs_cosine: bool = True,
):
    """
    Chamfer distance between two pointclouds x and y.

    Args:
        x: FloatTensor of shape (N, P1, D) or a Pointclouds object representing
            a batch of point clouds with at most P1 points in each batch element,
            batch size N and feature dimension D.
        y: FloatTensor of shape (N, P2, D) or a Pointclouds object representing
            a batch of point clouds with at most P2 points in each batch element,
            batch size N and feature dimension D.
        x_lengths: Optional LongTensor of shape (N,) giving the number of points in each
            cloud in x.
        y_lengths: Optional LongTensor of shape (N,) giving the number of points in each
            cloud in y.
        x_normals: Optional FloatTensor of shape (N, P1, D).
        y_normals: Optional FloatTensor of shape (N, P2, D).
        weights: Optional FloatTensor of shape (N,) giving weights for
            batch elements for reduction operation.
        batch_reduction: Reduction operation to apply for the loss across the
            batch, can be one of ["mean", "sum"] or None.
        point_reduction: Reduction operation to apply for the loss across the
            points, can be one of ["mean", "sum"] or None.
        norm: int indicates the norm used for the distance. Supports 1 for L1 and 2 for L2.
        single_directional: If False (default), loss comes from both the distance between
            each point in x and its nearest neighbor in y and each point in y and its nearest
            neighbor in x. If True, loss is the distance between each point in x and its
            nearest neighbor in y.
        abs_cosine: If False, loss_normals is from one minus the cosine similarity.
            If True (default), loss_normals is from one minus the absolute value of the
            cosine similarity, which means that exactly opposite normals are considered
            equivalent to exactly matching normals, i.e. sign does not matter.

    Returns:
        2-element tuple containing

        - **loss**: Tensor giving the reduced distance between the pointclouds
          in x and the pointclouds in y. If point_reduction is None, a 2-element
          tuple of Tensors containing forward and backward loss terms shaped (N, P1)
          and (N, P2) (if single_directional is False) or a Tensor containing loss
          terms shaped (N, P1) (if single_directional is True) is returned.
        - **loss_normals**: Tensor giving the reduced cosine distance of normals
          between pointclouds in x and pointclouds in y. Returns None if
          x_normals and y_normals are None. If point_reduction is None, a 2-element
          tuple of Tensors containing forward and backward loss terms shaped (N, P1)
          and (N, P2) (if single_directional is False) or a Tensor containing loss
          terms shaped (N, P1) (if single_directional is True) is returned.

简单来说Voxel IoU计算的是mesh格式的, Chamfer Distance计算的是点云,如果我们要衡量重建的三维模型是否接近原来的三维模型,这两个指标就够了,但是这是有监督的,如果是无监督生成,我们要怎么判断生成的好不好呢?

1、Diffusion-SDF: Text-to-Shape via Voxelized Diffusion

这篇文章不是草图到三维模型,但是用到了SDF-Diffusion的思路,所以也介绍了。提出了一个文本到三维模型的框架Diffusion-SDF,提出了用UinU-Net取代传统的Unet,引导出了新任务Text-Guided Shape Completion(文本引导形状完成,在文本引导下生成不完整形状的缺失部分)和Text-Guided Shape Manipulation(文本导向形状操纵,用文本来控制生成模型的细节具体形状)

提出的文本到三维模型分为两个阶段,第一个阶段为SDF Autoencoding, (Signed) Distance Function(SDF),中文名为符号距离函数,SDF有2D和3D的区别,它的定义非常简单:每个像素(体素)记录自己与距离自己最近物体之间的距离,如果在物体内,则距离为负,正好在物体边界上则为0。论文里使用了truncated signed distance functions(TSDF)TSDF是SDF的改进,讲取值限制在[-1,1]之间,同时仅在物体表面的限定的距离范围内进行计算,降低了计算量。

简单来说,SDF和TSDF都是三维形状表明的隐式表达方式,通过SDF我们可以得到所需几何体的细节表明信息

小白科研笔记:从零学习基于TSDF的三维重建_tsdf融合-CSDN博客

TSDF地图算法分析 实时三维重建 - 知乎 (zhihu.com)

TSDF思路很朴素,用一个大的空间包围盒(volume)去包括进去待3D构建的场景,volume成多个voxel(小立体方块):

TSDF的具体计算过程可以参考其他博客,论文作者将一个三维模型分成好几个空间包围盒构成,然后对每个空间包围盒进行TSDF计算,三维空间包围盒会生成三个视角的TSDF结果,也就是流程图中的Xp,作者这样子做的原因是为了更好地获取局部细节信息,同时降低输入数据的尺寸。

随后TSDF得到的特征向量,类似于N*3*P*P,作者用VAE-like autoencoder对其进行编码至latent representations Zp ∈ R^c,也就是N*C,c is the number of latent channels。同时为了保存不同patch之间的全局信息,又将Zp rearranged into a voxel grid embedding Z(rearrange是如何保存原有的patch空间信息的?从流程图中应该是arrange成了sqrt(NC)*sqrt(NC),论文中没有提这个Z的具体大小)

随后进入第二阶段,这个阶段是一个3D的diffusion模型,这里回顾一下diffusion的训练阶段和采样阶段,在该模型的训练阶段数据集会给出对应的三维模型和文本输入,编码得到特征向量Z,然后生成随机高斯噪声将输入Z一步步加噪成高斯分布的三维模型噪声,并用UinU-Net预测噪声,计算两个噪声之间的损失函数,使得UinU-Net在有文本条件输入的情况下尽可能预测出相近的噪声,采样阶段直接输入对应的文本和随机高斯分布三维模型即可通过UinU-Net预测相关噪声,然后再一步步减去,得到想要的特征Z^,这个特征随后会一次性解码为最大包围盒的TSDF X~,然后就可以得到根据文本重建的三维模型了。

这整个过程论文中叫做Voxelized Diffusion Models (VDMs)

梳理完流程后,再来看其新提出的UinU-Net,主要改进就是在新加了一个内网,主要由1*1*1的卷积构成,能够更好地提取各个patch特征,并利用spatial transformer提取不同patch之间地特征关系,文本输入的特征提取由原U-Net的cross-attention完成

 Spatial Transformer不是自注意力机制的那个Transformer变种,而是针对卷积改进的一种策略,具有可导性质的STN不需要多余的标注,能够自适应的学到对于不同数据的空间变换方式。它不仅可以对输入进行空间变换,同样可以作为网络模块插入到现有网络的任意层中实现对不同Feature map的空间变换。最终让网络模型学习了对平移、尺度变换、旋转和更多常见的扭曲的不变性,也使得模型在众多基准数据集上表现出了更好的效果。

理解Spatial Transformer Networks - 知乎 (zhihu.com)

除了根据文本生成模型以外,作者还提出了其他两个任务

Text-Guided Shape Completion:根据输入的部分三维模型形状和文本生成三维模型

做法是将已知的部分作为条件输入进 VDM的UinU-Net的训练阶段

Text-Guided Shape Manipulation:根据输入的三维模型形状和文本对已有的三维模型进行形状调整

做法和Text-Guided Shape Completion类似,将原模型作为VDM的条件输入

实验数据集是Text2Shape (T2S)

【论文阅读】Text2Shape: Generating Shapes from Natural Language by Learning Joint Embeddings - 知乎 (zhihu.com)

评价指标 IoU 计算的是SDF的IoU,Acc 用于衡量生成样本的语义真实性。CLIP-S(CLIP Similarity Score) 测量生成的样本和输入文本之间的语义一致性,TMD (Total Mutual Difference)评估每个给定文本查询的生成多样性

2、Locally Attentional SDF Diffusion for Controllable 3D Shape Generation

作者提出了目前三维模型生成的两个问题,生成模型质量不行(However, there exists a large quality gap between the synthesized shapes and the dataset the generator was trained on),模型控制性不够(Moreover, existing approaches lack intuitive control and convenient ways to control the shape generation process to satisfy users’ intentions)。

对于生成模型质量问题,作者认为有两个原因造成的,一是目前常用的三维表达形式是离散的导致了质量不好,例如点云和体素(Previous methods focus mainly on generating 3D shapes with discrete point cloud or voxel representations. The discretization error caused by the limited output resolution degrades the output quality.),它们还需要显示表达转换到连续形式,进一步降低了质量,二是所选择的生成技术的能力对于具有复杂结构的3D形状建模可能是有限的,这里主要是针对3D-GAN的问题。

对于控制性问题,作者认为目前有text2shape的研究,但草图更加直观(2D sketching is a natural interface for people with diverse backgrounds to depict, explore, and exchange creative ideas),而基于草图生成三维模型的研究相对较少。

所以对于质量问题,他们选用了SDF来表达三维模型,并用diffusion来生成,并且引入了草图作为输入,提出了locally attentional SDF diffusion(LAS-Diffusion)

在方法方面,作者提出了如上图所示的两阶段方案,第一个阶段叫做Occupancy-diffusion,将64^3的噪声体素网格作为输入,草图部分的信息作者用ViT进行特征编码提取,然后用View-aware Local Attention将特征引入到网格中,再用diffusion模型进行三维重建。

第二个阶段叫做SDF-diffusion,将第一阶段得到的64^3的体素网格分割为128^3,然后再进行细节的三维重建。作者这样子做的原因是直接用大体素网格会导致太大的计算量。

View-aware Local Attention

可以简单理解成用ViT提取图像特征,然后用交叉注意力机制结合进U-Net的推理,这里的二维三维对齐有些玄学...作者的意思应该就是一块对应图像的一部分。

仔细阅读代码以后,其实是ViT中间层输出的特征分别是分类和每一块的特征,作者就取了ViT输出的每一块特征来做交叉注意力机制结合,确实是有局部对应的感觉。

实验

数据集 ShapeNetV1 五类:椅子、汽车、飞机、桌子和步枪

数据预处理:一个三维模型会有很多个草图进行训练,首先是定下五个不同的视角,然后每个视角会添加扰动,随机扰动是通过±22.5°内的噪声扰动方位角和±5°内的噪音扰动仰角来实现的,每个视角会扰动十次,再用Canny edge detector生成投影,所以每个三维形状总共会有50张草图


 评价指标

CLIP score评估感知差异性(perception difference)

将原来的输入草图和重建后的三维模型的投影草图进行Clip特征提取对比

其余指标如CD, EMD, and Voxel-IOU来自SketchSampler
CD(Chamfer Distance)广泛用作3D生成和重建任务的评估度量

Chamfer Distance--倒角距离-CSDN博客

EMD(Earth Mover’s Distance)用于评估两个点云之间的相似性。但它对局部细节和密度分布更敏感。

Voxel-IoU测量两个体积模型的覆盖百分比。

实验结果

从重建效果来看非常不错,

视图方面:对视图的泛用性好,输入不同的视图可以得到同样的三维模型,对未训练的新试图也能重建出

草图指导方面:草图出现变化后,重建模型也会出现对应变化

模型多样性方面:对于未知结构,未知类别的草图也能生成,手绘草图也OK

消融实验

注意力结构消融

Global attention:我们不使用局部补丁特征,而是直接使用全局图像特征来指导体素特征学习。全局特征来自预先训练的ViT主干的分类标记。它通过MLP进行投影,以与U-Net特征维度对齐,并通过逐元素乘法与每个级别的占用扩散模块的U-Net特征向量相关联

View-agnostic attention:体素特征通过交叉关注与所有图像补丁特征相互作用

这个消融实验结果有些刻勤了,应该是特意挑选的...

3、Sketch-A-Shape: Zero-Shot Sketch-to-3D Shape Generation

作者提出了一个无监督从草图生成三维模型的方法。

作者认为目前从草图生成三维模型存在三个问题:

Firstly, there is a lack of (Sketch, 3D shape) paired data at a large scale which forces most methods to be trained on synthetic datasets or data collected on only few categories.

首先是缺乏足够数量和类别的草图-三维模型配对数据。

Even when a small number of categories of paired sketch-shape data has been collected[35], current methods fail to generalize to different levels of abstractions in the sketches, ranging from casual doodles to detailed professional drawings.

其次,在目前的数据集上取得的重建效果也无法适用于不同抽象级别的草图,例如随手画的和专家画的。

Finally, most of the present methods incorporate strong inductive biases, such as view information [79], differentiable rendering [20] and depth estimation [39, 16], thereby constraining their generalizability across 3D representations.

最后,目前的重建方法引入了过强的归纳偏置,例如视角信息,可微分渲染[20]和深度估计[39,16],从而限制了它们在3D表示中的可推广性。

因此,作者认为通过大规模图像训练的图像-文本模型可以解决这些问题,所以提出了一个基于训练好的大规模图像-文本模型的草图 生成三维模型框架

整个框架分为两部分,首先是1)Discrete Autoencoder,这部分是要训练的一个编码器和解码器结构,目标是获得从shape embedding解码获得重建形状的网络,编码器选用的是VQ-VAE

轻松理解 VQ-VAE:首个提出 codebook 机制的生成模型 - 知乎 (zhihu.com)

我在看了VQVAE之后发现这个模型几乎就是VQVAE在三维和草图方面的应用版本,VQVAE用的是解码器加上编码图像的PixelCNN,这个模型是类似的。

2)Prior Model:这一部分其实很有意思,我其实一直在思考怎么更好地从草图中获得三维重建的有效信息,目前最常用的方法其实是用预训练好的自然图像特征提取网络,作者在这里主要训练的是Masked Transformer作用是从Masked Shape Embeddings预测得到完整的Predicted Shape Embeddings。

那么完整的流程就是先给出一个完全Masked的shape embeddings,然后不停的训练预测得到Predicted Shape Embeddings,再解码得到最后的模型。

因为是无监督生成的,所以评价指标是ACC,通过人工判断生成的模型是否符合草图特征

猜你喜欢

转载自blog.csdn.net/fisherisfish/article/details/134197522