如下图所示,人脸视觉配音(Face visually dubbing)旨在根据输入的驱动音频同步源视频中的嘴型,同时保持身份和头部姿势与源视频帧一致。然而在少样本条件下,实现高分辨率视频下的高质量人脸视觉配音仍然是一项挑战。一个主要原因是,在少数样本的条件下,嘴部纹理细节与驱动音频的相关性很小,因此直接生成高频纹理细节是比较困难的。为了解决这个问题,形变修复网路DINet通过对参考人脸图像进行空间形变来保留更多的嘴部纹理细节。具体地,首先对参考人脸图像的特征图做空间形变,形变后的特征包含与语音同步和头部姿态对齐的口型特征;然后使用空间形变后的特征修补嘴部区域,空间形变是将像素移动,而不是重新生成,因此能够保存足够多的纹理信息。
DINet网络架构由两部分组成,形变网络 P D P^{D} PD和修补网路 P I P^{I} PI。形变部分对五张参考图像的特征进行空间形变,创建每帧嘴部形状的变形特征图,以便于对齐输入驱动音频和输入源图像的头部姿态。修复部分则侧重于利用形变结果修复源面部的嘴部区域。
自适应仿射变换算子(Adaptive Affine Transformation, AdaAT)解决人脸驱动前后空间不对齐的问题。AdaAT使用仿射变换来模拟和约束空间形变,它直接在特征通道空间中进行仿射变换。
给定一个源图像 I s ∈ R 3 × H × W I_{s} \in R^{3 \times H \times W} Is∈R3×H×W,一个驱动音频 A d ∈ R T × 29 A_{d} \in R^{T \times 29} Ad∈RT×29和五个参考图像 I r e f ∈ R 15 × H × W I_{ref} \in R^{15 \times H \times W} Iref∈R15×H×W,形变网络 P D P^{D} PD的任务就是输出与 A d A_{d} Ad同步的嘴型且与 I s I_{s} Is头部姿态对齐的形变特征 F d ∈ R 256 × H 4 × W 4 F_{d} \in R^{256 \times \frac{H}{4} \times \frac{W}{4}} Fd∈R256×4H×4W。
注: 第四步的全连接网络被用于计算rotation R = { θ c } c = 1 256 R=\{\theta^{c}\}_{c=1}^{256} R={θc}c=1256、translation T x = { t x c } c = 1 256 / T y = { t y c } c = 1 256 T_{x} = \{t_{x}^{c}\}_{c=1}^{256} / T_{y} = \{t_{y}^{c}\}_{c=1}^{256} Tx={txc}c=1256/Ty={tyc}c=1256和Scale S = { s c } c = 1 256 S=\{s^{c}\}_{c=1}^{256} S={sc}c=1256的系数。然后这些仿射系数与 F r e f F_{ref} Fref做仿射变换。
( x c , y c ) \left(x_{c}, y_{c}\right) (xc,yc)和 ( x ^ c , y ^ c ) \left(\hat{x}_{c}, \hat{y}_{c}\right) (x^c,y^c)分别为仿射变换前后的像素坐标, c ∈ [ 1 , 256 ] c \in [1,256] c∈[1,256]为 F r e f F_{ref} Fref中 c t h c_{th} cth的通道。
这也是为什么能选择AdaAT算子的原因,AdaAT算子在不同的特征通道中计算不同的仿射系数。
修补网路 P I P^{I} PI相比于形变网络 P D P^{D} PD而言就简单很多,只包含一个由卷积层组成的特征解码器网络。将源图像特征 F s F_{s} Fs和形变特征 F d F_{d} Fd按通道合并后,送入到特征编码器后输出配音图像 I o ∈ R 3 × H × W I_{o} \in R^{3 \times H \times W} Io∈R3×H×W。
在训练阶段,DINet的损失函数由三张不同的损失函数加权组成。
感知损失(perception loss)是一种基于深度学习的图像风格迁移方法中常用的损失函数。感知损失是通过预训练的神经网络(常见是VGG网络)来计算两张图片之间的差异。感知损失的目标是最小化输入图像和目标图像在特征空间的距离。
在这篇论文中,首先对真实图像 I r I_{r} Ir和配音图像 I o I_{o} Io进行降采样分别得到 I ^ r ∈ R 3 × H 2 × W 2 \hat{I}_{r} \in R^{3 \times \frac{H}{2} \times \frac{W}{2}} I^r∈R3×2H×2W和 I ^ o ∈ R 3 × H 2 × W 2 \hat{I}_{o} \in R^{3 \times \frac{H}{2} \times \frac{W}{2}} I^o∈R3×2H×2W,然后一起计算 { I o , I r } \{I_{o}, I_{r}\} {Io,Ir}和 { I ^ o , I ^ r } \{\hat{I}_{o}, \hat{I}_{r}\} {I^o,I^r}的感知损失值。损失感知公式如下所示:
预训练模型选用VGG-19网路, V ( ⋅ ) V\left( \cdot \right) V(⋅)为 i t h i_{th} ith层, W i H i C i W_{i}H_{i}C_{i} WiHiCi为 i t h i_{th} ith层的特征尺寸。
GAN loss使用的是least square GAN,公式为 L G A N = L D + L G L_{GAN} = L_{D} + L_{G} LGAN=LD+LG, G G G表示的是DINet网络, D D D为判别器。
论文中缺少判别器的资料。通过代码理解GAN loss。
# GAN 损失
class GANLoss(nn.Module):
'''
GAN loss
'''
def __init__(self, use_lsgan=True, target_real_label=1.0, target_fake_label=0.0):
super(GANLoss, self).__init__()
self.register_buffer('real_label', torch.tensor(target_real_label))
self.register_buffer('fake_label', torch.tensor(target_fake_label))
if use_lsgan:
self.loss = nn.MSELoss()
else:
self.loss = nn.BCELoss()
def get_target_tensor(self, input, target_is_real):
if target_is_real:
target_tensor = self.real_label
else:
target_tensor = self.fake_label
return target_tensor.expand_as(input)
def forward(self, input, target_is_real):
target_tensor = self.get_target_tensor(input, target_is_real)
return self.loss(input, target_tensor)
# train
net_dI = Discriminator(*) # 判别器D
net_g = DINet(*) # DINet网络
criterionGAN = GANLoss().cuda()
fake_out = net_g(*)
# (1) Update D network
optimizer_dI.zero_grad()
# compute fake loss
_,pred_fake_dI = net_dI(fake_out)
loss_dI_fake = criterionGAN(pred_fake_dI, False)
# compute real loss
_,pred_real_dI = net_dI(source_image_data)
loss_dI_real = criterionGAN(pred_real_dI, True)
# Combined DI loss
loss_dI = (loss_dI_fake + loss_dI_real) * 0.5
loss_dI.backward(retain_graph=True)
optimizer_dI.step()
lip-sync损失是为了提高配音视频中的嘴唇的同步性。损失公式定义如下。