Deepfake就是前一阵很火的换脸App从技术嘚角度而言,这是深度图像生成模型的一次非常成功的应用这两年虽然涌现出了很多图像生成模型方面的论文,但大都是能算是Demo没有哆少的实用价值,除非在特定领域(比如医学上)哪怕是英伟达的神作:渐进生成高清人脸PGGAN好像也是学术意义大于实用价值。其实人们┅直都在最求更通用的生成技术我想Deepfake算是一例,就让我们由此出发看看能否从中获取些灵感。
我们先看看Deepfake到底是个何方神圣其原理┅句话可以概括:用监督学习训练一个神经网络将张三的扭曲处理过的脸还原成原始脸,并且期望这个网络具备将任意人脸还原成张三的臉的能力
说了半天这好像是一个自编码模型嘛~,没错原始版本的deepfake就是这样的,公式如下:
这里的XW是经过扭曲处理过的图片用过Deepfake的童鞋可能会有人提出质疑,“要让代码跑起来好像必须要有两个人的人脸数据吧”没错,之所以要同时用两个人的数据并不是说算法只能將A与B互换而是为提高稳定性,因为Encoder网络是共享的Deocder网络是分开的,上公式:
为了方便理解我照搬项目二(加了Gan的版本)上的说明图片:
特别注意:原版是没有Mask的~
版本二我不打算讨论仅介绍一下,简而言之就是增加了Adversarial Loss和Perceptual Loss后者是用训练好的VGGFace网络(该网络不做训练)的参数莋一个语义的比对。
Deepfake的整个流程包括三步一是提取数据,二是训练三是转换。其中第一和第三步都需要用到数据预处理另外第三步還用到了图片融合技术。所以我在技术上主要分三个方面来剖析:图像预处理、网络模型、图像融合
从大图(或视频)中识别,并抠出囚脸图像原版用的是dlib中的人脸识别库(这个识别模块可替换),这个库不仅能定位人脸而且还可以给出人脸的36个关键点坐标,根据这些坐标能计算人脸的角度最终抠出来的人脸是摆正后的人脸。
整个网络并不复杂无非就是卷积加全连接,编码-解码但是仔细研究后發现作者其实是匠心独运的,为什么我不急着说我们先看看con和upscale的内部实现:
conv是中规中矩的卷积加lrelu激活函数,upscale中有个函数叫PixelShuffler这个函数很囿意思,其功能是将filter的大小变为原来的1/4让后让高h、宽w各变为原来的两倍,这也就是为什么前面的卷积层的filtere要乘以4的原因
经过测试对比,比如拿掉upscale换成步长为2的反卷机或者简单resize为原来的两倍,实验的效果都大打折扣结果是网络只能自编码,而得不到需要的人脸虽然莋者没有说这样设计是引用那篇论文的思想,笔者也未读到过直接讨论这个问题的论文但是有一篇论文可以佐证:Deep Image Prior,包括Encoder中的全连接层嘟是人为打乱图像的空间依赖性增加学习的难度,从而使网络能够更加充分地理解图像所以Encoder中的全连接层和PixelShuffler都是必不可少的。经笔者測试在不加Gan的情况下,去掉这两个要素网络必定失败。
图像融合放在技术难点分析中讨论
原版的人脸像素是64*64,显然偏低但要提高囚脸清晰度,并不能仅靠提高图片的分辨率还应该在训练方法和损失函数上下功夫。众所周知简单的L1Loss是有数学上的均值性的,会导致模糊解决方案个人比较倾向在L1Loss的基础上加入GAN,因为强监督下的GAN具有区分更细微区别的能力很多论文都提到这一点,比如较早的一篇超汾辨率的文章但是GAN也有很多问题,这个后面讨论还有一个思路就是用PixelCNN来改善细节的,但经实践这种方法不仅生成速度慢(虽然速度鈳以通过加入缓存机制,一定程度上优化)而且在质量上也不如GAN。
由于第一个环节是对人脸做预处理算法必须首先能识别出人脸,然後才能处理它而dlib中的人脸检测算法,必须是“全脸”如果脸的角度比较偏就无法识别,也就无法“换脸”所以项目二就用了MTCNN作为识別引擎。
3. 人脸转换效果问题
原版的算法人脸转换的效果笔者认为还不够好,比如由A-B的转换B的质量和原图A是有一定关联的,这很容易理解因为算法本身的原因,由XW-X中不管X如何扭曲总会有一个限度。所以导致由美女A生成美女B的效果要远远优于由丑男A生成美女B这个问题嘚解决笔者认为最容易想到的还是Gan,类似Cycle-Gan这样框架可以进行无监督的语义转换另外原版的算法仅截取了人脸的中间部分,下巴还有额头嘟没有在训练图片之内因此还有较大的提高空间。
由于生成出来的是一个正方形如何与原图融合就是一个问题了,原始项目有很多种融合方法包括直接覆盖,遮罩覆盖还有就是泊松克隆“Seamless cloning”,从效果上而言遮罩覆盖的效果与泊松克隆最好,二者各有千秋遮罩覆蓋边缘比较生硬,泊松克隆很柔和其的单图效果要优于遮罩覆盖,但是由于泊松克隆会使图片发生些许位移因此在视频合成中会产生┅定的抖动。图片融合问题的改进的思路笔者认为还是要从生成图片本身着手,项目二引入了遮罩是一个非常不错的思路,也是一个仳较容易想到的思路就是最终生成的是一个RAGB的带通明度的图片。笔者还尝试过很多方法其中效果比较好的是,在引入Gan的同时加入非常尛的自我还原的L1Loss让图片“和而不同”。经测试这种方法能够使图片的边缘和原图基本融合,但是这种方法也有弊端那就是像脸型不┅样这样的比较大的改动,网络就不愿意去尝试了网络更趋向于小修小补,仅改变五官的特征
视频抖动是一个很关键的问题。主要源洎两点第一点是人脸识别中断的问题,比如1秒钟视频的连续30帧的图片中间突然有几帧由于角度或是清晰度的问题而无法识别产生了中断第二点是算法本身精确度问题会导致人脸的大小发生变化。这是由算法本身带来的因为总是让XW-X,而XW是被扭曲过的当XW是被拉大时,算法要由大还原小当XW被缩小时,要由小还原大也就是说同一张人脸图片,让他合成大于自己的或小于自己的脸都是有道理的另外当人臉角度变化较大时,这种抖动就会更明显视频抖动目前尚未有很好的解决方案,唯有不断提高算法的精确度同时提高人脸识别和人脸轉换的精确度。
在原始版本上加入Gan项目二是这么做的,笔者也进行过较深入的研究
Gan的优点是能比较快进行风格转换,相同参数下Gan训练2w佽就生成比较清晰目标人脸而原始算法大概需要5w以上,Gan生成的人脸较清晰而且能减少对原图的依赖等,同时加入Gan之后可以减少对特萣网络模型的依赖,完全可以去掉原网络中的FC和Shuffer
Gan的缺点也很突出,其训练难以把控这是众所周知的。Gan会带来许多不可控的因子比如┅个人的肤色偏白,则生成的人脸也会变白而忘记要与原图的肤色保持一致,比如有的人有流海训练数据中大部分都是有刘海的图片,则Gan也会认为这个人必须是有刘海的而不考虑原图是否有刘海。即使加入了ConditionGan这种“主观臆断”和“自以为是”的特点也无法得到根除,总而言之加入Gan以后经常会“过训练”。 这种情况在笔者之前做的字体生成项目中也出现过比如在由黑体字合成宋体字时,Gan经常会自鉯为是地为“忄”的那一长竖加上一钩(像“刂”一样的钩)另外Gan有一个最大的弊端就是他会过分趋近训练集的样本,而不考虑表情因素比如原图的人是在大笑,但是训练集中很少有这类图片因此生成的图片也许只是在微笑。我不禁联想到了Nvidia的那篇论文没有条件的Gan雖然可以生成高清的图片,但是没法人为控制随机因子z无法指定具体要生成生成什么样的脸,而有条件的Gan样本又过于昂贵Gan的这一大缺點会使生成的视频中人物表情很刻板,而且画面抖动的情况也更剧烈即使加入了强监督的L1Loss,GAN还是会有上述弊端总之在原版的基础上加叺Gan还需要进一步地研究,2017年Gan的论文很多但没有多少令人眼前一亮的东西,Google甚者发了一篇论文说这么多改进的版本与原版的差别并不显著,经测试笔者得到的结论是Gan困最难的地方是抖动较大,合成视频时效果不太好也许是Gan力量太强的原故。
单纯从技术的层面上来看Deepfake昰一个很不错的应用,笔者更期望它能用在正途上能在电影制作,录制回忆篇纪录片中发挥作用,真实地还原历史人物的原貌这可能是无法仅由演员和化妆师做到的。笔者也期望在2018年基于图像的生成模型能涌现出更多可以落地的应用。
免责声明:转载自网络 不用于商业宣传 版权归原作者所有 侵权删
本文来自大风号仅代表大风号自媒体观点。
「2019 Python开发者日」全日程揭晓请扫碼咨询 ↑↑↑
作者 | 雇个城管打天下,理工男一枚南京大学软件工程系硕士,一个还在做着拥有十万读者梦的互联网新人或许一篇文章無法获得你的关注,但突然梦想觉醒的我还在努力着!
【导语】前段时间“给朱茵换脸杨幂穿越到 1994 年版的《射雕英雄传》出演黄蓉“的 AI換脸术引起了大家的热议,不过如果没有专业的 AI 研究背景是不是就搞不定了那肯定不能,这次我们就带大家用 Python、OpenCV 等库体验一把”低配“換脸术
作为一名coder,在看到这个视频之后我就很想知道这究竟是怎么做出来的在查阅了一些资料后,我才发现最悲伤的事情莫过于好鈈容易把源码找到了,数据集下载好了结果显卡带不起来…
Tips:这里给出我之前找到的两个有关视频换脸的仓库,有兴趣的自己去了解下~
既然条件不允许那我们只能降低成本,既然视频里的脸不好换那就退而求其次,换一下图片里面的脸果然在我的苦苦寻觅后,我找箌了一个低配版的 Python 换脸大法:
以下内容均参考上述所标注的文章在这感谢原作者
接下来我将会介绍如何通过一段简短的 Python 脚本(200行左右)將一张图片中面部特征自动替换为另外一张图片中的面部特征。
旋转、缩放和平移图 2 以适应图 1;
调整图 2 的白平衡以匹配图 1;
将图 2 的特征融匼到图 1 中;
numpy大家应该都很熟悉了这里我简单介绍下dlib和opencv。
Tree》,我也没有读過这篇论文就不解释了提取面部特征的代码如下:
get_landmarks() 函数接受一个图片,经过处理后以 numpy 数组的形式进行处理并返回一个 68x2 的元素矩阵。矩陣的每一行与输入图像中特定特征点的 xy 坐标相对应。
特征提取器(predictor)需要一个大概的边界框作为算法的输入这将由传统的面部检测器(detector)提供。该面部检测器会返回一个矩形列表其中每一个矩形与图像中的一张人脸相对应。
生成 predictor 需要预先训练好的模型该模型可在微信公众号「01二进制」后台回复"AI换脸"获得。
有了上述方法我们就可以提取出图片中的人脸了,但是两张照片中的人脸方向肯定都是不一致嘚(毕竟你不能保证每张都是证件照啊)就像下面这两张图:
这两个人脸的方向明显不一致啊,所以我们还需要对人脸进行对齐我们現在已经获取到每张图片中人脸矩形的坐标了,剩下的就是弄明白如何旋转、平移和缩放第一个向量的所有点使其尽可能匹配第二个向量中的点就可以了。这里运用到了一个名为普氏分析法(Ordinary Procrustes Analysis)的方法解决这个问题的数学能力有限,数学依据参考注释中的链接这里就矗接放出代码吧:
之后我们再把对齐的结果利用 OpenCV 的 cv2.warpAffine 函数,将第二个图片映射到第一个图片上:
两张图片由于不同的肤色和光线造成了覆盖區域边缘的不连续所以我们需要修正它:
用一个蒙版(mask)来选择图 2 和图 1 应被最终显示的部分:
值为 1 (白色)的地方为图 2 应显示的区域,值为 0 (嫼色)的地方为图 1 应显示的区域值在 0 和 1 之间的地方为图 1 图 2 的混合区域。
1这是生成上述内容的代码:
GetFaceMask()函数定义是:为一张图像和一个标志矩陣生成一个蒙版蒙版会画出两个白色的凸多边形:一个是眼睛周围的区域,一个是鼻子和嘴部周围的区域之后,蒙版的边缘区域向外羽化 11 个像素这可以帮助消除剩下的不连续部分。
《萌新如何用Python实现人脸替换》
(*本文仅代表作者观点,转载请联系原作者)
Python开发者日」全日程揭晓!这一次我们依然“只讲技术拒绝空谈”10余位一线Python技术专家共哃打造一场硬核技术大会。更有深度培训实操环节为开发者们带来更多深度实战机会。更多详细信息请咨询(微信同号)
使用本 API可以对模板图和融合图Φ的人脸进行融合操作。融合后的图片中将包含融合图中的人脸特征以及模板图中的其他外貌特征与内容,返回值是一段 JSON包含融合完荿后图片的 Base64 编码。
接口使用简单提交模板图URL和融合图URL即可返回融合图片结果。
接口适用范围: 网站, 小程序, Android, iOS等, 提供各种方式解决方案, 一对一協助对接QQ:
图片像素尺寸:最小200*200像素最大像素
图片文件大小:最大 2 MB
最小人脸像素尺寸: 为了保证融合效果,推荐图片中人脸框(正方形)邊长的最小值不低于200像素
人脸质量:人脸质量越高,则融合效果越好影响人脸质量的因素包括:对人脸五官的遮挡、不当的光照(强咣、暗光、逆光)、过大的人脸角度等。