通过计算机视觉技术模拟出人老了的样子,这样的应用实际上并不新奇。这些年,类似的场景可谓层出不穷,有的App可以通过夫妻的样貌预测出孩子的模样,有的App可以通过用户上传的照片还原你小时候的样子和老了之后的样子,甚至还有一些App可以通过一两张照片生成出一段短视频,展示用户一生的样貌变化,让使用的人颇有沧海桑田之感。
而我们这次的“当你老了”项目的着眼点略有不同,强调的是公益和技术的结合,因此我们需要将用户上传的面部照片变成20年,40年和60年后,让用户看到自己满脸皱纹,白发苍苍的样子,进而产生关爱身边老年人的感慨,人人每年公益3小时,共同为公益做出贡献 。
经过将近4周左右的努力,我们初步完成了人脸老化项目的开发,赶在9月5日央视慈善之夜晚会前及时上线。央视公益晚会期间,用户通过扫描电视屏幕上的二维码,进入我们手淘的互动页面(详见图1),选择自己喜欢的照片进行老化。一场晚会下来,许多的用户体验到了自己脸部变老之后的特效。
图1. 手淘“当你老了”项目页面示意图
整个项目中我们遇到了很多的挑战,比如老化模版的选择,脸型的变化趋势问题,肤色的融合问题等等,下面我会把整个人脸老化技术分成几个关键的部分,进行简短的剖析。
1、脸型的老化算法
我们借鉴了一篇2017年最新的利用深度学习进行人脸老化的文章[1],该文章提出了一种叫做conditional adversarial autoencoder (CAAE)的深度网络结构,该结构能够学习出面部的manifold,从而预测出任何一张输入面部图像的全年龄面部图像。该网络的结构示意图如图2所示,该网络学习之后的预测结果示意图如图3所示。
图2. Structure of the proposed CAAE network for age progression/regression. The encoder E maps the input face to a vector z (personality). Concatenating the label l (age) to z, the new latent vector [z, l] is fed to the generator G. Both the encoder and the generator are updated based on the L2 loss between the input and output faces. The discriminator Dz imposes the uniform distribution on z, and the discriminator Dimg forces the output face to be photo-realistic and plausible for a given age label.
图3. Comparison to prior works of face aging. The first column shows input faces, and second column are the best aged faces cited from prior works. The rest columns are our results from both age progression and regression. The red boxes indicate the comparable results to the prior works.
尽管该深度学习网络能够很好的获得全年龄段的输出,但是它存在两个弊端,其一是它训练预测出来的图片和输入人脸差异比较大,不像原始输入;其二是处理速度上该网络速度比较慢,很难适应项目的要求。针对这两点缺点,我们决定只保留该网络的老化脸型的能力,而脸上的纹理,即皱纹部分我们通过传统方法来贴。图4显示了我们通过该网络获得的脸型变老的能力示意图。
图4. 面部脸型变老的示意图,从左到右分别是原图,20年后,40年后,60年后
2、脸部纹理的老化算法
在贴脸部皱纹或者说纹理的过程中,我们采用的是分而治之的办法[2]。即把面部分成许许多多的小三角形,然后将老人模版上对应的三角形贴到相应的输入人脸的三角形上。这样做的好处是每个三角形足够小,利用OpenCV的WarpAffine进行形变贴图时不会出现不自然的现象。当然这样做的前提是,我们已经获得了输入人脸以及模版人脸的所有关键点,同时利用Delaunay Triangulation将所有关键点划分成若干三角形了。关键点和三角形Mesh示意图如图5所示。
图5. 面部关键点示意图,面部三角形化示意图
3. 肤色的融合算法
在完成了人脸的老化脸型变化和贴皱纹的步骤后,我们还缺最后一步,即将老化后的脸完美无瑕地贴回到原始输入图像上去,否则会显得老化很不自然。这里我们采用了一个非常经典地融合算法,即Poisson Image Editing[3],它是通过保留剃度的方式使贴过来的图像能够无缝地融入背景图像。这里我们利用了OpenCV3.2里面提供的SeamlessClone这样一个函数,可以比较方便地实现前后景融合。肤色和纹理的融合示意图如图6所示。
图6. 从左到右依次为原始图像,老人模版贴入相应三角形,SeamlessClone之后的融合结果
4. 项目小结
在脸型,皱纹,肤色的老化之外,我们还尝试了头发的变白等算法,篇幅有限,就不在此赘述了。最后贴几张我们认为效果还是不错的人脸老化结果作为结尾。
图7. 效果示意图
Reference
[1] Zhifei Zhang, Yang Song, and Hairong Qi. "Age Progression/Regression by Conditional Adversarial Autoencoder." IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2017.
[2] Face Morph Using OpenCV — C++ / Python,http://www.learnopencv.com/face-morph-using-opencv-cpp-python/
[3] Poisson Image Editing,http://www.ctralie.com/Teaching/PoissonImageEditing/.