基于改进Coarse-to-fine CNN网络的人脸特征点定位
原文地址:http://blog.csdn.net/hjimce/article/details/50099115
作者:hjimce
一、相关理论
本篇博文主要讲解2013年face++的大牛们提出粗到精人脸特征点定位算法paper:《Extensive Facial Landmark Localization with Coarse to fine Convolutional Network Cascade》,发表于2013年ICCV上的一篇用于定位多个人脸特征点的文献,实现了68个人脸特征点的高精度定位。这篇paper没有给出训练数据,也没有给出测试模型、源代码等,所以源代码需要自己写,训练数据我们需要自己到IBUG网站下载,可以下载到两千多张的训练数据,这篇paper的代码花了我两周的时间,主要是裁一些细节方面很麻烦。
我个人感觉这篇文章的创新点不是很大,基本上是在文献:《Deep Convolutional Network Cascade for Facial Point Detection》的基础上做了一点点的修改,使得我们构建的CNN模型可以用于定位更多的特征点,总结为一句话就是如果想要看懂这篇文献,还是建议先好好学习paper:《Deep Convolutional Network Cascade for Facial Point Detection》,熟悉代码是怎么实现的,然后再来搞这篇文章的算法,就只需要改一改就OK了。
人脸68特征点的定位方法,也是采用了从粗到精的定位思想,网络属于DCNN,开始讲解这篇paper之前,我先讲解一下文献的创新点,因为如果你已经熟悉了《Deep Convolutional Network Cascade for Facial Point Detection》的算法,我们只要把创新点抓住,就OK了。本篇给我的感觉最大的创新点在于:在网络的输入方面,不是用人脸检测器检测到的人脸区域图片作为网络的输入,而是采用CNN预测人脸的bounding box,这个改进对初始level定位精度提高非常多,如下图所示,当我们输入一张图片的时候,我们用CNN,分别预测出Inner points和Contour points的最小包围盒:
切记:上面的两个部分的特征点预测是完全分开的,各自的网络可以进行并行训练、预测。就像上面,两部分的分开预测,第一层次的目的都是为了获得Bounding Box。
虽然文献还提出了一些其它方面的细节,但是我感觉基本上对精度影响都不大,比如文献最后在预测inner point的时候,还多了一个层次网络level 4(对总精度提高非常小,后面再讲解),如果你仅仅是为了学习这个算法的话,完全可以不用level 4,当然如果你要实现最高的精度(用于商用),就要把老老实实根据文献的算法,一步一步来了。好了,言归正传,下面开始讲解paper算法。在这篇paper的算法中,被预测的68个人脸特征点分为两个部分。
第一部分:主要是人脸五官的特征点预测,这部分预测点的个数为51,在文献中又把这部分特征点命名为:Inner points,貌似文献中并没有显示51个点,如下图所示:
第二部分:用于预测人脸外轮廓的17个特征点。我们又称之为:Contour points ,请记住Contour points和Inner points这两个名词指的是哪部分特征点,我后面都使用这两个词进行讲解。
Inner points和Contour points这两部分相互独立,用不同的网络结构进行预测,也就说这两部分可以并行计算,其中contour point的预测比较简单,paper的大部分精力都花在讲解inner points 上面,算法也都是讲解inner points,因为inner points是五官特征点的位置,定位比较复杂,所以才要花费更多的精力去提高精度。
一、Inner points预测
Inner points的预测是一个四层次的DCNN模型。level 1就是我们前面讲的预测bounding box;level 2 用于这51个点的初始定位,也就是粗定位;level 3 用于精定位;level 4 用于更精定位(这一层次对精度提高很小)。
第一层次(level 1):这个就是我们上面讲的预测最小包围盒。输入一张完整的图片,我们通过这一层CNN,预测这51个点的最小包围盒(Bounding Box)。Bounding box 包含矩形左上角的坐标、右下角的坐标,也就是网络的输出是一个4维的向量:
输入 输出
第一层次
第二层次(level 2):网络的输入,就是我们通过第一层次预测到的51个点的最小包围盒中的人脸图片;网络的输出是51个特征点预测位置(粗定位位置)。这一层次比较简单,说白了就是我们常见的CNN,用普通的CNN预测51个特征点(当然用这一层预测出来的位置,只能作为初始位置,因为通过这一层预测的精度还不够高,只能作为51个点的粗定位。我们需要有后面继续两个层次网络进行精定位)。
第二层次
网络的输入:把level 1得到的最小包围盒中的图片裁剪出来,作为输入,进行51个点人脸特征点预测。
网络的输出:因为我们是要预测51个特征点,所以CNN的输出是102神经元。
第三层次(level 3):因为我们上面一层的网络,已经预测到了51个特征点,然而这51个点的位置还不够高,我们需要对其做进一步的精定位。
第二层次预测的51个点,之所以精度不够高,是因为我们输入的图片是大的图片,是对全局的统一预测(具体解释可以参考文献《Deep Convolutional Network Cascade for Facial Point Detection》),容易受冗余信息的干扰。说的简单一点吧:假设你要定位嘴巴的特征点,你的输入图片就应该只有嘴巴部分的区域图片,这样的精度才会比较高,而不是你把一整张人脸图片作为输入,这样冗余信息太多,容易干扰到我们的嘴巴区域的定位。
因此我们这一层次的网络,就是要利用level 2的网络预测到的51个点,把五官的图片裁剪出来,然后对五官进行分别的定位。具体的示意图如下:
第三层次
网络输入:利用level 2的51个点,对五官图片裁剪,把裁剪的五官,进行分开训练、预测。因为我们要各个器官分开训练,因此自然而然本层需要有4个CNN模型,每个模型用于预测各自的特征点
网络输出:各个器官的特征点
第四层次(level 4):这一层次的输入,与文献《Deep Convolutional Network Cascade for Facial Point Detection》相比,稍稍做了修改。跟我想象的有点不一样,paper通过把level 3的各个五官预测结果,计算各五官的旋转角度,然后把五官都摆正了,作为第四层次网络输入图片,然后在进行预测。
第四层次
这一层网络,对于我们来说可以不去实现,只到level 3就好了,这篇paper是为了达到state-off-art 所以才增加了level 4。其实这一层网络,对精度的提高非常非常小,我们看一下paper的每一层的误差:
各层次网络的误差
好好看一下上面这个表格的数据,level 2 作为初始的预测,验证误差是0.051,通过leve 3的精定位,误差减小到了0.0438,也就是说相对精度相当于提高了14%,这一层精度的提高很明显。然而从level 3到level 4 误差从0.0438到0.0431,好像性能提高不了多少。因此对于我们如果要用于商用,需要考虑计算时间效率、精度等综合因素,可以不要采用paper的level 4,不划算,精度提高那么小,计算时间却增加了相当多。
二、Contour points预测
这17个点的预测比较简单粗暴,就只是两个层次的DCNN模型,这两个层次说的简单一点就是类似上面Inner points的第一、二两个层次网络。
第一层次:这个在前面已经讲过了,也就是预测Contour points的最小包围盒(下图中的底部示意图)。
第二层次:CNN直接预测这17个特征点。
这个预测过程,没有精定位过程。也就是没有第三、四层次的CNN精定位,一来是因为这些脸庞特征点的图片区域比较大,如果加上第三、四层次的话,会比较耗时间;二来是因为paper还没想到比较好的方法,用于精定位。
总结:总的来说呢,这篇文献的思想和《Deep Convolutional Network Cascade for Facial Point Detection》的思想是一样的,看文献的名字就知道了,是在这篇paper的基础上,进行改进的一种用于多个特征点预测的网络结构。因为paper《Deep Convolutional Network Cascade for Facial Point Detection》只预测5个特征点,于是face++他们就在这篇文献的基础上做了改进,使网络结构可以用于很多个特征点的预测。
从这篇paper的创新方面讲:
1、文献把人脸的特征点定位,分开成两个部分了:Inner和Contour两部分特征点,进行分开预测
2、在Inner的预测部分,从level 2 开始把五官裁剪分开,进行精定位。
3、在每个器官的每个特征点的定位方面,文献并没有像《Deep Convolutional Network Cascade for Facial Point Detection》的方法,把每个特征点的都用独立的网络进行定位,不然如果按照《Deep Convolutional Network Cascade for Facial Point Detection》的思想,51个特征点的定位,精定位的每一层次就要有102个CNN模型(因为《Deep Convolutional Network Cascade for Facial Point Detection》文献每个特征点的精定位是用了两个网络进行训练、预测,然后用两个网络的输出作为平均值,所以是102个网络),这样太耗时间了,万一我要定位300个特征点,不得崩溃。因此face++的这篇paper并没有把每个特征点分开独立训练、预测,仅仅把各个器官分开训练。
4、多了一个bounding box 层,可以大大提高特征点粗定位网络的精度。
三、相关细节与原理解释
采用粗定位到精定位的过程,有很多优点:
1、各个五官分开预测的原因解释
各个部分分开训练,这样网络的损失函数是分开的。这样做可以提高精度的原因在于:因为网络各个部位特征点的定位难度不同,或者说定位难度不平衡。比如,contour特征点的定位比inner 特征点的定位难度大,这个主要是因为人脸外轮廓往往比较模糊、还有受到头发等背景因素的干扰,所以人脸的外轮廓的特征点的定位难度会比较大。这些因素,引起了训练损失函数各个特征点严重的不平衡,比如比较难定位的contour的特征点,就会对损失函数,占用比较大的比重,因此如果我们68个特征点一起训练的话,L2损失函数值基本上是contour的特征点占用了比较大的比重。所以文献才采用把inner和contour分开预测,这样可以避免不平衡问题。
同理,在inner预测部分,把五官的预测都分开。比如因为眉毛的误差往往会比较大,而眼睛的预测精度就比较高了,这样把各个器官都分开,不共用一个损失函数,可以避免不平衡问题。
2、采用多层回归的原因
也就是采用从粗定位到精定位的原因,这个感觉paper解释的有点不好,可以自己去看一下《Deep Convolutional Network Cascade for Facial Point Detection》文献的解释,这里懒得解释了。打了一个早上的字,才讲解到这边,心塞……。
3、采用CNN预测bounding box
相比与直接采用人脸检测器,进行预测人脸矩形框来说,这个方法比较靠谱。因为采用人脸检测器检测到的人脸框,往往包含了太多了无关的背景,会对我们的网络有一定的干扰。另一方面,如果直接采用人脸检测器,检测到的人脸有的时候,并不是位于矩形的中心,这样对结果也会有一定的影响。
四、网络结构及其训练
OK,到了这里我们就要讲具体的相关实现了。首先我们先做个定义:N1表示为inner point各个特征点的初始位置预测,也就是相当于inner 的level 2。N2表示为contour point点的预测(contour的level 2)。
下面是N1的网络结构图,网络的输入是60*60大小的图片:
网络结构方面基本上与传统的CNN模型,差不多,最大的区别在于locally sharing weights,也就是上面的unshared conv层,我们平时所遇到的CNN都是global sharing weights的。但是对于特征点的预测,五官的高层特征差别比较大,所以需要在高层采用unshared weight的方式,在低层采用global sharing weights。
1、网络训练:采用随机梯度下降,同时采用图片相似变换(旋转、缩放、平移等),对数据进行扩充,防止过拟合。
2、数据预处理:采用数据归一化到:均值为0,方差为1,然后采用hyper-tangent 函数,把数据映射到-1~1之间。还有就是以上各层,在进行图片裁剪的时候,需要稍微大一点点,不然当定位稍微不准的时候,直接采用原比例进行裁剪,会把我们想要的部分也可能给剔除掉。
六、算法试验
1、bounding box level 测试(level 1 到level 2)
为了快速验证文献的主要思想、创新点,也就是增加bounding box level层,我对《Deep Convolutional Network Cascade for Facial Point Detection》算法进行了改进测试,先测试5个特征点的情况,因为我对文献《Deep Convolutional Network Cascade for Facial Point Detection》之前已经比较熟悉了,而且代码也写过了一遍,所以利用已有的代码,直接测试本篇paper所提出的bounding box level,看看增加bouding box层与直接采用人脸检测器,对各特征点初始位置预测精度能提高多少?
我根据paper的算法,进行人脸特征点定位试验,只测试了5个特征点的预测,比较采用bounding box level和face detector 对5个特征点初始位置预测精度的影响。验证过程:主要是测试bounding box层对精度的影响,paper在验证集上测试误差,然后与直接采用人脸框检测的精度预测结果,对人脸特征点初始预测精度的影响。
(1)直接采用人脸检测器作为level 1
直接采用人脸检测器作为level 1,在我的测试集上,损失误差如下:
测试过程中,为了简单起见,暂时没有使用unshared weights的、也没有使用fabs层,直接采用face detector 各特征点的预测结果(蓝色的点代表标准点,红色点表示利用网络进行预测的点):
红色的点是预测点,蓝色点是手工标定的点
(2)采用bounding box estimation作为level 1
下面是采用bounding box 作为DCNN的level 1,最后测试level 2预测的精度:
结论:采用bounding box作为level 1,相比于直接采用人脸检测器作为level 1,人脸五官特征点的初始位置预测,误差可以减少0.02左右,相对精度相当与提高了26%。相关预测效果(蓝色的点代表标准点,红色点表示利用网络进行预测的点):
精度的提高还是比较明显的。
2、68个特征点测试(level 2 到level 3)
因为5个点的训练数据很多,所以上面一开始我才使用5个点的训练数据1w张,作了bounding box level层的测试。最后为了测试68个点的情况,我从ibug网站:
http://ibug.doc.ic.ac.uk/resources/300-W/ 下载了68个点的训练数据,总共有3k张,我等穷人只能硬着头皮上,利用3k张做训练测试。而且我比较懒,数据扩充也只用了360度旋转,没有采用镜像,因为镜像数据扩充的时候,各个特征点的序号是要改变的,最讨厌这些小细节了(特别是五官的裁剪,然后预测到特征点后,要重新组合,好心烦),所以干脆不镜像了,因为自己一个人要搞这些小细节,实在是很苦逼,很心烦。最后我也没有使用缩放扩充。(ps:文献使用了旋转、镜像、缩放等数据扩充,而且也不知到用了多少训练数据图片),总之穷人的难处,说多了,都是泪啊,啰嗦了这么多,该继续搬砖了……。
在第一部分,我已经测试了bounding box level 1层对leve2 层精度的影响,因此接着我就直接测试从leve2 到leve3 的粗预测到精定位过程(最后验证,性能跟文献说的差不多,提高了15%左右)。
(1)鼻子从粗到细
为了清楚查看从leve2 到leve3 的精度变化我裁剪出鼻子部位的预测结果,进行比较测试(蓝色的点代表标准点,红色点表示利用网络进行预测的点):
粗定位 精定位
试验1、粗定位&灰度图像:
试验2、精定位&灰度图像&左右expand大小选择0.3 ,上下expand选择0.1
(2)嘴巴从粗到细
试验1、粗&灰度图像:
试验2、细&灰度图像:
精度反而比粗定位的精度降低了。于是接着我用彩色图像定位嘴巴,得到如下的试验
试验3、细&彩色图像:
总结:对于嘴巴部位的精度,有可能是训练数据的原因,最后我是采用彩色图像作为网络的输入,提高精度
(3)右眼眼睛从粗到细:
试验1、粗&灰度图像:
试验2、精&灰度图像:
(4)左眼从粗到细
试验1、粗&灰度图像:
试验2、精&灰度图像:
(6)左眉毛从粗到细
试验1、粗&灰度图像:
试验2、精&灰度图像:
(7)51点整体误差
试验1、粗&灰度图像:
试验2、精&灰度图像
最后结果:
左边图是标准的基准点,右边是文献paper算法的最后预测结果。
参考文献:
1、《Extensive Facial Landmark Localization with Coarse-to-fine Convolutional Network Cascade》
2、《Face Alignment at 3000 FPS via Regressing Local Binary Features》
3、《Deep Convolutional Network Cascade for Facial Point Detection》
4、http://ibug.doc.ic.ac.uk/resources/300-W/
**********************作者:hjimce 时间:2015.11.29 联系QQ:1393852684 原创文章,转载请保留原文地址、作者等信息***************