1、前言
闲来无事,今天我们讲一篇有关换脸的论文——SimSwap。该模型与传统的换脸算法不同。它可以自由的交换不同身份的面部信息。
原论文:SimSwap: An Efficient Framework For High Fidelity Face Swapping (arxiv.org)
参考代码:SimSwapHD: Reimplement of SimSwap training code (github.com)(非官方)
Demo:
2、引入
在讲解之前,先适应几个概念
①:Source Image:源人脸(需要把该图像的人脸替换到目标图像)
②:Target Image:目标人脸(该图像的人脸信息要被替换成Source Image的人脸)
2.1、实现方法简介
想要实现在各种身份(不同任务)之间实现自由换脸。最好的方法,就是首先可以提取出了源人脸特征(论文中称为身份)。然后,把提取出来的特征施加到目标人脸上面,替换掉原来的人脸。当然了,这一个过程,还必须保持目标人脸的属性(如表情、姿态、光照等等)不变。
2.2、源人脸身份提取(ArcFace)
要把源人脸的身份信息提取出来,而不会提取出其他属性(表情、姿态等等),是一项非常重要的工作。然而,这不是这篇文章的重点,因为这项工作在其他论文已经取得了不错的成效。
什么样的工作(或模型)可以单单提取出身份信息?目前已知的技术有哪一个具备这种能力?当燃是人脸识别
人脸识别最重要的一步。就是录入不同身份人的脸部信息。然后,经过模型提取出面部特征。由于每个人的面部特征都不尽相同。然后模型就可以依据不同的特征,进行人脸识别,区分不同的人。
一个比较出名的人脸识别模型——ArcFace,论文:ArcFace: Additive Angular Margin Loss for Deep Face Recognition(CVPR 2019)
它利用一个特殊的损失函数,使得基于DCNN(深度卷积神经网络)的人脸识别系统,能够获得更好的分类效果(人脸识别效果)
而SimSwap,就是使用一个训练好的ArcFace,进行源人脸身份提取。
3、SimSwap
3.1、源人脸身份信息施加到目标人脸——AdaIN
在StyleGAN中,我们把一个人的各种信息W(包括人脸),以AdaIN的方式,注入到生成网络里面。然后生成网络就可以生成一张具有W风格信息的图像。现在,我们也同样的,可以把源人脸身份信息,注入到一个网络里面。然后得到的图像也可以具备源人脸的身份信息。
那么,这个网络是什么呢?这个网络就是一个编码器–解码器的结构
比如图中,我们把Target image( I T I_T IT)送给一个由卷积层构成的编码器(下采样)。在编码结束后,会把编码结果(记为 F e a i n Fea_{in} Feain)送入到IIM层中。我们从Sorce image( I S I_S IS)使用ArcFace提取源人脸身份信息( V S V_S VS)。把该信息输入给IIM层。
所以IIM层接收两个输入,一个是
I
T
I_T
IT的编码结果,另一个是
V
S
V_S
VS。一个IIM层包含9个ID-Block。一个ID-Block中,先对
F
e
a
i
n
Fea_{in}
Feain进行卷积,然后就是用AdaIN层,其实与stylegan是一样的
A
d
a
I
N
(
F
e
a
,
V
S
)
=
σ
S
F
e
a
−
μ
(
F
e
a
)
σ
(
F
e
a
)
+
μ
S
AdaIN(Fea,V_S)=\sigma_S\frac{Fea-\mu(Fea)}{\sigma(Fea)}+\mu_S
AdaIN(Fea,VS)=σSσ(Fea)Fea−μ(Fea)+μS
其中,
F
e
a
−
μ
(
F
e
a
)
σ
(
F
e
a
)
\frac{Fea-\mu(Fea)}{\sigma(Fea)}
σ(Fea)Fea−μ(Fea)是对
F
e
a
Fea
Fea进行实例归一化。
σ
S
,
μ
S
\sigma_S,\mu_S
σS,μS是由
V
S
V_S
VS经过一个线性层后拆分成两部分而得来。
经过完AdaIN后,把得到的结果,使用Relu进行激活。然后进行Conv。又重复AdaIN层。最后进行残差连接(详见图中)
经过完9个ID-Block之后,把得到的结果送给一个由上采样和卷积层构成的解码器。然后解码器恢复一张图像(
I
R
I_R
IR)。我们希望,这种恢复的图像可以具备与
I
S
I_S
IS一样的人脸身份信息。所以,我们把恢复的图像
I
R
I_R
IR也送给ArcFace,进行人脸身份提取,得到
I
R
I_R
IR的身份信息——
V
R
V_R
VR。最后,构建损失函数
L
I
d
=
1
−
V
R
⋅
V
S
∥
V
R
∥
2
∥
V
S
∥
2
(1)
L_{Id}=1-\frac{V_R\cdot V_S}{\Vert V_R \Vert_2\Vert V_S \Vert_2}\tag{1}
LId=1−∥VR∥2∥VS∥2VR⋅VS(1)
其中
cos
θ
=
V
R
⋅
V
S
∥
V
R
∥
2
∥
V
S
∥
2
\cos \theta = \frac{V_R\cdot V_S}{\Vert V_R \Vert_2\Vert V_S \Vert_2}
cosθ=∥VR∥2∥VS∥2VR⋅VS,
θ
\theta
θ是两个向量的夹角。
余弦相似度,两者越相似,那么说明夹角越接近 0 ∘ 0^{\circ} 0∘,而我们知道 cos 0 ∘ = 1 \cos 0^{\circ}=1 cos0∘=1。
由此可得当两个身份向量越相近,那么就越接近1。当两者向量完全相似,无损失 L I d = 0 L_{Id}=0 LId=0
3.2、图像重构
3.2.1、对抗损失
对于恢复的图像 I R I_R IR,如果只用 L I d L_{Id} LId损失。那么恢复的图像只需要具备 I S I_S IS的身份信息即可。不需要保持目标人物( I T I_T IT)的属性(标签、标签,灯光)等等。这显然不是我们想要的。那么,该如何保持 I T I_T IT的属性不变呢?
在论文中,采用对抗训练的思想,让输出图像 I R I_R IR可以保持原有的属性。简单来说,我们把真实图像 I T I_T IT与 I R I_R IR一起输入给一个判别网络,让判别网络判别真伪
在这个判别网络中,使用的是PatchGAN的判别器(判别器输出是一个矩阵,然后在该矩阵上每个元素上面判断真伪,其实就是相当于将一张图分成几个小块。依次对这些小块送给判别器进行判断。在代码中使用的是卷积层来划分不同的块。详见论文Image-to-Image Translation with Conditional Adversarial Networks (arxiv.org))
对于对抗损失,论文采用铰链损失,与之前讲过的FastGAN里一致
L
A
d
v
D
=
−
E
x
∼
I
T
[
min
(
0
,
−
1
+
D
(
x
)
)
]
−
E
x
∼
I
R
[
min
(
0
,
−
1
−
D
(
x
)
)
]
L
A
d
v
G
=
−
E
x
∼
I
R
[
D
(
x
)
]
(2)
\begin{aligned}L_{Adv}^D=&-\mathbb{E}_{x\sim I_T}\left[\min(0,-1+D(x))\right]-\mathbb{E}_{x\sim I_R}\left[\min(0,-1-D(x))\right]\\L_{Adv}^G=&-\mathbb{E}_{x\sim I_R}\left[D(x)\right]\end{aligned}\tag{2}
LAdvD=LAdvG=−Ex∼IT[min(0,−1+D(x))]−Ex∼IR[min(0,−1−D(x))]−Ex∼IR[D(x)](2)
3.2.2、弱特征损失
判别网络只能够判别图像的真伪,很难确保 I T I_T IT, I R I_R IR的属性一致性。因此,作者又使用了弱特征匹配损失,这个损失起源于论文High-Resolution Image Synthesis and Semantic Manipulation with Conditional GANs (arxiv.org)
简单来说,我们看上面那张图的判别网络。整个过程,其实就是判别网络首先使用卷积层,提取特征。最后,根据特征进行判断图像真伪。为了保证
I
R
I_R
IR、
I
T
I_T
IT的属性一致,当我们把真假图像输入给判别网络,我们希望真假图像中一些层提取出来的特征,可以尽可能的相似。比如图中,我们让真假图像中倒数第三、第二个层的输出值。一一对应尽可能地相似。如何让他们相似?使用L1范数
L
o
F
M
(
D
)
=
∑
i
=
1
M
1
N
i
∥
D
(
i
)
(
I
R
)
−
D
(
i
)
(
I
T
)
∥
1
L_{oFM}(D)=\sum\limits_{i=1}^M\frac{1}{N_i}\Vert D^{(i)}(I_R)-D^{(i)}(I_T) \Vert_1\
LoFM(D)=i=1∑MNi1∥D(i)(IR)−D(i)(IT)∥1
其中,
D
(
i
)
D^{(i)}
D(i)表示判别网络在第
i
i
i层的输出特征值;
N i N_i Ni表示第 i i i层的元素数量; M M M是总层数
值得注意的是,作者提到,浅层输出的特征值,主要是包含纹理信息。把过多的纹理信息作Eq.(2)损失,会导致 I R I_R IR和 I T I_T IT的纹理特征太过相似。然而,这两张图像是经过换脸的,他们的纹理特征定然是不一样的
因此,作者忽略了浅层的特征,不去计算他们的弱特征损失,只计算深层的。论文提到,深层的特征主要是属性语义信息。因此我们只使用最后几层来计算弱特征损失
论文还提到,他们采用多尺度判别器。具体来说:首先初始化一个判别器 D 1 D_1 D1,它用来判别 I R , I T I_R,I_T IR,IT。然后,又初始化一个判别器 D 2 D_2 D2,将 I R , I T I_R,I_T IR,IT下采样(比如平均池化)得到 I R 1 , I T 1 I_R^1,I_T^1 IR1,IT1,送给判别器 D 2 D_2 D2判别
于是损失就取两个判别器的求和
L
w
F
M
_
s
u
m
=
∑
i
=
1
2
L
w
F
M
(
D
i
)
(3)
L_{wFM_\_sum}=\sum\limits_{i=1}^2L_{wFM}(D_i)\tag{3}
LwFM_sum=i=1∑2LwFM(Di)(3)
3.3.3、解码重建损失
论文提到,如果源人脸和目标人脸来自同一身份(是同一个人),那么我们希望重建的图像应该与目标人脸尽可能的相似(因为如果来自同一个人,那么换了跟没有没啥区别),即最小化如下损失函数
L
R
e
c
o
n
=
∥
I
R
−
I
T
∥
1
(4)
L_{Recon}=\Vert I_R-I_T \Vert_1\tag{4}
LRecon=∥IR−IT∥1(4)
如果他们的身份不一致,那么直接设置为0,也就是不存在这个解码重建损失
3.3.4、梯度惩罚
出自WGAN-GPImproved Training of Wasserstein GANs (arxiv.org)。为了防止梯度爆炸,SimSwap也使用梯度惩罚项。
L
G
P
=
(
∥
∇
x
^
D
(
x
^
)
∥
2
−
1
)
2
(5)
L_{GP}=\left(\Vert\nabla_{\hat x}D(\hat x) \Vert_2-1\right)^2\tag{5}
LGP=(∥∇x^D(x^)∥2−1)2(5)
其中
∇
x
^
\nabla_{\hat x}
∇x^表示对
x
^
\hat x
x^求梯度。
x
^
=
α
∗
r
e
a
l
_
i
m
g
+
(
1
−
α
)
f
a
k
e
_
i
m
g
\hat x=\alpha* real\_img+(1-\alpha)fake\_img
x^=α∗real_img+(1−α)fake_img。real_img表示真实图像,fake_img表示伪造的图像。而
α
\alpha
α是从0-1均匀分布中采样出来出来的值。
总的来说,就是构造一个介于真实图像和伪造图像之间的图像。让他给判别网络判断。然后求梯度,我们希望它的梯度可以在1附近,从而避免梯度爆炸。
4、总损失
总损失就等于(1)+(2)+(3)+(4)+(5),加上一些权重稀疏
L
S
u
m
=
λ
I
d
L
I
d
+
λ
R
e
c
o
n
L
R
e
c
o
n
+
L
A
d
v
+
λ
G
P
L
G
P
+
λ
w
F
M
L
w
F
M
_
s
u
m
L_{Sum}=\lambda_{Id}L_{Id}+\lambda_{Recon}L_{Recon}+L_{Adv}+\lambda_{GP}L_{GP}+\lambda_{wFM}L_{wFM\_sum}
LSum=λIdLId+λReconLRecon+LAdv+λGPLGP+λwFMLwFM_sum
其中
λ
I
d
=
10
,
λ
R
e
c
o
n
=
10
,
λ
G
P
=
1
0
−
5
,
λ
w
F
M
=
10
\lambda_{Id}=10,\lambda_{Recon}=10,\lambda_{GP}=10^{-5},\lambda_{wFM}=10
λId=10,λRecon=10,λGP=10−5,λwFM=10
5、结束
好了,本篇文章到此为止,如有问题,还望指出。阿里嘎多!