Python换脸术,不会AI也能get有趣又料的技术!

 发布日期:2019-04-25 14:14:46  阅读次数:阅读数:8297  来源:

接下来我将会介绍如何通过一段简短的 Python 脚本(200行左右)将一张图片中面部特征自动替换为另外一张图片中的面部特征。

Python换脸术,不会AI也能get有趣又料的技术!

 

 

具体过程分为四个步骤

 

  • 检测面部标志;
  • 旋转、缩放和平移图 2 以适应图 1;
  • 调整图 2 的白平衡以匹配图 1;
  • 将图 2 的特征融合到图 1 中;

 

实验环境

  • MacOS 10.14.3
  • Python 3.7
  • PyCharm
  • 用到的库有:
  • numpy
  • dlib
  • opencv-python

 

工具说明

  • numpy大家应该都很熟悉了,这里我简单介绍下dlib和opencv。
  • dlib官网介绍其为:A toolkit for making real world machine learning and data analysis applications,简单来说他就是一个开源的机器学习库,包含了很多机器学习的算法。同时对外提供了C++和Python的接口。使用dlib可以大大简化开发,比如人脸识别,特征点检测之类的工作都可以很轻松实现。同时也有很多基于dlib开发的应用和开源库,比如face_recogintion库(据说识别率高达93%,有兴趣的可以查阅相关资料)。python下的安装也很简单,执行 pip install dlib即可。
  • OpenCV:Intel® 开源计算机视觉库。它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法。是计算机视觉领域非常重要的一个开源库。官网地址:https://opencv.org/

 

开始换脸

 

  • 提取面部特征

 

既然要换脸,我们肯定要先在图片中找到人脸,dlib中有一个函数 get_frontal_face_detector()实现了面部特征提取,核心算法来自于 Vahid Kazemi 和 Josephine Sullivan 的论文《One Millisecond Face Alignment with an Ensemble of Regression Tree》,我也没有读过这篇论文就不解释了。提取面部特征的代码如下:

Python换脸术,不会AI也能get有趣又料的技术!

 

get_landmarks() 函数接受一个图片,经过处理后以 numpy 数组的形式进行处理,并返回一个 68x2 的元素矩阵。矩阵的每一行与输入图像中特定特征点的 x,y 坐标相对应。

特征提取器(predictor)需要一个大概的边界框作为算法的输入。这将由传统的面部检测器(detector)提供。该面部检测器会返回一个矩形列表,其中每一个矩形与图像中的一张人脸相对应。

生成 predictor 需要预先训练好的模型。该模型可在微信公众号「01二进制」后台回复"AI换脸"获得。
  • 人脸对齐

 

有了上述方法,我们就可以提取出图片中的人脸了,但是两张照片中的人脸方向肯定都是不一致的(毕竟你不能保证每张都是证件照啊),就像下面这两张图:

Python换脸术,不会AI也能get有趣又料的技术!

 

这两个人脸的方向明显不一致啊,所以我们还需要对人脸进行对齐。我们现在已经获取到每张图片中人脸矩形的坐标了,剩下的就是弄明白如何旋转、平移和缩放第一个向量的所有点,使其尽可能匹配第二个向量中的点就可以了。这里运用到了一个名为普氏分析法(Ordinary Procrustes Analysis)的方法解决这个问题的,数学能力有限,数学依据参考注释中的链接,这里就直接放出代码吧:

Python换脸术,不会AI也能get有趣又料的技术!

 

之后我们再把对齐的结果利用 OpenCV 的 cv2.warpAffine 函数,将第二个图片映射到第一个图片上:

Python换脸术,不会AI也能get有趣又料的技术!

 

  • 校正图片颜色

 

两张图片由于不同的肤色和光线造成了覆盖区域边缘的不连续。所以我们需要修正它:

Python换脸术,不会AI也能get有趣又料的技术!

 

 

  • 图片融合

 

用一个蒙版(mask)来选择图 2 和图 1 应被最终显示的部分:

Python换脸术,不会AI也能get有趣又料的技术!

 

值为 1 (白色)的地方为图 2 应显示的区域,值为 0 (黑色)的地方为图 1 应显示的区域。值在 0 和 1 之间的地方为图 1 图 2 的混合区域。

Python换脸术,不会AI也能get有趣又料的技术!

 

GetFaceMask()函数定义是:为一张图像和一个标志矩阵生成一个蒙版。蒙版会画出两个白色的凸多边形:一个是眼睛周围的区域,一个是鼻子和嘴部周围的区域。之后,蒙版的边缘区域向外羽化 11 个像素,这可以帮助消除剩下的不连续部分。

至此,一个低配版的AI换脸就完成了,结果就如开头那样。此次实验虽然已有换脸的雏形,但是精度还远远不够,而且这种换脸如果用到视频中肯定是不堪入目的,毕竟做得好的已经是下面这样了:

 

Python换脸术,不会AI也能get有趣又料的技术!

如果您有好的新闻与建议,欢迎点击文章投稿

    发表评论

    电子邮件地址不会被公开。

  • 内容

  • 网名