Inverting Generative Adversarial Renderer for Face Reconstruction

1. 前言

这篇文章是2021年CVPR的oral,方法名翻译为“基于反向生成对抗渲染的三维面部重建”,个人觉得它里面提供的思路挺新颖的,并且也开放了源码,点此查看

2. 相关研究介绍

目前的主流人脸三维重建技术大致分为两类方式,基于学习的方式与基于优化的方式。基于学习的方式,是借助CNN来回归控制人脸三维结构的3DMM系数,但是缺点便是依赖三维标注数据集,而3DMM的真实值其实是很难获取到的,这种三维数据集非常稀缺;基于优化的方式,是将所输入的二维人脸图像看做是一个生成的过程,由一系列的参数控制,如albedo(反照率,可以理解为人脸表面的不加光照的基础颜色)、纹理、光照、观察角度等,按照特定的渲染图像的法则最终计算出来二维人脸图像,而这样我们就可以通过比较渲染图像与输入图像的差异进行优化了,但是缺点是所使用的渲染图像法则决定了重建效果的上限,这种法则其实是简化了很多复杂过程的。
最近的可微分渲染应用优化了以上两种方法,比如我使用3DMM系数渲染后的图像,可以通过比较与输入图像的差异进行优化(相当于结合了两种方法的好处,不再依赖数据集,有篇参考文章《Accurate 3d face reconstruction with weakly-supervised learning: From single image to image set》CVPR Workshop 2019),当然可微分渲染也有两个缺点,一是渲染的过程是人为指定的,像基于优化的方法一样,渲染出的图像不是很真实,二是可微分渲染器很难优化,它只能将误差反向传播给局部顶点(个人理解为很难调控全局的信息,比如这个人的身份特征)。
diff
如上图所示,文章将自己的方法渲染出的图像与最近的一些方法进行了比较,可以看到3DDFA使用的渲染(得到最终的3DMM系数后进行普通渲染)和GANFIT使用的渲染(通过可微渲染一步步优化3DMM系数)生成的图像都不是那么真实。这种所谓不真实的渲染方法文中称作graphics-based,就是图形学中通用的栅格化渲染,其实我们玩过很多的3A大作游戏,虽然图像很逼真,但是总是感觉和现实有那么一点差距,作者这里就认为是图形学里的渲染管线结构本身导致了这种不真实,如果替换成神经网络可能结果会更加逼真一点(可惜在图形学里是不可能用神经网络进行渲染的)。虽然有些文章对渲染过程做了优化,还是很难解决这种问题,如《Neural 3d mesh renderer》CVPR 2018、《Soft rasterizer: Differentiable rendering for unsupervised singleview mesh reconstruction》。
那么既然普通渲染、可微渲染太假,那么我将其升级为神经网络渲染会如何呢,也不太行,如上图d的DFG方法《Disentangled and controllable face image generation via 3d imitative-contrastive learning》CVPR 2020所示,输入是3dmm系数,但是神经网络渲染器要理解3DMM系数这种抽象的东西实在太难了,以至于生成的人脸和我们想要的人脸根本不是一个人。

3. 文章提出的方法

在读之前,建议先了解下styleGAN和styleGAN v2这两篇文章,因为后面的方法是基于style GAN v2的结构的。
先简单说一下个人理解的本文思想脉络:

  1. 如果我直接采用一般的渲染方式(图形学里通用的栅格化渲染),通过比较渲染图像与原图的像素差异,去优化控制人脸的3DMM系数(形状系数),会产生问题:因为本身这种渲染的方式渲染的图像根本就不真实,所以我再继续去比较像素差异的话肯定对于优化的效果来说没有说服力(文中称会产生domainshift noise)。所以这篇文章在渲染方式上进行了改进,基于自己改进的style GAN v2的结构来进行渲染,这样一来,我先保证了渲染出的图像足够真实,那么在能够渲染出真实图像的基础上按照像素差异去优化3DMM系数,肯定就有说服力了。
  2. 这个渲染器借鉴了style GAN v2的结构,输入是z(latent code,在style GAN里面控制着生成人脸图像的风格,如肤色、性别、年龄等,在本文里,作者设计了一种loss方法让他尽量控制人脸形状之外的人脸属性,如人脸纹理)、noise(在style GAN 里面保证生成图像细节方面的多样性)、normal map(法线贴图,style GAN里面没有这种东西,在本文里作者也是在训练时用loss方法让其控制人脸的形状;而法线贴图可以通过3DMM系数的形状与表情系数、拍摄角度系数得到)。通过类似于style GAN的训练方式,得到了这样一个效果较好的渲染器。
  3. 当然在这个渲染器的训练过程中,得考虑尽量让渲染出的图像的形状由法线贴图控制,还得考虑别让z和法线贴图的作用太相似(称之为解耦合),因为我们希望z和法线贴图控制的是图像的不同属性,这些问题作者通过设计了不同的损失函数来解决。这个渲染器训练解决的是什么问题呢,是根据输入,去尽量生成像训练数据集里面人脸的图像(或者说就是去尽量生成真实人脸图像),而毕竟是GAN网络嘛,数据集图像是没有标注的,整个过程是自监督训练。
  4. 有了这样一个完美的渲染器,下面就可以固定渲染器里面的各种参数不动,进行渲染器的各种输入参数的优化了,主要优化项包括z(latent code,可以相当于三维人脸的纹理)、3DMM形状与表情系数和姿态(就是相机拍摄角度)系数,其中虽然法线贴图作为渲染器输入,应该优化的是法线贴图才对,但是毕竟法线贴图背后是由3DMM系数控制的,所以就当做优化这些3DMM系数了。
  5. 其中在优化的时候还有个问题,渲染器的输入参数z是随机初始化的吗?万一最终结果陷入局部极小值怎么办?于是作者把这个渲染器给反转过来(就搞了个渲染器的对称结构,比如上采样改成下采样这样,有篇文章《 Seeing what a gan cannot generate》 ICCV 2019 就讨论了如何反转GAN网络获得latent code),将要进行三维重建的输入图像先当做渲染结果,预测一个靠谱的输入来进行渲染器的输入参数初始化,然后将这个初始化输入丢入渲染器进行渲染,按理说得到的渲染图像和输入图像应该八九不离十了,这时再进一步优化微调,应该就能避免局部极小值这样的问题了。
  6. 刚刚把z的初始化给解决了,那法线贴图该如何初始化呢,或者说3DMM系数该如何初始化呢,很简单,1999年提出3DMM系数的那篇文章就提出了一种基于2D关键点拟合3DMM系数的方法,直接搬过来用就行了~
  7. 最后我们回过神来想想,这篇文章因为使用的渲染方式与传统不一样,所以三维人脸的表示方式也与传统不太一样,比如三维人脸的纹理给换成了z进行表示,那我就无法导出obj文件了呀。不过好在三维人脸的3DMM形状系数与姿态系数还和传统一样,如果我想进行三维人脸的编辑的话也能勉强行得通,并且我的渲染结果比传统方法更真实,算是有失也有得吧~

梳理完文章的思想脉络,我们再来看具体的设计方法:

3.1 渲染器结构(GAR)

render
图中左边部分就是生成对抗渲染器(GAR)的结构图,整个渲染器的结构基于style GAN v2进行改进得到,在渲染的时候(黑线部分),接收z、noise、normal map三个输入,其中这三个输入在每一个渲染块都会产生作用(如果仅仅在输入渲染块产生作用的话,那么经过一层一层之后对最终结果就影响甚微了,这也是style GAN设计的核心思想),网络中的C1是一个固定的输入,相当于初始的特征图( 4 ∗ 4 4*4 44分辨率,512通道),每经过一层渲染块,分辨率会加倍, 8 ∗ 8 8*8 88 16 ∗ 16 16*16 1616一直到 1024 ∗ 1024 1024*1024 10241024。而每一层渲染块的具体结构如下图所示:
block
之前的z经过8层MLP转换到了参数w,可以认为将z所蕴含的特征进行了展开(因为z的特征比较紧凑,关联也高,不解耦合的话模型很难学习到有用的东西),而w如何控制每一个渲染块呢,如下面公式所示:
kernel
每一个渲染块都有一个卷积核,w通过对卷积核进行仿射变换(按理说仿射变换是对数据进行缩放和平移操作的,style GAN就是这样,但是style GAN v2将平移给去掉了,只剩下缩放),其实就相当于变相地对特征图(每一层渲染块的输出,最开始是C1)进行仿射变换了,而这种仿射变换,在style GAN v2里面正是影响图像风格的关键因素。上面的公式,c代表卷积核的通道,i和j代表卷积核像素的坐标,整个分子是图中的Mod模块(调制,modulation),分母是图中的Dem模块(解调制,demodulation),其实可以理解为根据方差进行数据的归一化(毕竟训练神经网络一般也要进行batchnorm的嘛)其中的 ϵ \epsilon ϵ是为了防止除以0。
之后就是进行简单的卷积了,如下面公式所示:
juanji
之后该如何将法线贴图作用到我们的网络中呢,作者提出的NIM(法线注入)模块做的是下面的操作:
norm
上面的 f f f是个三维的向量, n x y n_{xy} nxy代表法线贴图(x,y)处的值,法线贴图的RGB通道就相当于该点法线的x,y,z值了,也是个三维向量,对应相乘,就完成所谓的法线注入了~

3.2 渲染器损失函数

了解了渲染器的结构,下面就来看看作者是如何设计损失函数的

3.2.1 法线一致性损失

我们在法线注入模块将法线贴图作用在了最终的输出,那么我们肯定希望法线贴图是对最终渲染图像的形状有影响,而不是其它方面,于是,我们让渲染出的图像的法线贴图与渲染输入的法线贴图两者尽量一致,这样就能让法线注入模块发挥控制渲染图像形状的作用了,于是有如下损失函数:
norm con
P可以看做是一个遮罩,遮挡不输入面部的区域,让它们别发挥作用,n是渲染器输入的法线贴图,N这里采用的是SFSNet,预测渲染图像的法线贴图。对应像素相乘,得到损失函数。

3.2.2 面部关键点一致性损失

在保证法线贴图对渲染图像的形状有影响之后还不够,因为还有latent code z控制着渲染图像的结果,我们希望让z别去控制形状,于是得考虑一种损失函数让二者解耦合,于是就有了下面的损失函数:
ldmk
具体是什么原理呢,如果我让渲染器渲染两次,这两次的输入法线贴图是相同的,但是z不同,我们希望这两次输出的形状相同,其它方面不做追究,不就能够解决这个问题了吗。上面的G是渲染器,L是人脸关键点检测,用人脸关键点的距离来代替形状相似性的判断。

3.2.3 身份损失

有了上面的损失,看似就已经ok了,但是还不够,作者还在渲染出人物的身份性上做文章(类似于GANFIT),在法线贴图不同的时候,渲染出的人物可能是同一个人,可能是不同的人,具体是由其背后的3DMM系数与姿态系数(相机参数)控制的,于是为了让渲染器能够捕捉到法线贴图所蕴含的身份信息,提出了如下损失函数:
id
式子很简单,就是为了保证相同的形状 α \alpha α与相同的z的前提下,对于不同的表情与拍摄角度,渲染器渲染出的是同一个人,其中的R是一个人脸识别网络

3.2.4 总的损失函数

如下图所示
gan
其中的adv这个损失函数就是style GAN v2的损失函数

3.3 开始重建

当根据前面的损失函数与数据集训练好渲染器之后,我们就可以根据输入图像与渲染图像的像素差异进行三维重建了,具体损失如下所示:
niniminze
可以看到优化的参数是这5个,与传统的三维重建相比,文章直接是用z来表示人脸纹理了,emmm确实有点抽象了。
重建的过程中,肯能需要对参数进行初始化的,那么是随机初始化吗?这样的话,作者根据《 Seeing what a gan cannot generate》 ICCV 2019 这篇深入分析GAN本质的文章,认为这样会陷入一种局部极小值,所以设计了一种反转的方式,去较好地初始化输入参数。
参数的初始化分为两部分,一部分是初始化z,通过设计了与渲染器对称的一种反转网络结构,用统计平均值和方差来估计z,如下式子所示:
z
其中为了估计初始输入, I o u t I_{out} Iout就给换成输入要准备重建的图像了,根据估计的初始输入再正向渲染一波,渲染图应该就和输入图像差个不离了。
另一部分参数的初始化就是3DMM系数了,直接用简单粗暴的传统方法:
3d
具体可以看《A morphable model for the synthesis of 3d faces》这篇1999年的古董论文。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值