查看原文
其他

使用Python+OpenCV进行面部合成

2017-10-14 SATYA MALLICK 大邓带你玩python

原文 http://www.learnopencv.com/face-morph-using-opencv-cpp-python/

作者:


https://v.qq.com/txp/iframe/player.html?vid=u0560stpfqh&width=500&height=375&auto=0

在本篇教程中将教大家如何用OpenCV做面部合成,把一张脸演变为另外一张脸。

图片合成

图片合成首次在电影《Willow》(《风云际会》)中得到大量运用,这是由工业光魔(译者注:Industrial Light and Magic/ILM,电影特效制作公司)开发的一项技术。下面是电影的一个场景片段。

https://v.qq.com/txp/iframe/player.html?vid=w1326offcqj&width=500&height=375&auto=0

这个图片合成背后的想法相当简单。给定两张图片I和J,通过混合而成一张中间图M。图片I和J的混合程度由参数α控制,α的值在0和1之间(0≤α≤1)。当α= 0时,图片M看似I;当α= 1时,图片M看似J。简单来讲,你可以用以下方程在每个像素点(x,y)混合图片


但是,用以上方程(假设α= 0.5)得到的国务卿希拉里•克林顿与参议员特德•克鲁兹的混合图片,是下面这个有点糟糕的结果。


这个混合图片看起来很闹心,但它似乎在向你喊着要解决方案,恳求你无论如何在混合前把眼睛和嘴巴对准。当你想把两位不同政治思想家的观点糅合,如果没有事先统一他们的思想,你会得到同样闹心的结果——这有点离题了。

所以,为了将图片I过渡合成到图片J,我们需要先在两张图片之间建立对应像素点。换句话说,对于图片I中的每一个像素点 ,我们需要在图片J中找到对应像素点 。假设我们已经神奇般地找到了所有对应点,我们可以用两个步骤将图片混合。第一步,我们需要计算合成图片中像素点 的位置。可以由以下方程算出


第二步,我们需要利用以下方程找到像素点的像素强度

这就是合成过程,我们已经完成了。现在,让我们去给特朗普投票吧!开玩笑的!就像特朗普一样,我省略掉了一些重要的细节。想要在图片I中找到图片J中的每一个对应像素点,就如同在美国和墨西哥之间建10英尺高的墙一样难。当然这不是不可能,只是有点费力不讨好。

但是,找到部分对应点还是比较容易的。想要合成两个相异的物体,比如一张猫的脸和一张人的脸,我们可以点击两张图片中的部分像素点来建立对应关系,对于其余的像素点则采用插值法来得到最终结果。我们接下来会看到面部合成的具体步骤,这种方法可以应用于任意两个物体。

面部合成:一步一步来

以下步骤可以合成两张脸。为了简化,我们假定这两张图片大小相同,但实际上这并不必要。

1.用“面部特征检测”找到对应点

让我们从获取对应点开始。首先,我们可以通过检测面部特征点自动(或手工)获得大量像素点。我用dlib库检测到68个对应点。接下来,我手工增加了4个点(1个在右侧耳朵,1个在脖子处,2个在肩膀处)。最后,我增加了图片的角点和边的中点作为对应点。毋庸置疑,在头部和颈部增加越多的点,得到的图片效果就更好;反之,去掉手工点(只剩下自动点),得到的图片效果就要差一些。

2.德洛内三角剖分算法

我们从之前的步骤得到了两个80个点的集合——每个图片有一个集合。我们可以计算出两个集合中对应点的平均值,由此获得一个新的集合。我们在这个均值点集上使用德洛内三角剖分算法。这个算法将返回一个三角形列表,该列表由80个点的数组中点的索引表示(译者注:点的“索引”在此为保存80个像素点坐标文件的行数,即每个数字代表一个点的坐标)。在这个例子中,三角剖分法根据80个点产生了149个三角形。该结果以三列数组的形式保存。以下显示的是数组的前几行。

Triangulation
38 40 37
35 30 29
38 37 20
18 37 36
33 32 30

该列表表示点38,40和37组成了一个三角形,以此类推。三角剖分法的结果显示在下面的图中。


请注意,两张图中的三角形抓取了近乎相似的区域。我们从对应点开始,由于使用了三角剖分,可以得到对应三角(或区域)。

3.图片变形和alpha混合处理

现在,我们具备智能混合两张图片的条件了。正如前文所言,混合的程度是由参数控制的。可以按以下步骤创建一张合成图片。

找到合成图片中的特征点坐标:在合成图片M中,我们可以用方程(1)找到全部80个点的坐标 。

计算仿射变换:我们有了图片1中80个点的集合,图片二中80个点的集合,以及合成图片的80个点的集合。我们也知道这些像素点所确定的三角形。选取图片1中的一个三角形和合成图片中的对应三角形,计算仿射变换,将图片1的三角形的三个顶点映射到合成图片的对应三角形的三个顶点。在OpenCV中,可以使用getAffineTransform来计算149对三角形各自的仿射变换。最后,在图片2和合成图片间重复这个过程即可。

三角形变形:对于图片1中的每个三角形,用之前步骤计算出的仿射变换来将三角形内的所有像素点变形到合成图片中。对图片1中的所有三角形重复使用这个变形过程,可得到图片1的变形版。同样的,可以得到图片2的变形版。在OpenCV中,可以用warpAffine函数来实现这个变形。然而,warpAffine的输入要求为一个图像,而不是一个三角形。有个窍门是算出三角形的边界框,在边界框内用warpAffine变形所有像素点,然后遮盖掉三角形外的像素点。可以用fillConvexPoly创建三角形状的遮片。一定要确保用warpAffine的同时使用blendMode BORDERREFLECT101。这样会将接合处隐藏得很好——比国务卿克林顿藏她的邮箱藏得好多了!(译者注:请搜索克林顿的Email Scandal,这位美国政界的女性翘楚似乎不大满意白宫配发给她的邮箱啊~)

Alpha混合变形图像:在之前的步骤里我们得到了图片1和图片2的变形版。这些图片可以用方程(2)做alpha混合,会得到最终的合成图片。在我提供的代码里,把三角形变形和alpha混合组合成简单的一步。

面部合成结果

应用以上技巧合成的结果如下方所示。中间的图片是将左、右两图按50%的比例进行混合。本文的第一个视频展示了使用不同alpha数值的动画。动画可以很好地掩盖合成过程的一些瑕疵;参议员特德•克鲁兹也喜欢这样的小把戏。

大多数面部特征是对准的。但脸部外侧的部分重合得不好,因为在那些区域我们选取的对应点较少。你可以手工增加额外的像素点来修正未对准的部分,以此获得更棒的效果。

历史文章:

数据采集

selenium驱动器配置详解

抓取单博主的所有微博及其评论

爬虫神器PyQuery的使用方法

pyquery一些自定义的用法

【视频】猫途鹰网站评论数据抓取

【视频讲解】在scrapy框架中如何使用selenium?

【实战视频】使用scrapy写爬虫-爬知乎live

简易SQLite3数据库学习

【视频教程】对视频进行基本操作

【视频】抓包小练习-B站评论数据抓取

fake-useragent库:值得花2分钟学习的库

【视频】爬取饿了么平台上的门店信息

如何抓取视频资源-以头条视频为例

当爬虫遭遇验证码,怎么办

【视频】手把手教你抓美女~

【视频】有了selenium,小白也可以自豪的说:“去TMD的抓包、cookie”

【视频】快来get新技能--抓包+cookie,爬微博不再是梦

【视频教程】用python批量抓取简书用户信息

识别假货有绝招,就用python爬淘宝评论

用Python抓取百度地图里的店名,地址和联系方式

文本处理分析

gensim:用Word2Vec进行文本分析

Python NLP中的五大英雄

用SenticNet库做细粒度情感分析

如何对csv文件中的文本数据进行分析处理

复杂网络分析数据准备篇

文本分析之网络关系

用词云图解读“于欢案”

基于共现发现人物关系的python实现

用pyecharts制作词云图

图片数据处理

OpenCV:快速入门图片人脸识别

好玩的OpenCV:图片操作的基本知识(1)

好玩的OpenCV:图像操作的基本知识(2)

OpenCV:计算图片有多色

如何对数据进行各种排序?

其他

【视频】初学者必看:python环境配置

开扒皮自己微信的秘密

初识装饰器函数

计算运行时间-装饰器实现

花十分钟,给爱机安装个MongoDB

chardet库:轻松识别文件的编码格式

使用Python登录QQ邮箱发送QQ邮件

WTF Python: 开启你的懵逼模式

8行代码实现微信聊天机器人

WTF Python: 开启你的懵逼模式

WTF Python:开启懵逼模式第二弹


本文不是原创,无需给我红包。如果觉得大邓给力,可将本文分享给亲朋好友,谢谢大家支持。

项目代码

链接: https://pan.baidu.com/s/1i5Bvdo5 密码: ipv6

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存