小猪学AI—图像生成原理与应用

概述

最近替换视频中的人脸比较火,涉及的技术主要是图像生成,主要采用生成式对抗网络(GAN, Generative Adversarial Networks )深度学习模型。GAN是近年来复杂分布上无监督学习最具前景的方法之一。模型通过框架中(至少)两个模块:生成模型(Generative Model)和判别模型(Discriminative Model)的互相博弈学习产生相当好的输出。
本文基于Deepfakes Faceswap实现了一个简单的图片换脸过程。

GAN

生成式对抗网络(GAN, Generative Adversarial Networks )是一种深度学习模型,是近年来复杂分布上无监督学习最具前景的方法之一。模型通过框架中(至少)两个模块:生成模型(Generative Model)和判别模型(Discriminative Model)的互相博弈学习产生相当好的输出。原始 GAN 理论中,并不要求 G 和 D 都是神经网络,只需要是能拟合相应生成和判别的函数即可。但实用中一般均使用深度神经网络作为 G 和 D 。一个优秀的GAN应用需要有良好的训练方法,否则可能由于神经网络模型的自由性而导致输出不理想。

机器学习的模型可大体分为两类,生成模型(Generative Model)和判别模型(Discriminative Model)。判别模型需要输入变量 ,通过某种模型来预测 。生成模型是给定某种隐含信息,来随机产生观测数据。举个简单的例子,

  • 判别模型:给定一张图,判断这张图里的动物是猫还是狗
  • 生成模型:给一系列猫的图片,生成一张新的猫咪(不在数据集里)

对于判别模型,损失函数是容易定义的,因为输出的目标相对简单。但对于生成模型,损失函数的定义就不是那么容易。我们对于生成结果的期望,往往是一个暧昧不清,难以数学公理化定义的范式。所以不妨把生成模型的回馈部分,交给判别模型处理。这就是Goodfellow他将机器学习中的两大类模型,Generative和Discrimitive给紧密地联合在了一起 。

GAN的基本原理其实非常简单,这里以生成图片为例进行说明。假设我们有两个网络,G(Generator)和D(Discriminator)。正如它的名字所暗示的那样,它们的功能分别是:

  • G是一个生成图片的网络,它接收一个随机的噪声z,通过这个噪声生成图片,记做G(z)。
  • D是一个判别网络,判别一张图片是不是“真实的”。它的输入参数是x,x代表一张图片,输出D(x)代表x为真实图片的概率,如果为1,就代表100%是真实的图片,而输出为0,就代表不可能是真实的图片。

在训练过程中,生成网络G的目标就是尽量生成真实的图片去欺骗判别网络D。而D的目标就是尽量把G生成的图片和真实的图片分别开来。这样,G和D构成了一个动态的“博弈过程”。

最后博弈的结果是什么?在最理想的状态下,G可以生成足以“以假乱真”的图片G(z)。对于D来说,它难以判定G生成的图片究竟是不是真实的,因此D(G(z)) = 0.5。

这样我们的目的就达成了:我们得到了一个生成式的模型G,它可以用来生成图片。

Goodfellow从理论上证明了该算法的收敛性 ,以及在模型收敛时,生成数据具有和真实数据相同的分布(保证了模型效果)。

目前GAN最常使用的地方就是图像生成,如超分辨率任务,语义分割等等。

 

常见的图像生成器

一、NVIDIA StyleGAN

https://github.com/NVlabs/stylegan

这是英伟达2018年底发布的最新研究成果。十天前,英伟达正式给这个模型命名为StyleGAN。顾名思义,GAN的生成器,是借用风格迁移的思路重新发明的。

这个开源实现可以用Linux跑,也可以用Windows跑,但墙裂推荐大家用Linux跑,为性能和兼容性着想。此外还需要Python 3.6和TensorFlow 1.10以上 (支持GPU CUDA9.0+,cuDNN 7.3.1+) 。

和官方代码实现一起发布的,还有Flickr高清人脸数据集。那些几可乱真的人脸,就是StyleGAN吃了这个数据集,才生成的。当然,StyleGAN不止能生成人脸,英伟达还提供了猫、汽车、卧室的预训练模型。

 

二、Deepfakes Faceswap

https://github.com/deepfakes/faceswap

上面这一段一段合成视频就是Deepfake的杰作,通过机器学习技术搭建了一个系统,让 AI 学习了女明星的面部特征,最后合成到了另一个女演员的头部。

原理与GAN及下方的NVIDIA StyleGAN、CycleGAN基本一致不再赘述。

实现方法: yum install cmake bzip2 pip install tqdm psutil pathlib numpy opencv-python scikit-image scikit-learn matplotlib ffmpy nvidia-ml-py3 h5py Keras cmake dlib face-recognition flask
#0.download准备照片
#   python ~/project/piglab/machinelearning/lib/download_image.py
# 1.extract提取
#   python faceswap.py extract -i ./data/photo/huangrong/ -o ./data/extract/huangrong/
#   python faceswap.py extract -i ./data/photo/guojing/ -o ./data/extract/guojing/
#   python faceswap.py extract -i ./data/photo/zhu/ -o ./data/extract/zhu/
#   python faceswap.py extract -i ./data/photo/yan/ -o ./data/extract/yan/
# 2.train训练   (AB参数:模型用于输入A,输出B)
#   python faceswap.py train -A ./data/extract/huangrong/ -B ./data/extract/zhu/ -m ./models/huangrong2zhu/
#   python faceswap.py train -A ./data/extract/guojing/ -B ./data/extract/yan/ -m ./models/guojing2yan/
# 3.convert替换
#   python faceswap.py convert -i ./data/test/ -o ./data/output/ -m ./models/huangrong2zhu/
# 9.视频<->图片互转
#   ffmpeg -i ./data/video/shediao.mp4 ./data/photo/shediao/video-%d.png
#   ffmpeg -i ./data/photo/shediao/video-%0d.png -c:v libx264 -vf "fps=25,format=yuv420p" ./data/video/shediao-out.mp4

训练数据和模型见:https://github.com/yanjingang/faceswap

*TODO:训练结果待上传

训练环境:4核cpu

训练3小时的情况:loss_A: 0.10076, loss_B: 0.11611

训练12小时后:loss_A: 0.04685, loss_B: 0.04972

训练160小时后:loss_A: 0.03098, loss_B: 0.03123

注:跑了1个月后,发现有个非常重要的影响因素,即本身两个人的肤色、脸型要比较像,否则在没gpu的情况下极难收敛。所以换脸先得有gpu然后找比较像的两个人换。

视频的人脸替换方法:使用视频与图片互转工具从视频中提取帧图片作为训练素材按上边的方法进行训练,然后将所有帧图片换脸,再逆向将帧转回视频即可。

 

三、CycleGAN

https://github.com/PaddlePaddle/models/tree/develop/fluid/PaddleCV/gan/cycle_gan

CycleGAN是发表于ICCV17的一篇GAN工作,可以让两个domain的图片互相转化。传统的GAN是单向生成,而CycleGAN是互相生成,网络是个环形,所以命名为Cycle。并且CycleGAN一个非常实用的地方就是输入的两张图片可以是任意的两张图片,也就是unpaired。

单向GAN:

读者可以按照原论文的顺序理解CycleGAN,这里我按照自己的思路解读。CycleGAN本质上是两个镜像对称的GAN,构成了一个环形网络。其实只要理解了一半的单向GAN就等于理解了整个CycleGAN。

上图是一个单向GAN的示意图。我们希望能够把domain A的图片(命名为a)转化为domain B的图片(命名为图片b)。为了实现这个过程,我们需要两个生成器GABGAB和GBAGBA,分别把domain A和domain B的图片进行互相转换。图片A经过生成器GABGAB表示为Fake Image in domain B,用GAB(a)GAB(a)表示。而GAB(a)GAB(a)经过生辰器GBAGBA表示为图片A的重建图片,用GBA(GAB(a))GBA(GAB(a))表示。最后为了训练这个单向GAN需要两个loss,分别是生成器的重建loss和判别器的判别loss。以上就是A→B单向GAN的原理。

环形GAN:

CycleGAN其实就是一个A→B单向GAN加上一个B→A单向GAN。两个GAN共享两个生成器,然后各自带一个判别器,所以加起来总共有两个判别器和两个生成器。一个单向GAN有两个loss,而CycleGAN加起来总共有四个loss。CycleGAN论文的原版原理图和公式如下,其实理解了单向GAN那么CycleGAN已经很好理解。

效果:

 

参考:

https://blog.csdn.net/sinat_26918145/article/details/79591717

https://mp.weixin.qq.com/s/Kqyv3tC7yeC0BOqin22cWQ

https://mp.weixin.qq.com/s/Rgi6Yxy-kS5y8ui20aU3vg

欢迎关注下方“非著名资深码农“公众号进行交流~

发表评论

邮箱地址不会被公开。