1. 论文大致介绍
论文是基于GAN网络的高精度、基于单张图片的人脸三维重建,重建效果如下图所示
我们可以看到人脸的细节还原得特别详细,总而言之,本篇论文的特点如下
- 与传统生成3dmm的颜色系数的方法不同,本文使用GAN网络生成一张高分辨率的人脸UV纹理图,代替3dmm颜色系数来表示人脸的纹理,因此能够还原出很多详细的细节
- 基于设计的GAN网络与可微渲染器(三维的物体渲染成二维图像的时候,其实本质上是进行了一系列矩阵变换,这和神经网络有一定的相似之处,渲染相当于前向传播,而进行反向传播的时候,其实就是根据二维图像来推导三维信息),设计了人脸拟合策略(fitting)(其实所谓的拟合就是求与三维人脸重建相关的各种参数,有了这些参数就能得到三维人脸了)
- 设计了许多损失函数来帮助人脸拟合
2. 相关研究介绍
关于人脸重建,20年前的Volker Blanz 和 Thomas Vetter发表的论文《A morphable model for the synthesis of 3d faces》做了一项开创性的工作,提出了3dmm模型,而近20年来大部分的人脸重建论文也是基于以上提出的方法进行展开的。他们提出的方法是:将在严格控制环境下采集的200个人脸的较为精确的数据(每个人脸用53215个点进行表示,精度其实挺高了)进行PCA处理后,做成BFM数据集,之后基于这个数据集,我们就可以表示我们遇到的任意一张人脸了,具体该怎么表示呢?我们只需要两类3dmm系数即可: p s p_s ps(表示人脸基本形状)、 p e p_e pe(表示人脸表情) 与 p t p_t pt(表示人脸纹理),其中 p s p_s ps与 p e p_e pe称为形状参数(shape), p t p_t pt称为纹理参数(texture)
2.1 3dmm形状参数
p
s
p_s
ps与
p
e
p_e
pe分别可以看做
199
∗
1
199 * 1
199∗1与
29
∗
1
29 * 1
29∗1的列向量,因为都是表示形状(或者说是人脸各个顶点的三维坐标)所以一般都写在一块,表示成
p
s
,
e
=
[
p
s
,
p
e
]
p_{s,e}=[p_s,p_e]
ps,e=[ps,pe] ,这样的话,对于人脸形状,我们就可以用如下公式表示了:
其中BFM数据集经过处理可以得到
m
s
,
e
m_{s,e}
ms,e(表示平均脸,是一个形状为53215*3行,1列的矩阵)和
U
s
,
e
U_{s,e}
Us,e(形状为
53215
∗
3
53215*3
53215∗3行,199+29列的矩阵),他们相乘之后得到形状为
53215
∗
3
53215*3
53215∗3行,1列的矩阵,这样人脸53215个点的三维坐标就得到了。
这样的表示无疑是极为方便的,给三维人脸重建提供了大大的简化方向,对于给我的任意一张照片,我不需要再费尽心思去想如何生成点云等等复杂的东西,我只需要专心去生成
p
s
p_s
ps与
p
e
p_e
pe即可
2.2 3dmm纹理参数
一般来说,人脸的纹理可以使用UV纹理贴图进行表示,只要给我一张纹理贴图与映射关系,便可以轻松得到人脸纹理,用公式表示如下:
但是人脸纹理在3dmm里面却不是这样表示,与形状参数类似,使用如下式子表示:
与之类似的,
p
t
p_t
pt代表形状为[199,1]的矩阵,
m
t
m_t
mt与
U
t
U_t
Ut均可以通过对BFM数据集进行处理生成,最终依然是得到一个[53215*3,1]的矩阵,代表53215个点的rgb颜色
2.3 关于人脸拟合(fitting)
- 有了3dmm模型,那么与之相关的所有人脸三维重建工作都可以看做如下最优化问题:
其中 p = [ p s , e , p t , p c , p l ] p=[p_{s,e},p_t,p_c,p_l] p=[ps,e,pt,pc,pl], p c p_c pc代表相机参数,包括位置,朝向,向上向量, p l p_l pl代表光照参数,有了这些参数便可以通过渲染得到 W ( p ) W(p) W(p),通过与要拟合的图像 I 0 ( p ) I^0(p) I0(p)进行比较,便可以进一步计算误差了。 - 最近也是涌现出了许多计算方法,其中2017年CVPR的一篇《3d face morphable models in-the-wild》提出了如下简化的模型:
其中H代表手工特征(称之为handcrafted features,可以看做是68个关键点?), p r = [ p s , e , p c ] p_r=[p_{s,e},p_c] pr=[ps,e,pc], ∣ ∣ a ∣ ∣ A 2 = a T A a ||a||^2_A=a^TAa ∣∣a∣∣A2=aTAa,之后再使用高斯牛顿法便可以进一步求解了,当然这种方法最大的缺点就是只能重建形状,不能重建纹理
3. 本文核心方法
先看结构图:
接下来分三个部分介绍
3.1 GAN网络
我们先看前半部分,
p
s
p_s
ps与
p
e
p_e
pe与3dmm模型一样,而
p
t
p_t
pt我们可以理解为是GAN网络的生成器的一系列网络结构参数,与3dmm的参数有着本质区别,用式子可以表示为
也就是长度为512的噪声经过
p
t
p_t
pt变成一张rgb的纹理贴图,根据后文训练介绍来看应该是
512
∗
512
512*512
512∗512的分辨率,在如此高分辨率的情况下,为了保证生成图片的质量,本文参考了《Progressive growing of GANs for improved quality, stability, and variation》In ICLR, 2018 这篇论文,其实就是先从低分辨率开始生成,然后一点一点加分辨率,来保证最后生成的图片不要太离谱
补充:本文具体是如何使用GAN生成纹理图呢,是使用大量的高精度UV纹理图(获取应该比较困难吧)来训练一个GAN网络,使得我随机采样一个latent code,他都能给我生成一张像人的人脸纹理图,这样在后面的可微渲染中,调节的就只有latent code了,网络参数不再变化
3.2 渲染
有了纹理贴图,以及3dmm形状参数,就得到了人脸三维模型,之后再经过可以微分的渲染器,结合 p c p_c pc和 p l p_l pl 就能得到我们渲染的人脸2维图片了,这样我们就能通过与原输入图片进行比较,求得损失,通过反向传播得到各个梯度,然后经过若干次迭代来优化各个参数了,当然为了得到最终的目标函数,作者还是设计了很多损失,如下所示
3.3 损失函数
- 身份损失
试想我们的模型得到的三维人脸,不管在哪个角度与光照条件下拍照,最后得到的人的身份肯定是同一个人才对,那么如果我有了一个可以识别人身份的网络,那么不同的角度与光照渲染生成的人脸图片,经过该网络,最终结果的差别应该越小越好,借助这个思想,设计了如下损失函数
人脸识别器网络来自于《Additive angular margin loss for deep face recognition》这篇文章,最终得到的是长度为512的向量,而比较这两个向量的差异,一般来说就是余弦夹角(就是点乘除以各自模长),上面式子中 I R I^R IR代表渲染图片, I 0 I^0 I0代表输入的原始图片
而 I R I^R IR换个角度、表情、光照渲染,就是 I ^ R \hat{I}^R I^R了:
而将损失函数式子中的 I R I^R IR替换成 I ^ R \hat{I}^R I^R,就可以得到 L ^ i d \hat{L}_{id} L^id,之后也会用到 - 内容损失
当然,身份损失是必要的,但是我们不管怎样,得保证渲染图片与输入图片尽量一样啊,我们当然可以直接将他们相减求得损失函数,但是这里作者提供了个稍复杂的做法,将上面的身份识别网络中的每一层都进行相减,如下所示
对每个像素,求解的是欧几里得距离 - 像素损失
上面的身份损失,需要将图片降到 112 ∗ 112 112*112 112∗112才能进行,也就是说没有直接进行渲染图片与真实图片相减,这称之为像素损失,作者认为的是像素损失主要还原的是光照参数,之前的身份损失和内容损失主要还原的是纹理贴图,而像素损失也有助于恢复纹理贴图,因此就加入了像素损失
这里的损失函数时L1 loss,也就是对每个像素值求相差的绝对值之和得到损失 - 关键点损失
当然,我们渲染的图片与原始输入图片相比,最重要的首先应该是68个关键点得对齐,不然的话前面的这么多损失函数设计的再好也没用,用的也是比较优秀的网络,来自《Cascade multi-view hourglass model for robust 3d face alignment》IEEE 2018 ,损失函数如下:
其实就是各个关键点的距离之和。事实上作者在生成三维人脸的时候,首先采取的是如下策略
也就是先把人脸的形状与位置先给大致找对,之后再专心优化纹理与光照
- 最终,得到的是如下目标函数