想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!

如今,随着技术的不断进步,“变脸”技术不再是四川喜剧的“独门武功”。运用机器学习的方法,我们同样可以实现人脸“融合”。当然这里说的人脸融合指的是将两个人的人脸照片进行融合,至于融合的比例,要按照自己的喜好来定。

<bi style=”box-sizing: border-box; display: block;”>Python学习群:683380553 ,有大牛答疑,有资源共享!是一个非常不错的交流基地!欢迎喜欢Python的小伙伴!</bi>

核心原理介绍

1).首先是人脸识别的原理介绍

要进行人脸的融合,且融合后两个人脸的位置应该大体一致,这要如何才能做到呢?首先便是人脸的检测,只有检测到了人脸,才能进行接下来的工作。人脸的检测,我们采用的是Dlib函数库,帮助我们进行人脸的检测。如下图所示:

<tt-image data-tteditor-tag=”tteditorTag” contenteditable=”false” class=”syl1553583146879″ data-render-status=”finished” data-syl-blot=”image” style=”box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: “PingFang SC”, “Hiragino Sans GB”, “Microsoft YaHei”, “WenQuanYi Micro Hei”, “Helvetica Neue”, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;”>
《想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!》 image

<input class=”pgc-img-caption-ipt” placeholder=”图片描述(最多50字)” value=”” style=”box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);”></tt-image>

得到人脸的位置后,接下来就是对于人脸的关键点的定位,什么是关键点的定位呢,说的通俗一点,就是确定图片中人脸的关键特征的位置,比如眼睛,嘴巴,鼻子的位置。而这些关键点又被称为Landmark。

2).如何检测这些关键点呢

这里又利用到了Dlib库,Dlib库为我们提供了68个标记点的Dlib官方人脸识别模型,用于构建Dlib的特征提取器,帮助我们进行关键点的提取。提取效果如下图所示:

<tt-image data-tteditor-tag=”tteditorTag” contenteditable=”false” class=”syl1553583146882″ data-render-status=”finished” data-syl-blot=”image” style=”box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: “PingFang SC”, “Hiragino Sans GB”, “Microsoft YaHei”, “WenQuanYi Micro Hei”, “Helvetica Neue”, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;”>
《想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!》 image

<input class=”pgc-img-caption-ipt” placeholder=”图片描述(最多50字)” value=”” style=”box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);”></tt-image>

image

有了关键点,相当于我们有了两张脸的数据,接下来我们将针对于这些关键点进行融合,融合的公式代码如下所示:

<pre spellcheck=”false” style=”box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;”>points = (1 – alpha) * np.array(points1) + alpha * np.array(points2)
</pre>

其中alpha是我们的融合系数,而points1和points2分别代表两张图的关键点,points表示关键点融合的结果。接下来便是对points运用delaunay算法,这个算法将返回一个三角形列表。而至于效果则如下图所示:

<tt-image data-tteditor-tag=”tteditorTag” contenteditable=”false” class=”syl1553583146886″ data-render-status=”finished” data-syl-blot=”image” style=”box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: “PingFang SC”, “Hiragino Sans GB”, “Microsoft YaHei”, “WenQuanYi Micro Hei”, “Helvetica Neue”, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;”>
《想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!》 image

<input class=”pgc-img-caption-ipt” placeholder=”图片描述(最多50字)” value=”” style=”box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);”></tt-image>

image

由上图可以看出,两张图中的三角形抓取了近乎相似的区域。由上面我们可以得到图片1中关键点的和图片2中关键点的集合,以及合成图片的关键点的集合。

我们也由delaunay算法得到了确定的三角形。接下来我们选取图片1中的三角形和合成图中的三角形进行仿射变换,也就是将图片1中的三角形对应的映射到合成图片当中去,关于仿射变换,我们可以使用opencv中的getAffineTransform函数进行。

对于图片2,我们也采取同样的处理方式,最后是基于我们提供的融合系数,进行两张人脸的融合。部分源码如下图所示:

<tt-image data-tteditor-tag=”tteditorTag” contenteditable=”false” class=”syl1553583146890″ data-render-status=”finished” data-syl-blot=”image” style=”box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: “PingFang SC”, “Hiragino Sans GB”, “Microsoft YaHei”, “WenQuanYi Micro Hei”, “Helvetica Neue”, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;”>
《想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!》 image

<input class=”pgc-img-caption-ipt” placeholder=”图片描述(最多50字)” value=”” style=”box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);”></tt-image>

image

上述的morph_faces函数,用来进行人脸的融合,首先是读取两张人脸图片,然后是获取两张人脸的关键点,分别命名为points1和points2并对points1和points2进行融合,命名为points,然后利用morph_triangle函数对人脸进行仿射变换,实现两张人脸的对齐,并将对齐的两张人脸按照融合系数进行融合。

软件界面设计

以上就是关于人脸融合的基本原理,接下来就是运行界面的搭建了。

  • 运行界面的搭建采用的是tkinter进行处理,
  • 首先是打开文件夹,读入我们想要进行融合的人脸
  • 然后是输入融合的比例系数,如果我们忘记输入融合系数的话,软件默认的系数便是0.5
  • 最后点击我们的“人脸融合”按钮,软件便会展示出人脸融合后的效果。
  • 这里需要注意的是,输入的两张图片大小不需要严格的一致,程序会自动帮大家进行图片大小的调整。

<tt-image data-tteditor-tag=”tteditorTag” contenteditable=”false” class=”syl1553583146896″ data-render-status=”finished” data-syl-blot=”image” style=”box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: “PingFang SC”, “Hiragino Sans GB”, “Microsoft YaHei”, “WenQuanYi Micro Hei”, “Helvetica Neue”, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;”>
《想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!》 image

<input class=”pgc-img-caption-ipt” placeholder=”图片描述(最多50字)” value=”” style=”box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);”></tt-image>

image

一共有4个按钮,分布是打开图片1,打开图片2,人脸融合和退出软件。

<tt-image data-tteditor-tag=”tteditorTag” contenteditable=”false” class=”syl1553583146898″ data-render-status=”finished” data-syl-blot=”image” style=”box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: “PingFang SC”, “Hiragino Sans GB”, “Microsoft YaHei”, “WenQuanYi Micro Hei”, “Helvetica Neue”, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;”>
《想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!》 image

<input class=”pgc-img-caption-ipt” placeholder=”图片描述(最多50字)” value=”” style=”box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);”></tt-image>

image

中间有3张图片,前2张都是原始图片,最后一个合成图片,尤其是合成图片那里是关键中关键:

<tt-image data-tteditor-tag=”tteditorTag” contenteditable=”false” class=”syl1553583146901″ data-render-status=”finished” data-syl-blot=”image” style=”box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: “PingFang SC”, “Hiragino Sans GB”, “Microsoft YaHei”, “WenQuanYi Micro Hei”, “Helvetica Neue”, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;”>
《想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!》 image

<input class=”pgc-img-caption-ipt” placeholder=”图片描述(最多50字)” value=”” style=”box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);”></tt-image>

image

这里面的main函数是调用后台的算法函数,然后再输入一个融合系数,就是entry.get()里面获取的用户输入的融合系数,一般默认是0.5,即两个脸一半一半。

后台的算法会把两种图片利用cv2和dlib进行处理合成,然后生成一个新的合成图片

最后我们用PIL库把图片读出来,然后显示在界面上即可。

看一下效果

最后,小编找了几位明星,进行人脸的融合,效果如下图所示:

<tt-image data-tteditor-tag=”tteditorTag” contenteditable=”false” class=”syl1553583146904″ data-render-status=”finished” data-syl-blot=”image” style=”box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: “PingFang SC”, “Hiragino Sans GB”, “Microsoft YaHei”, “WenQuanYi Micro Hei”, “Helvetica Neue”, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;”>
《想不想有一张明星脸,来看看用Python玩人脸合成!刷PS一条街!》 image

<input class=”pgc-img-caption-ipt” placeholder=”图片描述(最多50字)” value=”” style=”box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);”></tt-image>

image

这篇文章主要用了很多计算机视觉方面的库opencv,这个库很博大精深,几乎玩图像的无人不知无人不晓,有兴趣的同学可以研究一下。

    原文作者:不谈风月_0eb8
    原文地址: https://www.jianshu.com/p/34a738bad481
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞