您的位置:首页 > 房产 > 建筑 > 中国产品网免费网站_苏州现在可以正常进入吗_搜索引擎优化的简称_seo文章是什么

中国产品网免费网站_苏州现在可以正常进入吗_搜索引擎优化的简称_seo文章是什么

2024/12/22 17:26:24 来源:https://blog.csdn.net/m0_58806853/article/details/144487898  浏览:    关键词:中国产品网免费网站_苏州现在可以正常进入吗_搜索引擎优化的简称_seo文章是什么
中国产品网免费网站_苏州现在可以正常进入吗_搜索引擎优化的简称_seo文章是什么

目录

    • 摘要
    • Abstract
    • Wav2Lip
      • 1.1 总体结构
      • 1.2 Wave2Lip训练
      • 1.3 代码分析
    • 总结

摘要

本周学习的主要内容是Wav2Lip模型。Wav2Lip是一种基于生成对抗网络(GAN)的模型,用于将音频与静态图片中的人脸进行对齐并合成动态视频,是制作虚拟主播的重要技术之一。Wav2Lip模型作为将音频波形转换为面部动画的深度学习技术,在原理、训练和应用方面都展现出强大的实力。通过结合生成对抗网络和适当的损失函数,Wav2Lip模型能够从音频信号中提取关键信息并将其转换为面部动画。本周,作者将从总体结构、训练以及代码解析三部分对Wav2Lip进行学习。

Abstract

The main content of this week’s study is the Wav2Lip model. Wav2Lip is a model based on Generative Adversarial Network (GAN), used to align audio with faces in static images and synthesize dynamic videos. It is one of the important techniques for creating virtual anchors. The Wav2Lip model, as a deep learning technique for converting audio waveforms into facial animations, has demonstrated strong capabilities in terms of principles, training, and applications. By combining generative adversarial networks with appropriate loss functions, the Wav2Lip model is able to extract key information from audio signals and convert it into facial animations. This week, the author will study Wav2Lip from three parts: overall structure, training, and code analysis.

Wav2Lip

Wav2Lip是一种基于生成对抗网络(GAN)的模型,用于将音频与静态图片中的人脸进行对齐并合成动态视频。它可以接受任何一个人的音频,然后翻译成一个人口型,使得同样的口型可以根据输入的音频内容生成不同的视频。相比传统的基于手工特征提取和规则的方法, Wav2Lip可以自动学习音频和图像之间的关系,并生成更加真实且准确的结果。因此,它已经被广泛应用于影视制作、虚拟主播、应急通信等领域,具有广阔的应用前景。本次的学习基于名为A Lip Sync Expert Is All You Need for Speech to Lip Generation In The Wild的论文。
在这里插入图片描述

在文章中,他们提出一个叫做Wav2Lip的AI模型,只需要一段人物视频和一段目标语音,就能够让音频和视频合二为一,人物嘴型与音频完全匹配。对口型的技术,此前其实已经有很多,甚至在基于深度学习的技术出现之前,就有一些技术使角色的嘴唇形状与实际的语音信号相匹配。但这Wav2Lip 在目前的众多方法中,显示出了绝对优势。
现有的其它方法,主要是基于静态图像,来输出与目标语音匹配的唇形同步视频,但对于动态的、在讲话的人物,唇形同步往往效果不佳。而 Wav2Lip 则可以直接将动态的视频,进行唇形转换,输出与目标语音相匹配的视频结果。

1.1 总体结构

模型分为三部分:
(1)生成器:负责输入原始图像和音频,输出音频驱动的图像,使用重构loss;
(2)预训练好的嘴唇同步专家判别器:输入音频驱动的图像和音频,输出二者的同步loss,用于驱动嘴型同步;
(3)视觉质量判别器:输入音频驱动的图像以及GroudTruth,输出0和1判断哪张图像是真的,哪张图像是生成的,用于驱动获取高质量的音频驱动图像,使用判别器loss。
在这里插入图片描述
在生成器中又分为三部分,第一部分是图像编码器,它的输入由两部分构成,一部分是下半部分被遮掩的5帧原始图像(来自于GroudTruth,模型在此基础上生成),一部分是用于嘴唇姿态参考的5帧图像,将两组图像拼接在一起输入到图像编码器,然后输出图像特征。第二部分是音频编码器,它的输入是对应的下半部分被遮掩的5帧原始图像的音频,不过从代码中可以看到,音频编码器的输入是5组5帧的音频,也就是前后25帧,然后输出音频特征。第三部分是解码器,输入是图像特征和音频特征,输出音频驱动的5帧图像,与GroudTtuth做重构loss。
在这里插入图片描述
音频编码器用于编码输入的语音片段,图像编码器则通过反卷积进行上采样,用于重建人脸图像,它的输入是编码后的音频特征和身份特征的拼接。
生成器通过最小化生成帧与真实帧之间的L1重构损失来提高生成的帧的质量,重建目标函数为:

在这里插入图片描述

wav2lip生成器独立地生成每一帧,然后将连续生成的帧序列输入给预训练的专家音频和口型同步判别器。

具体来说,为了在训练过程中与专家判别器的配合,生成器需要生成 Tv=5 个连续帧,但只使用生成的人脸的下半部分进行判别,生成器通过最小化来自专家判别器的同步损失来提高生成的帧的口型同步质量,同步损失函数为余弦相似度二元交叉熵损失:
在这里插入图片描述
在生成器的训练过程中,专家判别器的权重保持不变,因为专家判别器是从真实视频中的口型数据训练的,无需改变。通过这种生成器的结构和专家判别器的共同作用,可以生成任意人脸对象,并且口型与语音的同步性较好。但由于LRS2清晰度偏低,生成图像脸部较模糊,而且牙齿部分还原度稍差,可以选择清晰度更高的数据集,或者利用超分模型提升脸部的清晰度。此外,当参考人脸图片侧脸时,脸部可能会不协调。

使用专家口型同步判别器可以使生成器生成准确的口型形状,但有时候会导致生成区域出现模糊或者伪影。为了提高生成图像质量,wav2lip在生成器中使用了一个额外的的视觉质量判别器。wav2lip有两个判别器,口型同步判别器和质量判别器,一个用于提高口型同步准确性,另一个用于提高生成图像视觉质量。口型同步判别器在GAN训练期间保持冻结,视觉质量判别器只对生成的人脸的质量进行监督,不负责口型同步。
视觉质量判别器 D 由多个卷积块组成,训练目标是最大化目标函数 Ldisc
在这里插入图片描述
其中, 对应于生成器 G 生成的图像, 对应于真实图像。

1.2 Wave2Lip训练

(1)训练数据
训练中用到了LRS2 数据集,该数据集由英国广播公司电视台的数千句口语组成。每句话的长度不超过100个字符。训练、验证和测试集根据广播日期进行划分。
在这里插入图片描述
预训练集中的话语对应于部分句子和多个句子,而训练集仅由单个完整句子或短语组成。预训练和训练之间有一些重叠。数据集统计数据如下表所示。
在这里插入图片描述
(2)训练目标
wav2lip 模型的训练由生成器和判别器共同组成。GAN 负责学习音频-图像之间的对应关系,生成同步的嘴唇动作。判别器负责评估图像-音频的同步性。具体的,音频会被处理为音频 chunk 并处理转换为梅尔频谱矩阵,该矩阵常用于信号处理中的音频频谱特征;视频则是会逐帧抽取,转化为 [Channel、width、height] 的多通道矩阵。通过训练频谱矩阵与图像多通道矩阵的对应关系,学习chunk 与视频帧中口型的对应关系,不断地反馈训练以优化视频与音频的同步效果。
(3)训练过程
wave2lip的训练大致遵循下述流程,下述流程扩展为整个视频图像帧,即可实现视频与音频的嘴型对应:
1)解析视频文件
这里一般最常用的格式即为 mp4,通过 cv2 库的 VideoCapture 解析视频文件,并通过 video_stream 流式读取视频的每一帧,更简单的,你的视频可以是一张人物的 Face 图,这样会将图像复制扩展为与音频匹配的帧数。
2)音频文件解析
使用 audio 库处理音频文件,为了统一,这里会使用 ffmepg 将音频文件统一转换为 wav 格式。随后通过 melspectrogram 方法获取 wav 音频的梅尔频谱矩阵并将矩阵转换为多个 chunk。
3)人脸识别模块
针对视频帧识别人脸位置对应的 coord 坐标,因此 Wave2lip 实现中还需要一个 face-detect 的模型,用于对每一帧图像中人脸进行定位。
4)GAN 生成
基于上面的人脸的图像通道数字矩阵与音频的 mel 频谱矩阵构造模型的输入,通过调用 GAN 模型生成对应音频的嘴型图像。
5) 图像拼接与重建
将预测得到的 pred 和 coord 坐标结合,替换原图中的人脸部分,实现人脸与嘴型的替换。

论文中给出的数据:数据集LRS2,训练大约29小时,batchsize:64, 时间窗口Tv:5,优化器:Adam,初始化学习率:1e−3在LRS2test上,准确率91%
在这里插入图片描述

1.3 代码分析

Wave2Lip的项目代码是开源的,代码地址为:https://github.com/Rudrabha/Wav2Lip。
接下来我将对其中的重要部分进行说明
(1)数据载入部分
该段代码用于构建一个数据集,以学习如何同步视频帧和相应的音频。可以看到图像输入x=5帧,但是音频输入有mel=5帧和indiv_mels=25帧。x和indiv_mels输入到生成器,得到x’=5帧,x’和mel输入到嘴唇同步专家判别器。


syncnet_T = 5
syncnet_mel_step_size = 16class Dataset(object):def __init__(self, split):self.all_videos = get_image_list(args.data_root, split)def get_frame_id(self, frame):return int(basename(frame).split('.')[0])def get_window(self, start_frame):start_id = self.get_frame_id(start_frame)vidname = dirname(start_frame)window_fnames = []for frame_id in range(start_id, start_id + syncnet_T):frame = join(vidname, '{}.jpg'.format(frame_id))if not isfile(frame):return Nonewindow_fnames.append(frame)return window_fnamesdef read_window(self, window_fnames):if window_fnames is None: return Nonewindow = []for fname in window_fnames:img = cv2.imread(fname)if img is None:return Nonetry:img = cv2.resize(img, (hparams.img_size, hparams.img_size))except Exception as e:return Nonewindow.append(img)return windowdef crop_audio_window(self, spec, start_frame):if type(start_frame) == int:start_frame_num = start_frameelse:start_frame_num = self.get_frame_id(start_frame)start_idx = int(80. * (start_frame_num / float(hparams.fps)))end_idx = start_idx + syncnet_mel_step_sizereturn spec[start_idx : end_idx, :]def get_segmented_mels(self, spec, start_frame):mels = []assert syncnet_T == 5start_frame_num = self.get_frame_id(start_frame) + 1 # 0-indexing ---> 1-indexingif start_frame_num - 2 < 0: return Nonefor i in range(start_frame_num, start_frame_num + syncnet_T):m = self.crop_audio_window(spec, i - 2)if m.shape[0] != syncnet_mel_step_size:return Nonemels.append(m.T)mels = np.asarray(mels)return melsdef prepare_window(self, window):# 3 x T x H x Wx = np.asarray(window) / 255.x = np.transpose(x, (3, 0, 1, 2))return xdef __len__(self):return len(self.all_videos)def __getitem__(self, idx):while 1:idx = random.randint(0, len(self.all_videos) - 1)vidname = self.all_videos[idx]img_names = list(glob(join(vidname, '*.jpg')))if len(img_names) <= 3 * syncnet_T:continueimg_name = random.choice(img_names)wrong_img_name = random.choice(img_names)while wrong_img_name == img_name:wrong_img_name = random.choice(img_names)window_fnames = self.get_window(img_name)wrong_window_fnames = self.get_window(wrong_img_name)if window_fnames is None or wrong_window_fnames is None:continuewindow = self.read_window(window_fnames)if window is None:continuewrong_window = self.read_window(wrong_window_fnames)if wrong_window is None:continuetry:wavpath = join(vidname, "audio.wav")wav = audio.load_wav(wavpath, hparams.sample_rate)orig_mel = audio.melspectrogram(wav).Texcept Exception as e:continuemel = self.crop_audio_window(orig_mel.copy(), img_name)if (mel.shape[0] != syncnet_mel_step_size):continueindiv_mels = self.get_segmented_mels(orig_mel.copy(), img_name)if indiv_mels is None: continuewindow = self.prepare_window(window)y = window.copy()window[:, :, window.shape[2]//2:] = 0.wrong_window = self.prepare_window(wrong_window)x = np.concatenate([window, wrong_window], axis=0)x = torch.FloatTensor(x)mel = torch.FloatTensor(mel.T).unsqueeze(0)indiv_mels = torch.FloatTensor(indiv_mels).unsqueeze(1)y = torch.FloatTensor(y)return x, indiv_mels, mel, y

(2)训练代码
下面是训练代码,分别使用了3个损失,重构loss,专家判别器loss和视觉质量判别器loss,并且分别有一个权重。在hparams.py我们可以看到,原作者在最开始给定专家判别器loss的权重为0(意味着没有梯度反传,没有训练),视觉质量判别器loss为0.07,当专家判别器loss在验证集中下降到0.75的时候,才修改专家判别器loss的权重为0.03(此时才开始梯度反传)。


def train(device, model, disc, train_data_loader, test_data_loader, optimizer, disc_optimizer,checkpoint_dir=None, checkpoint_interval=None, nepochs=None):global global_step, global_epochresumed_step = global_stepwhile global_epoch < nepochs:print('Starting Epoch: {}'.format(global_epoch))running_sync_loss, running_l1_loss, disc_loss, running_perceptual_loss = 0., 0., 0., 0.running_disc_real_loss, running_disc_fake_loss = 0., 0.prog_bar = tqdm(enumerate(train_data_loader))for step, (x, indiv_mels, mel, gt) in prog_bar:disc.train()model.train()x = x.to(device)mel = mel.to(device)indiv_mels = indiv_mels.to(device)gt = gt.to(device)### Train generator now. Remove ALL grads. optimizer.zero_grad()disc_optimizer.zero_grad()g = model(indiv_mels, x)if hparams.syncnet_wt > 0.:sync_loss = get_sync_loss(mel, g)else:sync_loss = 0.if hparams.disc_wt > 0.:perceptual_loss = disc.perceptual_forward(g)else:perceptual_loss = 0.l1loss = recon_loss(g, gt)loss = hparams.syncnet_wt * sync_loss + hparams.disc_wt * perceptual_loss + \(1. - hparams.syncnet_wt - hparams.disc_wt) * l1lossloss.backward()optimizer.step()### Remove all gradients before Training discdisc_optimizer.zero_grad()pred = disc(gt)disc_real_loss = F.binary_cross_entropy(pred, torch.ones((len(pred), 1)).to(device))disc_real_loss.backward()pred = disc(g.detach())disc_fake_loss = F.binary_cross_entropy(pred, torch.zeros((len(pred), 1)).to(device))disc_fake_loss.backward()disc_optimizer.step()running_disc_real_loss += disc_real_loss.item()running_disc_fake_loss += disc_fake_loss.item()if global_step % checkpoint_interval == 0:save_sample_images(x, g, gt, global_step, checkpoint_dir)# Logsglobal_step += 1cur_session_steps = global_step - resumed_steprunning_l1_loss += l1loss.item()if hparams.syncnet_wt > 0.:running_sync_loss += sync_loss.item()else:running_sync_loss += 0.if hparams.disc_wt > 0.:running_perceptual_loss += perceptual_loss.item()else:running_perceptual_loss += 0.if global_step == 1 or global_step % checkpoint_interval == 0:save_checkpoint(model, optimizer, global_step, checkpoint_dir, global_epoch)save_checkpoint(disc, disc_optimizer, global_step, checkpoint_dir, global_epoch, prefix='disc_')if global_step % hparams.eval_interval == 0:with torch.no_grad():average_sync_loss = eval_model(test_data_loader, global_step, device, model, disc)if average_sync_loss < 2:hparams.set_hparam('syncnet_wt', 0.01)prog_bar.set_description('L1: {}, Sync: {}, Percep: {} | Fake: {}, Real: {}'.format(running_l1_loss / (step + 1),running_sync_loss / (step + 1),running_perceptual_loss / (step + 1),running_disc_fake_loss / (step + 1),running_disc_real_loss / (step + 1)))global_epoch += 1

但是根据作者的这个策略进行训练,专家判别器loss始终下降不到0.75,即使训练了100个epochs。这就导致专家判别器一直没有参与训练。得出的结果也不好。为了使得专家判别器能够起作用,在模型训练20个epochs之后人为将专家判别器loss调至0.03。得出的结果比之前要好,但是还是没有达到原作者给出的效果。于是继续改进,先加入随机种子确保可复现性。

def set_seed(seed):np.random.seed(seed)random.seed(seed)torch.manual_seed(seed)if torch.cuda.is_available():torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)torch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.deterministic = True

然后设置,专家判别器损失低于2,直接改变专家判别器loss权重为0.01。

if global_step % hparams.eval_interval == 0:with torch.no_grad():average_sync_loss = eval_model(test_data_loader, global_step, device, model, disc)if average_sync_loss < 2:hparams.set_hparam('syncnet_wt', 0.01)

总结

在实际应用中,Wav2Lip模型已经成为语音交互领域的重要工具之一,为虚拟现实、增强现实、电影和游戏制作以及智能语音助手等领域带来了更加自然、逼真和智能的交互体验。随着技术的不断发展和完善,Wav2Lip模型将会在未来发挥更加重要的作用。通过本周的学习,我对wav2lip有了初步的认识和了解,希望在后续的学习中可以进一步深入理解。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com