tags: 人脸检测;face detection;S3FD
论文题目《S3FD: Single Shot Scale-invariant Face Detector》
作者:Shifeng Zhang Zhen Lei 中科院自动化研究所 2017
代码地址:https://github.com/sfzhang15/SFD
基于anchor的目标检测算法在复杂场景和目标数量较多的情况下,表现依然较为鲁棒,但是当目标尺度很小的时候,检测效果就有很大幅度的下滑。主要原因有以下几点:
基于anchor的检测框架容易漏掉小型和中型的人脸。通常,在开始检测的时候,原始图像已经经过网络进行了多次pooling,这就会导致原始图像中的小型人脸和中型人脸特征在后续的特征传递中丢失。比如下图:
从图中可以看到,在某特征层进行检测的时候,生成的anchor为蓝色框,感受野为黑色框,但是需要检测的人脸是绿色框,这就导致了三者的不匹配,从而anchor无法真实检测到人脸。
在目标检测中,通常设置的anchor值为离散值,比如16,32, 64等,但是人脸通常是连续的,比如一张图像中可能存在各种大小不同的人脸,人脸大小的变化范围可能是从16到64之间任何值,那么用这样离散的anchor值去检测多尺寸的人脸,势必会发生漏检的可能。
从图上可以看到,人脸的变化是连续值,但是设定了anchor之后,只能够检测anchor值附近某一个区间内的人脸,而在anchor两个值之间的人脸,极有可能被漏掉。
当然,为了检测到小人脸,大可以在浅层设置密集的anchor来增加检测小脸的概率,但是会同时引入更多的负样本。如下图:
从图中可以看到,如果将anchor设置的很小,那么为了检测到小脸,会引入更多的负样本。
综合以上三种因素,作者提出来三种对应的解决方案:
前面说过,基于anchor的人脸检测器在人脸尺度较小的情况下很容易漏检。这里作者采用了在更大范围的特征图上进行检测的策略。比如SSD等检测器是从conv4-3之后开始进行检测,原始图像经过了3次pooling之后到这层时,stride=8。而这里作者从conv3-3开始检测,那么原始图像仅仅进行了2次pooling,相对来说,小的人脸特征还在,不至于被漏掉。同时,为了检测更大的脸,对网络进行了更多次的pooling,从而使最终的stride=128。这就保证了不同尺度的人脸都能够检测到。
另外,根据有效感受野和等比例区间原则,将anchor的变化设置为从16到512。下面是具体的实现过程:
1. 网路结构设计
基础网络:这里采用了VGG16的基础结构,保留conv1到pool5,删除了其它层。同时在pool5之后又增加了3个conv层和3个pooling层。
检测网络:检测层则从conv3_3开始到conv5_3,加上conv_fc7, conv6_2, conv7_2,共有6种不同的尺度,对应stride为4,8,16,32,64,128。
标准化层:考虑到conv3_3,conv4_3, conv5_3层的特征相比后面检测层包含更多的细节信息,而且尺度也不相同,因此使用了L2标准化来将这些特征层的范数规范至10,8,5。缩放系数为超参数,随网络一起训练。(这里不是很理解,为什么后续就不需要规范?)
预测层:由于网络从conv3_3就开始检测,该层的特征图也比较大,那么该层的anchor所对应的负样本会非常多。因此为了解决这个问题,特意对这层的预测网络进行了特殊处理。对于一般的检测结果而言,通常为6个预测值,分别代表4个位置或位置与宽高结合的回归值与2个分类结果。但是该层不能仅仅这样简单处理,因为样本相差太悬殊,训练时候很难平衡。所以这里在预测的时候,在conv3_3与结果之间又加入了max-out层进行预测,这样可以使结果更加可靠。关于max-out,这篇博客讲的很好,可以看下。
损失层:网络用的损失函数为softmax loss + smooth L1
2. anchor尺度设计
网络在每一个检测层都对应一种特定尺度的anchor,而anchor的大小和对应的感受野之间的大小如下:
这里,所有的anchor采用的都是方形,长宽比为1:1。
有效感受野
感受野指的是原始图像经过各种卷积池化操作之后,得到的特征图中某个像素点对应于原图中相应某个区域的大小。关于感受野,这里有一篇很好的讲解:感受野。分为两种:理论感受野 和 实际感受野。
理论感受野 指的是通过理论计算,特征图中的某个像素点对应到原图时所对应的大小。而实际感受野 指的是原图中对特征图该像素点起重要影响的像素点集合。两者的对比如下图所示:
上图中,某一像素的理论感受野指的是图中的整个黑色区域,这是根据理论计算得到的。而实际感受野是图中的亮色区域。因为图中的亮色区域在不断的卷积池化过程能够保留大部分信息,而边缘黑色区域的信息则在卷积池化中丢失了。算法主要关注的是实际感受野,但理论感受野便于分析。对比示例,可以看到,实际感受野为蓝色虚线内,所以检测的时候,应该检测蓝色区域内的红色框,而不是对整个黑色框进行检测。
等比例间隔原则
从前图中可以看到,某层特征所对应的stride决定了其产生的anchor的感受野的大小。比如对conv3_3而言,其stride为4,而anchor设置为16*16,正好anchor的大小为stride的4倍。这样的好处在于,可以保证不同尺度的anchor对应到原始图像上都有相同的密度,从而不同尺度的人脸就能够匹配数量相同的anchor。
在训练时候,需要判断某张脸所匹配的anchor是什么,从而利用这个最匹配的anchor去回归人脸框。而当前的检测算法所采用的anchor匹配策略是根据IOU来衡量的。比如anchor与某个人脸框的IOU大于0.5,则该anchor就匹配这个人脸。但是,人脸的变化是连续的,而anchor的设定是离散的。那就说明,有的人脸不会匹配到足够好的anchor。同样还是前面的图:
从图中可以看到,不同尺度的人脸所匹配的anchor数量大约为3个(均值)。但是在人脸大小变化的整个范围内,只有当人脸大小与所设置的anchor大小相近的时候,所匹配的anchor数量是最多的,而其余的时候,匹配的anchor数量减少很多。这就导致了处于这个大小区间内的人脸不容易检出。
可以采用两种方式来解决这个问题:
阶段1:将IOU阈值从0.5减少到0.35,从而增加每张脸所匹配的anchor数量
阶段2:在经过了上面步骤之后,还是有很多脸没有匹配到足够的anchor(如下图所示)。此时可以将与这些人脸IOU阈值大于0.1的anchor挑出来,将其排序后选取前N个anchor来作为这些脸所匹配anchor。而N的值为第一阶段算出来的每个脸匹配anchor的均值。
经过这样的步骤,就可以保证每张人脸都能够匹配到足够数量的anchor,便于后续进行检测。
人脸检测中,其实绝大部分anchor所对应的样本为负样本(背景),主要原因在于对小脸进行检测时,其所对应的特征图一般较大(stride较小),那么生成anchor的时候会产生大量的背景框,如下图统计结果:
对于一个640*640大小的图像而言,conv3_3产生的anchor数量为25600(640/4*640/4)。占总数的75%。而且,这些anchor中负样本占主要部分,如果直接用这些样本进行训练,那么最终会导致假阳率很高。
为了解决这个问题,这里对conv3_3层的anchor预测引入了max-out的方式。从网路结构图中可以看到,conv3_3的anchor,其在预测的时候需要增加一个max-out层,该层将预测 N m N_m Nm个结果,最终取得分最高的作为背景预测值。
1.数据增强
所采用的数据集为WIDER FACE。通过增加颜色抖动,随机裁剪,水平翻转的等扩充技术对原始图像进行了进一步扩充。
2. 损失函数
损失函数为:
各项内容代表的意义与这里一致。
3. 难例挖掘
主要解决样本不平衡问题。这里不再是随机选取负样本来与正样本组合成对,而是通过将他们的损失值进行排序,选择出最大损失所对应的正负样本作为训练样本,比例为1:3。
4. 训练细节
网络将VGG16的pool5之后的全连接层换成了卷积层,并增添了卷积层。在对conv_fc6和conv_fc7进行初始化时,是对原始VGG16的全连接的fc6和fc7进行了参数采样来初始化对应的卷积层的。
作者就提出的三种解决方法进行了分开对比,并与Faster-RCNN和SSD进行了比较,在Wider Face数据集上的对比如下:
小脸检测结果主要看hard这项。可以看到,作者从conv3_3开始检测能够极大的提升准确率。这项的提升也是最明显的。而采用对等间隔原则和max-out的方法,分别都有了进一步提升。
在AFW、PASCAL、FDDB、WIDER FACE数据集上算法与其他算法的对比如下:
其实利用anchor的方法检测多尺度小人脸,从特征金字塔上切入的话,很容易想到从浅层开始检测,但是如何解决浅层检测所带来的anchor数量剧增的问题是比较关键的。作者这里使用的方法是很有启发性的。不得不说,膜拜!
S3FD: Single Shot Scale-invariant Face Detector