公司年会,大部门一起照了大合影。忽然有兴趣看看大家的平均脸是什么样子的,于是用 OpenCV 从大合影中提取出一千多名程序员的脸,构造了所有人的平均脸。
拿给同事看,大家又要求看分性别平均的平均脸。于是又下载了 Caffe 的 gender classification model,将样本做了一下性别分类,之后分别构造了双方的平均脸。得出结果:大平均的颜值原来是被男生拉低的[哈哈]
本文就讲述根据照片计算平均脸的原理,具体代码,配发实现代码和分类模型。
本场 Chat 只有文章,没有交流。
0. 有趣的平均脸1878年,英国的弗朗西斯·高尔顿爵士(Sir Francis Galton)发明了一种将许多人的照片合成为一张照片,从而创造出一个“平均”面容的技术。
弗朗西斯·高尔顿爵士,英国维多利亚时代的博学家、人类学家、优生学家、热带探险家、地理学家、发明家、气象学家、统计学家、心理学家和遗传学家;也是《物种起源》作者查尔斯·达尔文的表弟。*
当时具体的合成方法是照片叠加——给多个人,比如20个人,照相,将每个人照片所需的曝光时间缩短为1/20,通过20次曝光得到一张“平均”照片。
弗朗西斯·高尔顿最初合成平均脸的目的是将不同“种类”的人(例如:囚犯、精神病患者等等)视觉化,以期得到这类人的“原型”(共同特征),但结果却意外的发现,这样合成的人脸却比用于合成大部分(甚至是全部)都要好看!
虽然高尔顿爵士的初衷没有达到,合成平均脸的方法却保留了下来。
随着技术的发展,照片不再需要物理底片,合成也不再需要复杂的曝光冲印技术,通过一些简单的操作就能做到,人人都可以上手。
大家想必看到过一些按国家、民族合成的平均脸吧:
想不想自己动手制作一张周围人的平均脸?
一点都不复杂,只要知道了原理,会写几行简单的代码,就能顺利完成。
1. 用Image Morphing技术叠加照片Image Morphing技术的原理相当简单:给定两张图片I和J,我们通过叠加(或者叫做混合)I和J来获得一张中间状态的图片M。
I和J的叠加由一个参数[0,1]区间内的参数alpha来控制。当alpha=0时,M就等同于I,而aphla=1时,M就为J。
换言之, M中的每一个像素M(x,y),都可以通过这样一个公式来得到它的值:
M(x,y) = (1 – alpha)·I(x,y) + alpha·J(x,y)
当alpha=0.5的时候,I和J就五五开,平均贡献了M。如果I和J是两张人脸照片的话,M自然也就成了它们的“平均脸”。
看起来好容易哦,那我们赶紧找两张照片来试试吧!就用这两张:
这两张照片alpha=0.5后直接叠加的结果是这样的:
这也不是人脸呀!先别急,看看为什么会这样?
从这张“重影图”上不难看出来,之所以这样,是因为最基本的五官都没有对齐。如果我们事先把两个人的眼睛和嘴对齐,效果就不会是这样的了。
2. 叠加两张“对齐的”人脸叠加图片I和图片J的时候,首先应该建立两张照片中像素的对应关系。
对I中的某一个像素点(xi,yi),我们不是直接在J中取同样位置的点就可以了,而是要找到它在J中内容上的对应点 (xj,yj),然后再进一步找到M中这两个点叠加之后应当处在的位置(xm,ym),最后再用下列式子得出M中对应点的像素值:
xm = (1-alpha) · xi + alpha · xj
ym = (1-alpha) · yi + alpha · yj
算式-1
对一个像素点我们这样做,对整幅图片,则是将上面的过程运用到它的每一个像素点上:
M(xm,ym) = (1 – alpha)·I(xi,yi) + alpha·J(xj,yj)
算式-2
很好,我们已经知道从原理上该怎么叠加两张图了。
其中关键的一步就是:找到对应点。
其实对应点叠加的方法可以用来叠加任何图片,不仅限于人脸。不同物体的叠加,真正的区别就在于找到像素点之间的对应关系!一旦对应关系找到,直接运用算式-2就好了,
既然我们现在要做的是叠加人脸,那么首先当然要找到人脸上的对应点。
人脸是生活