极市导读 详解经典2D数字人算法SadTalker和Wav2Lip技术原理。 >>加入极市CV技术交流群,走在计算机视觉的最前沿 最近两年,数字人受到越来越多人的关注。数字人可分为3D和2D。3D的话比较出名的是虚幻引擎的meta human,背后的技术涉及到blendshape等等。而本文将介绍两个比较知名的2D数字人算法,分别是SadTalker和Wav2Lip。另外,最近泰勒斯威夫特说中文的视频很火,据说背后用到的算法之一是GeneFace++,不过限于篇幅和它的前提知识比较多,本文暂时不讲。 2D数字人根据输入类型的不同,还可以进一步分为视频+音频,wav2lip和geneface属于这一类,这一类算法只生成新的口型,另一类的输入是图片+音频,sadtalker属于这一类,这一类不仅生成新的口型,还生成头部运动,复杂度较高。 Wav2Lip技术原理论文:《A Lip Sync Expert Is All You Need for Speech to Lip Generation In the Wild》 http://cdn./cdn/cvit./images/Projects/Speech-to-Lip/paper.pdf 官方代码:https://github.com/Rudrabha/Wav2Lip wav2lip采用的是GAN的训练范式,但它一共有1个生成器(下图左边大框,Generator)和2个判别器(下图右边两个小框,分别是pre-trained lip-sync expert和visual quality discriminator)。 为什么要两个判别器呢?因为作者认为之前的唇音同步效果不佳,是因为损失函数设计上有问题,比如对全脸应用L1的重建损失,因为嘴唇区域只占图片4%的面积,导致模型训练前期是在学习重建姿态、身份、背景等信息,后半阶段才会开始对嘴唇变形,因此作者认为需要一个额外的判别器来判断唇音同步。而现有的像LipGAN里的唇音同步判别器太弱,在LRS2测试集上只有56%的准确率,而本文使用的lip-sync expert能达到91%。作者认为LipGAN效果不佳的原因是,第一,只使用了单帧画面,没有使用时序上的上下文信息,第二,判别器聚焦在了生成图像上的伪影(artifacts)而不是唇音同步。基于这两个发现,作者提出了一个预训练好的唇音同步判别器,正如名字所强调的,训练好后就不再微调,否则会像LipGAN那样,模型权重被污染。这个唇音同步判别器基于SyncNet改造而来,SyncNet输入帧画面和形状的音频频谱图。SyncNet内有图像编码器和音频编码器(两者主要都是堆叠了一些Conv2d),分别对图像音频编码后得到face_embedding和audio_embedding,训练时,会随机选取跟一段音频匹配的画面和不匹配的画面,来作为正样本和负样本。损失函数的计算方法就是对face_embedding和audio_embedding计算余弦相似度,得到[0,1]之间的数值,然后根据正样本或负样本做BCE。 讲完唇音同步判别器,剩下的一个生成器和一个判别器就跟常规的GAN差不多了。 生成器由三部分组成:(i) Identity Encoder, (ii) Speech Encoder, (iii) Face Decoder,如上图中的蓝色、绿色、红色所示。它们内部主要都是由2D卷积组成,人脸解码器的上采样使用的是转置卷积。身份编码器的输入比较特殊,包括随机选取的参考帧(上图的粉红框)和被遮掉下半部分的、要重新合成嘴型的视频帧(上图的橙色框),每张图片3个通道,所以它的输入是6通道,而音频编码器只有一张单通道的梅尔频谱图。训练时,等生成器生成连续的帧后,再一起送给唇音判别器计算损失函数。还有个细节是,音频和图像这两种模态在生成器里怎么融合的。简单来说,首先音频编码器把音频从输入形状 SadTalker技术原理论文:《SadTalker: Learning Realistic 3D Motion Coefficients for Stylized Audio-Driven Single Image Talking Face Animation》 https:///pdf/2211.12194.pdf 官方代码:https://github.com/OpenTalker/SadTalker 我用modelscope封装的sadtalker:https://github.com/wwdok/sadtalker_modelscope 简单来说,SadTalker将音频编码成了中间表示:表情系数和头部姿态系数,n代表合成视频中的帧数,然后再将这些中间表示经由渲染器渲染出每一帧,整体流程如下图所示: 展开细讲,SadTalker利用3DMM技术对图片中的人脸进行3D重建,得到表情系数和头部姿态系数,作为后续合成视频每一帧的参考系数。 后续每一帧的表情系数和头部姿态系数分别是由ExpNet、PoseVAE这两个模型输出。为什么不把表情系数和头部姿态系数用一个模型输出就好?因为作者发现,表情运动是局部的,头部运动是全局的,且表情跟声音的关系比较强,头部姿态跟声音的关系比较弱,将这两个系数解耦开可以减少人脸扭曲。 ExpNet的测试时和训练时的工作流程如下图所示: 测试时(即推理时),Audio Encoder(代码位于 经过ExpNet的推理,输出形状(BS, n, 64)的张量,也就是说视频每一帧都有一个64维的表情系数。训练时,把音频和图片输入给wav2lip得到对应口型的视频帧,再把视频的每一帧输入给3D人脸重建模型,模型会输出257个系数,拿取其中的表情系数跟Mapping输出的系数做蒸馏学习(用wav2lip生成的结果做标签来训练,这一点似乎注定了sadtalker在唇形同步上难以超越wav2lip)。其他系数会用来构建lip-reading loss 、facial landmark loss ,这部分内容详见论文附录B.3。 这里讲一下上面提到的3DMM技术和3D人脸重建。3DMM是3D人脸重建中的一种技术或思想。3DMM(3D Morphable Models)的思想是用以下等式建模一个3D人脸: ,其中, 是平均人脸,是形状系数,是形状基, 是表情系数, 是表情基,平均人脸、形状基、表情基都是3维的。我们只要计算出形状系数和表情系数,我们就能重建一个三维人脸。一种计算这些系数的方法就是是用神经网络模型。 SadTalker里的三维人脸重建模型(代码中的 PoseVAE的训练时和测试时的工作流程如下图所示: PoseVAE本质上是一个Conditional VAE,而这个condition就是头部姿态风格。是一个形状(46,64)的embedding,也就是说模型能自主学习到46种头部姿态。图中只绘制了Conditional VAE,但从代码来看,还有个AudioEncoder,跟ExpNet里的AudioEncoder模型结构一模一样,也是负责把每一时间步、形状为的音频梅尔谱图编码成形状的向量,但两者不共享权重。 从图中还可以看出,PoseVAE的损失有三部分、、组成。另外,由符号可知,PoseVAE实际生成的是相对于参考头部姿态系数的偏移量。 经过PoseVAE的推理,输出形状(BS, n, 6)的张量,也就是说视频每一帧都有一个6维的头部姿态系数。 目前我们已经得到了每一帧的表情系数和头部姿态系数,接下来我们要使用3D-aware Face Render将这些系数转换为一帧帧图片,那怎么转换呢?作者从 face-vid2vid中获得了灵感,face vid2vid能实现输入一张图片和一段视频,输出受视频中的人脸驱动的图片中的人脸的视频。不过,在face-vid2vid中,它拥有一个驱动的视频作为驱动信号,(实际做法是从视频中提取人脸3D关键点作为驱动信号),而我们这里只能通过 3DMM 运动系数(表情系数和头部姿势系数)来驱动。如下图所示,作者使用 mappingNet 来将 3DMM 运动系数映射成3D关键点(代码中实际上mappingNet只生成、 、 、、这些系数,然后再用这些系数对canonical keypoint做变换得到15个3D关键点)。mappingNet主要是通过几个一维卷积层构建的。与 PIRenderer一样,为了人脸动作更平滑,作者使用整个滑动时间窗口中(体现在代码中就是 有了源图片、源3D关键点、驱动3D关键点,将它们送给Image Generator,就能合成每一帧画面了。Face vid2vid和3D-aware Face Render的工作流程如下图所示: 至于mappingNet的训练,包含两个步骤:首先,按照原论文中的方法训练 face-vid2vid。第二步,冻结appearance encoder, canonical keypoints estimator 和 image generator的所有参数,重构pipeline后在真实视频的 3DMM 系数上训练mappingNet。最终生成视频按照face-vid2vid的原始实现方式进行。 这一部分论文中讲得比较少,因为大部分内容都是借鉴自face-vid2vid的论文《One-shot free-view neural talking-head synthesis for video conferencing》,项目主页:https://nvlabs./face-vid2vid/ 。 Image Generator代码中对应的是 如果你想体验SadTalker,除了跑官方代码仓库外,也可以试试我用modelscope封装的sadtalker库( https://github.com/wwdok/sadtalker_modelscope ),它的优点是把模型权重也打包进去了,国内下载速度很快,几行代码就可以调用sadtalker的能力。 |
|
来自: swordinhand > 《Research》