基于深度卷积网络级联的面部点检测
最近在学习如何制作一个实时的人脸检测系统。
思路很简单,先以单人为例,如果要检测两个图片是不是同一个人,首先要在检测出两个人的面部区域,然后画一个固定像素大小的框,再把框抠下来,这样就得到了两个待匹配的区域。
把两个待匹配区域输入一个训练好的神经网络,输出两个高维特征,通过计算它们之间的距离(例如余弦距离),距离大于阈值,则说明两个照片是同一个人。
这是一个简化的思路,具体每一步的实现都还需要在改进。
我们先来聊聊第一步,读取照片或者读取视频的工作,我们可以通过opencv来实现,通过opencv得到每一帧的图像,还可以通过opencv的内置函数cascadeclassifier得到帧图像中的人脸。但是这样得到的人脸数据是比较粗糙的,对后期的匹配精度影响很大,所以我们需要进行预处理一下。
下面就要开始介绍今天的主角了。
Deep Convolutional Network Cascade for Facial Point Detection
文章是介绍如何卷积神经网络对一个人脸图像进行五个面部点检测,他们分别是:左眼中心,右眼中心,鼻子尖端,左嘴中心,右嘴中心,大致效果如下图:
得到的5个点用于重塑我们的人脸图像,作为最后特征提取网络的输入。
现有的面部点检测技术,可以分为两大类:
(1)一种是训练一个分类器,把图像切分成一个个小区域,用分类器进行分类,找出关键点所在区域。分类器可以使用经典的分类算法,例如Adaboost,SVM,Randomforest等等。这种做法比较容易受到噪声的干扰,有可能会得到多个输出,或者是没有输出。
(2)另一种这是训练一个回归器,通过多次迭代,直接预测关键的位置,这个方法显然是比上一个方法要好的。对于回归器来说,只要算法能够收敛,必然是有输出的,并且这么做不需要扫描图片(我们把使用分类器去分类一个个小区域的做法成为扫描)。这种做法的缺点也明显,由于神经网络是基于梯度下降来优化目标函数的,所以模型容易陷入局部最小值。因此,这个做法需要选取一个合适的初值。
而文章是使用的第二种做法。通过多个卷积神经网络的级联来实现对关键点的预测。
我们先来看一段论文中提出的创新点。
我们提出了一种用于面部检测三层卷积网络,它基于一个级联的回归方法。和现有的方法不同的是,现有的方法只能近似的估计出面部点的初始位置,而我们的卷积网络能够在第一层精确地做出预测,即使是在图一中的非常有挑战性的环境下。这有效的避免了其他方法中的局部最小值问题。我们的卷积网络使用了全脸做为输入,最大程度的利用了上下文的纹理特征信息,并且输出全局的高位特征在深度结构中的更高的曾,这有效地预测关键点,即使当局部区域中的低维特征是挑战性的模糊的或者是损坏的图像样本。我们的卷积网络被同时训练用于预测所有的关键点,并且关键点之间的约束被隐式的编码。
剩下的两个卷积网络,优化了关键点的初始预估值。和现有的方法不同,现有的方法是用了相同的回归器在不同的级联步骤中,我们则设计了不同的卷积网络。这两层中的网络结构是比较浅的,因为他们的任务是在低等级的,并且他们的输出被限制在初始位置周围的很小的局部范围内。
一句话概括,就是论文中的模型一共由三个神经网络组成。第一个模型深,后两个模型浅。第一个模型用整个面部的信息作为输入,同时预测所以的关键点。后两个模型则是基于第一个模型预测的关键点,把以关键点为中心的小范围区域作为输入,最后输出的预测的关键点。
接下来我们来看一下模型的结构图。
解释一下,绿色的框代表的是面部检测器(来自opencv,sk-image之类的)检测到的区域。黄色区域代表的是输入的像素区域。红色点代表每层网络最终的预测结果。第一个层神经网络由三个并行的子网络组成。他们名字分别为F1,EN1,NM1,作用分别是:F1——预测所有的五个关键点,EN1——预测上三个关键点,NM1——预测下三个关键点。当然他们的输入也是不一样的,F1是绿框的区域,EN1是F1上移一点,NM1下移一点。第一层三个子网络得到的点,取平均,作为第二层的输入。对于第二和第三层中的子网络,它们的作用仅仅是对一个关键点的预测。但是每个关键点,都会构造两个网络来预测,结果是之前的输入作为绝对量,在加上后两层大网络的预测值的均值作为偏移量。公式表达为:
具体的网络结构,还有对输入范围设置可以在文章中找到,这里就不多提了。
下一章节我们将研究如何用得到的五个关键点来实现人脸图像的重构。