【人工智能】AI换脸尝试

本文介绍了如何利用深度学习中的自编码器、上采样技术,结合TensorFlow2实现人脸互换,包括数据预处理、特征提取、模型训练和应用。重点讲解了数据可视化、编码器解码器设计、子像素卷积等关键技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

、## 一、实验目的
人脸互换是计算机视觉领域比较热门的一个应用,它可以应用于视频合成,提供隐私服务,肖像更换等各个应用。本课程将从自编码器,上采样,数据增强等知识点出发,对深度学习下的人脸互换进行讲解。并且利用 TensorFlow 2 实现川普和道格拉斯·凯奇的人脸互换。训练后的模型可以在不修改原图表情的情况下,完成人脸替换。

二、实验内容和要求

数据的可视化
数据增强
自编码器
上采样与下采样
子像素卷积

三、实验结果(结果描述、结果截图、代码截图等)

传统人脸互换

在深度学习出来之前,人脸互换主要是通过对比两张脸的相似信息来进行互换。我们可以通过特征点(下图的红色点)来提取一张脸的眉毛、眼睛等特征信息,然后匹配到另外一张人脸上。如下图所示,这种实现方法不需要训练时间,每次只需要遍历所有的像素点即可。但是,这样实现的效果比较差,无法修改人脸的表情。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/0a60ebc68a979889facf2209b3f91b45.png#pic_center

而深度学习却可以在不修改人脸表情的情况下,做到人脸特征替换的效果。由于视频中的人脸互换所需要的资源过多,并且视频就是由一张张图片组成的,因此本次实验只考虑图片中的人脸替换。我们会借用自编码器的核心思想,然后对 DeepFake 的源码进行解析,最后实现川普和尼古拉斯 · 凯奇的人脸互换。

数据的可视化

下载实验所需要的数据集,并且完成解压。
在这里插入图片描述

数据集主要由两个文件夹构成,一个文件名为 trump ,一个为 cage 。接下来,我们利用 Python 遍历这两个文件夹,并获得所有文件的路径。
在这里插入图片描述

接下来,我们利用 Python 中的 OpenCV 库,对图片进行批量加载。
在这里插入图片描述

这里我们分别加载了两个人物的前三张图片。从上面的运行结果可以看出,每张图片大小为 256×256256×256 。那么怎样才能一次性,将这些图片同时展示出来呢?核心思想便是将这 6 张图片拼在一起,形成一个 512×768512×768 的图片(一行三张,一共两行)。整体的思路如下图所示:
在这里插入图片描述

首先来实现 stack_images 函数。为了方便以后使用,将 stack_images 写成一个可以将图片集合转变成一张图片的函数。
在这里插入图片描述

将 A_images ,B_images 两个图片集合进行展示。由于 OpenCV 无法在 Notebook 上进行图片的展示。因此我们只能利用 OpenCV 读取图片,再利用 Matplotlib 进行展示。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/93814d0663271985e10aabf1267b1834.png#pic_center

编码器与解码器

自编码器是一种用于非监督学习过程的人工神经网络。自动编码器通常由两部分构成:编码器和解码器。下面,我们通过图示来对其进行解释。
在这里插入图片描述

Encoder :编码器,由各种下采样的方法构成。将输入图片压缩成空间特征 (上图的 Code ),也就是对原图片进行特征提取。
Decoder :解码器,由各种上采样的方法构成。重构编码器输出的空间特征,并对其进行解码,输出新的图片。
自编码器的全过程:编码器对输入的图片进行特征提取,然后解码器对提取的特征进行解析,最后输出新的图片。
在这里插入图片描述

如上图所示,我们可以将加噪点后的手写字符放入自编码器中,然后以加噪点前的手写字符为目标进行训练。最终就能得到一个专门处理噪点的神经网络模型。当以后出现新的具有噪点的图片时,只需放入训练好的自编码器就可以直接进行去噪了。

子像素卷积( Sub-pixel Convolution )

子像素卷积是一种巧妙的图像及特征图的 upscale 方法,又叫做 Pixel Shuffle(像素洗牌)。这种方法于 2016 年被 Wenzhe Shi 等人 提出。较之前的上采样算法,子像素卷积在速度和质量上都有明显的提升。
子像素卷积的结构(主要观察后面的彩色部分)如下所示:
在这里插入图片描述

第一个彩色部分是通道数为 r^2 ,大小为 𝑛×𝑛的特性图,即为 Sub-pixel Convolution 前的图像。
第二个彩色部分是通道数为 1 ,大小为 𝑛𝑟×𝑛𝑟 的特征图,即为 Sub-pixel Convolution 后的图像。
上图很直观得表达了子像素卷积的做法,前面就是一个普通的 CNN 网络,到后面彩色部分就是子像素卷积的操作了。
简单的说,就是将每一个像素点的所有通道合并在了一起。例如通道数为 9,那么我就可以把第一个像素点的所有通道拿出来,排成一个 3×33×3 的“像素点”,如下图所示:
在这里插入图片描述

对每个像素点都进行上述操作,最后得到了大小为 𝑛𝑟×𝑛𝑟的特征图,进而提高了原图的分辨率。这种提高分辨率的过程就叫做子像素卷积。
因为相关作者已经为我们写好了 Keras 版的子像素卷积函数,所以我们只需要复制过来(无需手敲),直接运行即可。以后遇到这种上采样的需求,也可直接将函数复制到本地,用以调用。子像素卷积的代码如下:
在这里插入图片描述
在这里插入图片描述

下采样层与上采样层的编写

下采样和上采样就是构成编码器和解码器的具体部件。下采样层主要用于缩小图层大小,扩大图层通道数(即编码器)。上采样主要用于扩大图层大小,缩小图层通道数(即解码器)。
在本次实验中,每个下采样层包括了一个卷积层和一个 LeakyReLU 激活函数层。而上采样包含了一个卷积层,一个 LeakyReLU 激活函数层和一个像素洗牌层。下采样中的卷积层用于缩小图层大小提取图层特征,上采样中的卷积层用于扩大图层通道数,保证在像素洗牌后的图层的通道数和所需通道数相同。
假设在上采样时,我们输入的图层大小为 32×3232×32 ,而我们需要输出的图层大小为 64×6464×64,通道数为 256256 。那么我们就需要在子像素卷积之前先进行一次卷积,使得图层的通道数变为 256×4256×4 (即得到 32×32×102432×32×1024 的图层)。然后再通过子像素卷积,就能够输出 64×64×25664×64×256 的新图层了。
接下来我们利用子像素卷积函数以及 Keras 提供的卷积函数对自编码器中的上采样层和下采样层进行编写。
在这里插入图片描述

接下来,我们传入一张图片对上面自定义的两个网络层进行测试:
在这里插入图片描述

从结果可以看出,上采样层可以将图层的大小减小为原来的 1212 ,下采样层可以将图层大小扩大为原来的 22 倍。

人脸互换的基本架构

其实人脸互换的基本结构就是两个自编码器,更准确的说应该是 1 个编码器 + 2 个解码器。接下来,我会从训练过程和运用过程分别对 AI 换脸的概念进行阐述。

训练过程

![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7d26b00c06a79c6094c2af53efc3ea32.png#pic_cente

如上图,我们利用同一套方法(编码器)对两种图片进行特征提取。将提取出来的特征放到各自对应的解码器中,生成各自所对应的图像。然后利用生成的图像与原来的图像计算损失,再反向传播并对模型参数进行调整,如此循环,直到损失最小。
当损失最小时,我们把川普的图片放入训练好的(Encoder,Decoder_A) 中就能够得到一张和川普神似的图片。同理,若把凯奇的图片放入训练好的(Encode,Decode_B)中,也能得到和凯奇神似的图片。也就是说,在模型训练过程中,原始图片既是训练集合也是目标集合。

运用过程

现在让我们理一下思路,A,B 两类图片通过同一种方法进行特征提取,然后把得到的特征放入各自的解码器中得到了属于自己的图片。
也就是说 Decoder_A 和 Decoder_B 都能够识别 Encoder 所提取的特征。因此,从同一个 Encoder 中出来的特征既可以放入 Decoder_A 中,也可以放到 Deconder_B中,这就是人脸互换的关键,也是 Encoder 只有一个的原因。
因此,在上图的模型训练好后,我们只需进行下图的操作即可实现人脸互换:

如上图所示,将一张川普的图片放入训练好的 EnCoder 中,得到一组特征。将这组特征放入 Decoder_A 中,就能得到一张神似川普的新图片。若将这组特征放入 Decoder_B 中,就会输出与川普表情一样但是和凯奇神似的图片。

神经网络结构

说完人脸互换的原理后,让我们来谈谈本次实验中用到的 Encoder 和 Decoder 的具体网络结构,如下图所示:
在这里插入图片描述

中间那层为编码器的神经网络结构。它由 4 个下采样的卷积层,2 个全连接层,1 个上采样层构成。其中下采样卷积层用于对图片特征进行提取。全连接层用于打乱特征的空间结构,使模型能够学习到更加有用的东西。上采样层用于增加图层大小。
上下两层为两个解码器。他们的网络结构相同,但是参数不同。他们都是由三个上采样层和一个下采样卷积层构成。其中上采样层的作用是为了扩大图层大小,使最后能够输出和原图片一样大小的新图片。最后的卷积层是为了缩小图层通道数,使最后输出的是一个三通道的图片。
接下来利用 Keras 对 Encoder 和 Decoder 进行编写:
在这里插入图片描述

根据人脸互换所需要的自编码器结构,创建 (Encoder,Decoder_A)和(Encoder,Decoder_B)结构,并且选择绝对平方损失作为模型的损失函数。
在这里插入图片描述

数据预处理

为了能够训练出较好的模型,在模型训练之前,我们必须先对数据进行相关处理。接下来,我们将对数据集做如下处理:
在这里插入图片描述

数据增强

数据增强是深度学习中很重要的一步。这种方法可以在不消耗任何成本的情况下,获得更多的数据,进而训练出更好的模型。通过旋转、平移、缩放、剪切等操作,将原来的一张图片拓展成多张图片是数据增强的一种方法。
我们通过对旋转角度,平移距离,缩放比例等随机取值,来对原始图片进行随机转换。
在这里插入图片描述

传入一张图片,进行测试,并观察图片的变化情况:

仔细比较结果中的两个川普(从他们的下巴与下边界的距离,目光方向等方面进行比较),你会发现图片已经发生了变化。当然,如果你并没有发现太大变化,可以多次运行上述代码,如果幸运的话,你可以看到图片出现了翻转(设置的图片翻转概率为 40% )。

输入数据集和目标数据集

由于图片已经把川普的整个大头包含了进去,而我们需要训练只是川普的脸部特征。因此为了提高模型的训练效率,我们需要将川普的小脸从他的大头中切割出来,即将一张 256×256256×256 的大图变为 64×6464×64 的小图。将切割下来的小图放入模型中,既可以提高模型的训练速度,又可以提高准确性。
如果仅仅是裁剪,我们可以直接进行随机剪切。但是为了提高模型的泛化性,在剪切的时候,我们还需要做一次数据增强,也就是将图片进行了扭曲编写。
那么如何做到图片的扭曲呢?首先这里我们用到了 OpenCV 中的简单映射的方法 :将一张图片的一个像素点的值,放到另一张图片上的某个像素点上。
在这里插入图片描述

如上图所示,为了达到卷曲的效果,可以在决定映射位置时,添加一个小的波动,即某个点可能会映射到他原来位置的相邻位置。比如,原图的 4 位置本来应该映射到另外一张图的 4 位置,但是我们可以加上一个比较小的随机值,是它的映射位置出现细微偏移进而达到卷曲的效果。代码如下(下面代码会使用 OpenCV 中的 remap() 函数):
在这里插入图片描述

从上面代码中可以看出,我们并没有直接把做好的输入数据集当做目标数据集,而是对输入数据集中的图片又进行了一次转换。这次转换采用的是点云匹配算法,其本质还是一种映射算法。
代码如下:

在这里插入图片描述
在这里插入图片描述

接下来,我们传入一张图片测试,观察图片的变化,可以发现图片被被裁剪成了 64×64×364×64×3的新图片。
在这里插入图片描述

构造 Batch 数据集

终于到了数据预处理的最后一步,构造 Batch 数据集。这是深度学习中常见的一个步骤,其本质就是根据 batch_size 的大小将数据集进行分批。大小合适的 batch_size 可以使模型更加高效的收敛。代码如下:
在这里插入图片描述

下来我们对上面代码进行测试,从川普的图片集合中取出一个 batch_size 的数据集。
在这里插入图片描述

模型训练

现在神经网络结构搭好了,数据也准备齐了,我们终于可以开始进行模型的训练了。
在这里插入图片描述

模型运用

整个换脸模型被保存成了三部分:编码器 encoder.h5、解码器 A decoder_A.h5 和解码器 B decoder_B.h5。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

根据上述结果,可以看出该模型已经能够很好的进行脸部模仿了。

四、总结与讨论(实验心得、难点分析等)
人脸互换虽然是一个很小的项目,但是里面却包含了各种各样的知识点。在本次实验中,我们学习到了数据的可视化、自编码的应用、上采样的实现以及计算机视觉领域中常用的数据增强的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值