走近人脸检测(2)——VJ人脸检测器及其发展

人脸检测技术的突破发生在2001年,两位杰出的科研工作者Paul Viola和Michael Jones设计了出了一个快速而准确的人脸检测器:在获得相同甚至更好准确度的同时,速度提升了几十上百倍——在当时的硬件条件下达到了每秒处理15张图像的速度,已经接近实时速度25fps(即25帧每秒)。这不仅是人脸检测技术发展的一个里程碑,也标志着计算机视觉领域的研究成果开始具备投入实际应用的能力。为了纪念这一工作,人们将这个人脸检测器用两位科研工作者的名字命名,称之为Viola-Jones人脸检测器,或者简称为VJ人脸检测器。

VJ人脸检测之所以器能够获得成功,极大地提高人脸检测速度,其中有三个关键要素:特征的快速计算方法——积分图,有效的分类器学习方法——AdaBoost,以及高效的分类策略——级联结构的设计。VJ人脸检测器采用Haar特征来描述每个窗口,所谓Haar特征,其实就是在窗口的某个位置取一个矩形的小块,然后将这个矩形小块划分为黑色和白色两部分,并分别对两部分所覆盖的像素点(图像上的每个点称为一个像素)的灰度值求和,最后用白色部分像素点灰度值的和减去黑色部分像素点灰度值的和,得到一个Haar特征的值。


Haar特征反映了局部区域之间的相对明暗关系,能够为人脸和非人脸的区分提供有效的信息,例如眼睛区域比周围的皮肤区域要暗,通过Haar特征就可以将这一特点表示出来。但是由于提取Haar特征时每次都需要计算局部区域内多个像素点灰度值之和,因此在速度上其并不快,为此VJ人脸检测器引入了积分图来加速Haar特征的提取。

积分图是一张和输入图像一样大的图,但其每个点上不再是存放这个点的灰度值,而是存放从图像左上角到该点所确定的矩形区域内全部点的灰度值之和。


积分图所带来的好处是两方面的,一方面它使得每次计算局部区域像素点的灰度值之和仅需要做4次加减法,与局部区域的大小无关;另一方面它避免了在相同像素点上重复求和,只在最开始计算一次——相邻的窗口有很大的重叠部分,对应的Haar特征也会重叠,如果每次都重新计算像素点的灰度值之和,则重叠部分的计算是重复的。积分图极大地加速了Haar特征的提取,向快速的检测器迈出了第一步。

除了特征提取,分类过程的速度对于检测的速度也至关重要。分类的速度取决于分类器的复杂程度,也即从特征向量变换到类别标签的计算过程的复杂程度。复杂的分类器往往具有更强的分类能力,能够获得更好的分类准确度,但是分类时的计算代价比较高,而简单的分类器虽然计算代价小,但是分类准确度也较低。那么有没有兼顾计算代价和分类准确度两方面的办法呢?当然有,这就是AdaBoost方法。希望计算代价小,所以只用简单的分类器,但是又希望分类准确度高,于是把多个简单的分类器组合起来——聚弱为强,将多个弱分类器组合成一个强分类器,这就是AdaBoost方法的核心理念。通过AdaBoost方法来学习分类器,达到了以更小的计算代价换取同样的分类准确度的目的。

造成人脸检测速度慢的根本原因还在于输入规模过大,动辄需要处理几十上百万的窗口,如果这样的输入规模是不可避免的,那么有没有可能在处理的过程中尽快降低输入规模呢?如果能够通过粗略地观察快速排除掉大部分窗口,只剩下少部分窗口需要进行仔细的判别,则总体的时间开销也会极大地降低。从这样的想法出发,VJ人脸检测器采用了一种级联结构来达到逐步降低输入规模的目的。


具体说来,VJ人脸检测器将多个分类器级联在一起,从前往后,分类器的复杂程度和计算代价逐渐增大,对于给定的一个窗口,先由排在最前面也最简单的分类器对其进行分类,如果这个窗口被分为非人脸窗口,那么就不再送到后面的分类器进行分类,直接排除,否则就送到下一级分类器继续进行判别,直到其被排除,或者被所有的分类器都分为人脸窗口。这样设计的好处是显而易见的,每经过一级分类器,下一级分类器所需要判别的窗口就会减少,使得只需要付出非常少的计算代价就能够排除大部分非人脸窗口。从另一个角度来看,这实际上也是根据一个窗口分类的难度动态地调整了分类器的复杂程度,这显然比所有的窗口都用一样的分类器要更加高效。

VJ人脸检测器通过积分图、AdaBoost方法和级联结构取得的巨大成功对后续的人脸检测技术研究产生了深远的影响,大量的科研工作者开始基于VJ人脸检测器进行改进,这些改进也分别覆盖了VJ人脸检测器的三个关键要素。

特征的改进和变迁

虽然Haar特征已经能够刻画人脸的一些特点,但是相比于人脸复杂的变化模式,VJ人脸检测器所采用的5种Haar特征还是过于简单。光考虑姿态上的变化,人脸可能是斜着的(平面内旋转),也可能是仰着的或者侧着的(平面外旋转),同一个Haar特征在不同姿态的人脸上差异可能非常大,而同时又可能和非人脸区域上的特征更相近,这就很容易在分类的时候引起误判。于是人们开始对Haar特征进行扩展,使得其能够刻画更加丰富的变化模式:

1. 环形的黑白区域划分模式,而不仅仅是上下或者左右型;

2. 旋转的Haar的特征,即将原来提取Haar特征的局部小块顺时针或逆时针旋转45度;

3. 分离的Haar特征,即允许一个Haar特征由多个互相分离的黑白区域来计算,而不要求黑白区域必须处于一个矩形小块中;

4. 对角型Haar特征;

5. 组合Haar特征,即对多个不同的Haar特征进行组合和二值编码;

6. 局部组合二值特征,即在局部对特定的Haar特征按照一定的结构进行组合和二值编码;

7. 带权多通道Haar特征,即一个Haar特征不再只包含黑白两种块,而允许有多种不同形状和不同颜色的块,其中不同的颜色对应着不同的权值,表示像素点上求和之后所占的比重——原来只有1和-1两种,多通道指的是在像素点上求和不仅仅是在灰度这一个通道上计算,而是同时在其它通道上计算(如RGB三个颜色通道;事实上,基于原图计算而来和原图同样大小的任何一张图都可以是图像的一个通道)。

这些扩展极大地增强了Haar特征的表达能力,使得人脸窗口和非人脸窗口之间具有更好的区分性,从而提高了分类的准确度。


除了直接对Haar特征进行改进,人们也同时在设计和尝试其它特征。Haar特征本质上是局部区域像素值的一种线性组合,其相对应的更一般的形式则是不指定线性组合的系数,允许系数为任意实数,这被称之为线性特征——这里的组合系数可以基于训练样例来进行学习,类似于学习分类器参数的过程。稀疏粒度特征也是一种基于线性组合来构造的特征,与线性特征所不同的是,稀疏粒度特征是将不同尺度(将100*100的图像放大到200*200,它和原本大小就为200*200的图像是处于不同的尺度上)、位置和大小的局部区域进行组合,而线性特征只是组合同一个局部区域内的像素值。

LBP特征是一种二值编码特征,其直接基于像素灰度值进行计算,特点是在编码时考虑的是两个值的相对大小,并且按照一定的空间结构来进行编码,局部组合二值特征就是在LBP特征的启发下设计的;从计算上来看,提取LBP特征比提取Haar特征要快,但是Haar特征对于人脸和非人脸窗口的区分能力更胜一筹。简化的SURF特征是一种和Haar特征相类似的特征,但是其计算的是局部区域中像素点的梯度和,并在求和的过程中考虑了梯度方向(所谓梯度,最简单的一种情形就是指同一行上两个不同位置像素值的差比上它们水平坐标的差);SURF特征比Haar特征更为复杂,因此计算代价更高,但是由于其表达能力更强,因此能够以更少数目的特征来达到相同的区分度,在一定程度上弥补了其在速度上的不足。HOG特征也是一种基于梯度的特征,其对一个局部区域内不同方向的梯度进行统计,计算梯度直方图来表示这个区域。积分通道特征和多通道的Haar特征有些类似,但是其使用的通道更加多样化,将通道的概念推广为由原图像变换而来并且空间结构和原图像对应的任何图像。聚合通道特征则在积分通道特征的基础上进一步加入了对每个通道进行下采样的操作,实现局部区域信息的聚合。

在过去十几年的探索过程中,涌现出的特征不胜枚举,这里只选取了部分比较有代表性和反映了人们探索思路的特征进行举例。这里所有列举的特征都有一个共同的特点:都由科研工作者根据自己的经验手工设计,这些特征的设计反映了人们对问题的理解和思考。虽然随着不断的改进,设计出的特征已经日臻完善,但直到现在,人们在特征上的探索还远没有结束。

分类器及其学习方法的改进

分类器能力的强弱直接决定了分类准确度的高低,而分类的计算代价是影响检测速度的一个关键因素,因此,人们探索的另一个方向就是对分类器及其学习方法的改进。

采用AdaBoost方法由弱分类器构建强分类器,这是一个顺序执行的过程,换言之,一旦一个弱分类器被选中,其就必定会成为强分类器的组成部分,不允许反悔,这其实是假设增加弱分类器一定会使得强分类器的分类准确度更高,但是,这个假设并不总是成立。事实上,每次对弱分类器的选择只是依照当时的情况决定,而随着新的弱分类器被增加进来,从整体上来看,之前的选择未必最优。基于这样的想法,出现了允许回溯的FloatBoost方法。FloatBoost方法在选择新的弱分类器的同时,也会重新考查原有的弱分类器,如果去掉某个弱分类器之后强分类器的分类准确度得到了提升,那说明这个弱分类器带来了负面影响,应该被剔除。

VJ人脸检测器中,相级联的多个分类器在学习的过程中并不会产生直接的联系,其关联仅体现在训练样例上:后一级分类器的训练样例一定要先通过前一级分类器。不同分类器在学习时的独立性会带来两方面的坏处:一是在每个分类器都是从头开始学习,不能借鉴之前已经学习好的分类器的经验;二是每个分类器在分类时都只能依靠自己,不能利用其它分类器已经获得的信息。为此,出现了两种改进的方案:链式Boosting方法和嵌套式Boosting方法。两种方案都在学习新一级的分类器时,都考虑之前已经学好的分类器,区别在于链式Boosting方法直接将前面各级分类器的输出进行累加,作为基础得分,新分类器的输出则作为附加得分,换言之,前面各级分类器实际上是新分类器的一个“前缀”,所有的分类器通过这种方式链在了一起;嵌套式Boosting方法则直接将前一级分类器的输出作为新分类器第一个弱分类器的特征,形成一种嵌套的关系,其特点是只有相邻的分类器才会互相影响。还有一种和嵌套式Boosting方法相类似的方案:特征继承,即从特征而不是分类器的角度来关联不同的分类器,具体而言,新的分类器在学习时会先继承前一级分类器的所有特征,基于这些特征学习弱分类器,再此基础上再考虑增加新的弱分类器,这一方案的特点在于其只引入了分类器学习时的相互影响,而在分类时分类器之间仍然是相互独立的。

相关的任务之间往往会相互产生促进作用,相辅相成,而和人脸检测密切相关的一个任务就是特征点定位:预测脸部关键点的位置,这些关键点可以是双眼中心、鼻尖、嘴角等。基于这样一种想法,在2014年出现了Joint Cascade,即把检测人脸所需要的分类器和预测特征点位置的回归器交替级联,同时进行人脸检测和特征点定位两个任务。用特征点定位辅助人脸检测的关键在于形状索引特征的引入,即特征不再是在整个窗口中提取,而是在以各个特征点为中心的局部区域进行提取,这样的好处就在于提高了特征的语义一致性。不同的人脸其对应的特征点位置是不同的,反过来看,也就是说相同的位置实际上对应于脸部的不同区域,那么在相同区域提取的特征实际上表示的是不同的语义,简单地说,就是在拿鼻子去和嘴巴匹配。采用形状索引特征可以很好地避免这个问题,从而增大人脸和非人脸窗口之间的区分性。对于一个给定的窗口,我们并不知道特征点的位置,因此采用一个“平均位置”作为初始位置,即基于标注有特征点坐标的人脸样例集,计算出的每个点坐标的平均值;在平均位置的基础上,我们提取特征预测各个特征点真实的位置,不过一次预测往往是不准确的,就好像跑步的时候我们没法直接从起点跳到终点一样,所以需要不断基于当前确定的特征点位置来预测新的位置,逐步向其真实的位置靠近。这个过程很自然地形成了一种级联结构,从而能够和人脸检测器耦合在一起,形成一种不同模型交替级联的形式。

针对分类器学习过程中的每一个环节,人们都进行了细致而充分的探索,除了上面提到的几个方向,在分类器分类阈值的学习、提升分类器学习的速度等问题上,也出现了很多出色的研究工作。大部分在分类器及其学习方法上进行改进的工作关注的还是Boosting方法(AdaBoost方法是Boosting方法的一个杰出代表)和相对简单的分类器形式,如果能够引入具有更强分类能力的分类器,相信能给检测器带来进一步的性能提升,这一点在后文会有所涉及。

级联结构的演化

分类器的组织结构也是人们关心的一个重要问题,尤其是在面临多姿态人脸检测任务的时候。人脸的姿态是指人脸在三维空间中绕三个坐标轴旋转的角度,而多姿态人脸检测就是要将带旋转的人脸给检测出来,不管是斜着的(绕x轴旋转)、仰着的(绕y轴旋转)还是侧着的(绕z轴旋转)。不同姿态的人脸在表观特征上存在很大的差异,这给检测器带来了非常大的挑战,为了解决这一问题,通常采用分治的策略,即分别针对不同姿态的人脸单独训练分类器,然后组合起来构建成多姿态人脸检测器。

最简单的多姿态人脸检测器就是将针对不同姿态人脸的分类器采用并列式的结构进行组织,其中并列的每一个分类器仍然采用原来的级联结构(我们称这种分类器为级联分类器);在检测人脸的过程中,一个窗口如果被其中一个级联分类器分为人脸窗口,则认为其确实是一个人脸窗口,而只有当每一个级联分类器都将其判别为非人脸窗口时,才将其排除掉。这种并列式的组织架构存在两方面的缺陷:一是造成了检测时间的成倍增长,因为绝大部分窗口是非人脸窗口,这些窗口需要经过每一个级联分类器的排除;二是容易造成整体分类准确度的降低,因为整个检测器分错的窗口包含的是所有级联分类器分错的窗口。

有人设计了一种金字塔式的级联结构,金字塔的每一层对应于对人脸姿态(旋转角度)的一个划分,从顶层到底层划分越来越细,级联的每个分类器只负责区分非人脸和某个角度范围内的人脸。对于一个待分类的窗口,从最顶层的分类器开始对其进行分类,如果其被分为人脸窗口,则送入到下一层的第一个分类器继续进行分类,如果其被分为非人脸窗口,则送入到同一层的下一个分类器继续进行分类,当在某一层上所有的分类器都将其分为非人脸窗口时,就确认其为非人脸窗口,将其排除。金字塔式的级联结构也可以看成是一种特殊的并列式结构,只不过每个级联分类器相互之间有共享的部分,这样最直接的好处就在于减少了计算量,共享的部分只需要计算一次,同时在底层又保留了分治策略所带来的好处——子问题比原问题更加容易,因此更容易学习到分类准确度更高的分类器。

还有一种比较典型的结构是树形的级联结构,从形状上来看其和金字塔式的级联结构是一样的,也是从上往下分类器的数目逐层增多,区别就在于树形的级联结构中没有同一层分类器之间的横向连接,只有相邻层分类器之间的纵向连接,即一个窗口在同一层上不会由多个分类器进行分类,而会直接被送往下一层或者被排除。树形级联结构通过引入分支跳转机制,进一步减少了对一个窗口进行分类所需要的计算量,不过同时也带来了新的问题,分支跳转通常根据姿态估计(估计旋转角度的范围)的结果来进行,而如果姿态估计出现错误,就会出现某个姿态的人脸窗口被送给另一个姿态人脸对应的分类器进行分类的情况,容易导致错误的分类。为了缓解这一问题,出现了允许多个分支同时跳转的设计,从而降低了由于跳转错误而引起分类错误的风险。

分治策略是处理多姿态人脸检测任务最基本的策略,但要同时兼顾速度和分类准确度并不是一件容易的事情,分类能力的增强不可避免地会带来计算代价的增大,如何用更小的计算代价来换取更高的分类准确度,这仍然是一个需要去思考和探索的问题。