编程语言
首页 > 编程语言> > 手把手:用OpenCV亲手给小扎、Musk等科技大佬们做一张“平均脸”(附Python代码)

手把手:用OpenCV亲手给小扎、Musk等科技大佬们做一张“平均脸”(附Python代码)

作者:互联网

请紧盯这张照片5秒钟,你能否看出任何异样呢?

照片中的女性同时拥有白人血统、西班牙人血统、亚洲人血统以及印度人血统。

她皮肤光彩无暇,眼神扑朔迷离,似乎美得不真实。

她并不真实存在,但她也并非完全虚构。

创造她的正是文摘菌今天要介绍的一项黑科技——“平(da)均(zhong)脸”。

文摘菌今天的手把手专栏将为大家介绍,如何用OpenCV随心所欲帮各种人组合“平均脸”。完整的python代码可在后台回复“平均脸”获取。

让我们先来看两张文摘菌好奇的平均脸。

成功男性科技界企业家平均脸长什么样?

下图是小扎,马斯克,拉里·佩奇,和杰夫·贝索斯的平均脸。杰夫·贝索斯似乎拉低了发量平均值,不过幸好这张平均脸并没有全秃。

小扎,马斯克,拉里·佩奇,和杰夫·贝索斯的平均脸

奥斯卡最佳女主角平均脸又长什么样呢?

下图为布丽·拉尔森,朱丽安·摩尔,凯特·布兰切特,詹妮弗·劳伦斯的平均脸。这张平均脸真是非常迷人了!她的牙齿比企业家平均脸洁白整齐得多。一点也不意外!

近四届奥斯卡最佳女主角:布丽·拉尔森,朱丽安·摩尔,凯特·布兰切特,詹妮弗·劳伦斯的平均脸

最后,文摘菌还用平均脸生成了一张文摘家主编大大们的平均脸,翻到文末看大大们的颜值哦~

“平均脸”的历史

为何平均脸的颜值看起来如此之高?在进入代码实操之前,让我们先来简单了解一下平均脸的历史。

“平均脸”源于达尔文的堂兄Francis Galton在1878年提出的一种新的摄影技术——通过对准眼睛来合成人脸。他认为,通过生成罪犯的平均脸,人们就可以根据面部特征来预测一个人是否是罪犯。很显然,他的假设是错误的——你不能通过照片来预测一个人是否是罪犯。然而,“平均脸”这个创意却流传了下来。

此后,多项研究证明,平均脸其实比个体脸更具有吸引力。在其中一项研究中,研究者们生成了22名入围2002年德国小姐评选决赛的选手的平均脸,并让吃瓜群众打分。结果显示人们认为平均脸比22位选手的脸更有吸引力,包括赢得比赛的柏林小姐。紧接着人们发现,柏林小姐的长相和这张平均脸非常接近。噢!原来柏林小姐的脸吸引人,正是因为她的脸接近平均水平!

按常理说,平均脸不应该很平庸吗?为什么平均脸吸引人?

根据进化假说,有性繁殖的动物会寻找长着平均脸的伴侣,因为偏离平均值可能产生不利的突变。平均脸也是对称的,因为脸的左边和右边的变化是平均的。(文摘菌顿悟瞬间——原来“大众脸”可以是个褒义词。)

接下来,就让我们一起来OpenCV学习创造“平均脸”!

美国总统的平均脸:从Carter到Obama

文摘菌将以美国总统的脸为例(因为美国总统像清晰且高度一致!),给大家介绍生成平均脸的关键技术步骤,完整的python代码可在后台回复“平均脸”获取。

步骤一:面部特征检测

首先,我们需要使用dlib库在每张面部图像上建立68个面部基准点。安装dlib库的步骤较为复杂,如果你无法成功安装dlib,可以跳过该步,使用文摘菌为大家准备的面部基准点示例文档(即为faces文档中的txt文件)。

面部特征检测案例

步骤二:坐标转换

我们手头的面部图像的尺寸很可能是不一样的,同时面部也很可能处于图像的不同位置,所以我们需要标准化面部特征,并把它们放到同一参考坐标系下。

为了实现这一点,我们将图像大小转为600*600,把左眼(外眼角)放在像素位置(180,200),右眼(外眼角)放在像素位置(420,200)。我们称该坐标系统为输出坐标系统,称原始图像坐标为输入坐标系统。

为什么我要选择上述点呢?

因为我希望确保两只眼睛的点都在一个水平线上,面部中心大约在离顶端三分之一高度的位置。所以我将眼角位置设为(0.3宽,高/3)和(0.7宽,高/3)。

在原始图像的68个面部基准点中,左眼外眼角和右眼外眼角分别在基准点36和45。因此我们可以利用这两个点计算图像的相似变换矩阵(旋转、变换和缩放),将输入坐标系统的点进行转换为输出坐标系统。

30002300大小的输入图像通过相似变换矩阵转为600600大小的输出图像

什么是相似变换矩阵?(不想学数学的同学可以简单略过)

如果你想对一个正方形作出转换,使正方形在x和y方向上分别缩放s_x和s_y,同时将它旋转theta角度,再在x和y方向上平移t_x和t_y,对应的相似变换矩阵就是

对于一个(x, y)点来说,它的新位置就将会是

代码实现很简单(这里你需要安装cv2库):

cv2.estimateRigidTransform(inPts, outPts, False)

相似变换矩阵是一个2*3矩阵,用于转换点坐标或整个图像。矩阵前两列用于转换与缩放,最后一列用于变换(如移位)。

这儿还存在一个小问题:

OpenCV要求你至少提供3个点,虽然通过两点你就可以计算相似变换矩阵了。好消息是,我们可以简单假设第三个点,让它与已知的两个点组成等边三角形,然后我们就可以使用 estimateRigidTransform了。

得到相似变换矩阵后,我们就可以用来它将输入图像和基准点转换生成输出坐标了。我们使用warpAffine来转换图像,用transform来转换点。(详见代码)

步骤三:人脸对齐

第二步后直接生成的平均脸

上一步中,我们能够将所有的图像和关键点变换到输出图像坐标系。现在所有图像都是相同大小,并且眼睛的两角都分别对齐。似乎对这些图像每个像素的值进行平均我们就能得到平均脸啦。但如果你真这么做了,会得到上图这样的结果。当然眼睛肯定是对齐的,但是其他面部特征都没对齐。

如果我们知道两张输入图像的点如何一一对应,那我们很容易就能将两张图像完美对齐。然而我们并没有这些信息。我们只知道这些输入图像68个对应点的位置。所以,我们可以用这68个点把图像分成若干三角形区域,然后对齐这些区域,再对像素值进行平均。

平均基准点的Delaunay三角剖分

首先,我们需要计算这68个基准点的坐标平均值,我们利用这68个点(图6蓝色点)以及输出图像边界上的8个点(上图绿色点)来计算Delaunay三角剖分(上图红色边框)。更多Delaunay三角剖分细节请看这里(https://www.learnopencv.com/delaunay-triangulation-and-voronoi-diagram-using-opencv-c-python/)。

Delaunay三角剖分将图像分解成若干三角形。Delaunay三角剖分的结果是一个三角形列表,用76个点(68个人脸基准点+8个边界点)的序号表示。下面的矩阵展示了部分三角形列表,我们看到,关键点62、68和60形成一个三角形,32、50和49形成另一个三角形,等等。

[

62 68 60

32 50 49

15 16 72

9 8 58

53 35 36

… ]

基于Delaunay三角剖分的图像扭曲

至此,我们计算出了人脸基准点的平均位置,并用这些位置计算出Delaunay三角剖分,将图像分成若干三角形。如上图所示,左图是变换后输入图像的Delaunay三角剖分,中图是平均关键点的三角剖分。注意,左图的三角形1对应中图的三角形1。用左图三角形1的三个顶点及其对应的中图三个顶点计算变换矩阵。用这一变换将左图三角形1中的所有像素变换到中图的三角形1中去。对左图每个三角形重复该过程,得到右图这一结果。右图只是将左图扭曲到平均脸。

第四步:人脸平均

现在,激动人心的时刻到了!

经过了上述处理之后,我们就可以对这些照片的像素取平均值,得到神奇的平均脸了。

当然,你也可以生成对称脸,将一张脸及其镜像进行平均。比如:

对奥巴马的图像(左)及其镜像(右)进行平均得到对称脸(中)

彩蛋部分!文摘菌也制作了编辑大大们的平均脸。噔噔噔噔!

  大连包皮医院 mobile.62671288.net

  大连包皮医院哪家好 mobile.xasgnk.cn

标签:Musk,小扎,基准点,剖分,OpenCV,图像,68,三角形,平均
来源: https://blog.csdn.net/qq_42894764/article/details/93198543