人脸检测的一些坑

做了大概2个多月人脸检测,从查最近三年的论文到确定技术路线,再到实现其中的几篇,遇到了不少坑。这些坑都是一些小细节,这种小细节在论文里面基本都是一笔带过或者根本就没说,而国内外的一些博客和问答网站上,又基本没有给出过太好的答案。在此总结一下,同时也希望给在做或者准备做这方面的人一些有用的提示。

 

1.怎样选择合适的算法做人脸检测

最近人脸检测算法的流派包括三类以及这三类之间的组合:viola-jones(后面简称vj)框架,dpm和cnn。如果准备搞学术刷性能,建议搞dpm和cnn这两个,尤其是cnn目前比较有搞头。如果是为了在服务器上搭一个性能不错但是也要兼顾一些速度的人脸检测服务,建议搞cnn和vj这两个,因为dpm实在是太慢了,如果是dpm+cnn更是慢上加慢。相比之下,单独使用cnn就可以获得很不错的性能,同时如果有gpu服务器的话,速度也尚可。vj的话,性能一般但是速度是没问题的。如果准备在移动端or嵌入式上使用(就是计算能力,内存,甚至代码和模型大小都有限制),而且还想实时的话,基本上就只能选vj了,当然特征不一定要用haar。hog,lbp,pixel-difference以及一系列手工设计的特征都可以一战。其实如果待检测的人脸没有特别大幅度的姿态变化,传统的vj就够了,新的方法主要还是在表达能力(说白了就是能检测到更多千奇百怪的人脸)上增强了很多。如果你的人脸没那么奇怪(例如:严重遮挡、旋转的特别厉害、特别不清晰等等),用vj也就够了。

 

2.怎样收集负样本图片

没有人脸的那种风景照片基本是不行的。说白了人脸检测器就是把一张图片中的人脸和背景区分开,所以负样本也应该是从带有人脸的图片中收集。例如像aflw这种公开数据集中,人脸比较小,背景变化也比较大,就可以用一些确定没有人脸的图片遮挡住一张图片中的人脸位置,这张图片就可以当作负样本图片了。当然,大多数公开数据集并没有把一张图片中的所有人脸标注出来,所以多数情况下还需要自己把上述方法处理过的图片再过一下。

 

3.在每个stage怎样生成负样本

我目前在搞基于vj和cnn的两套结构。这个问题主要存在于vj框架中,因为vj框架在每个stage开始训练之前,都需要利用当前的人脸检测器,把正样本过一遍,留下true positive,然后再从负样本图片中选取一些被错分的区域(patch),即false positive,用作补充,和目之前stage被错分的负样本放在一起,作为当前stage的负样本。我查阅了一些论文和网上的资料,再加上我个人分析,一般来讲,合理的负样本生成策略如下:

(1)随机选取一张负样本图片

(2)从负样本图片中随机选取一个区域(left,top,size)

(3)将(2)中的区域送入当前的分类器,如果被错分成正样本,就保留下来,用于接下来stage的训练。

(4)重复(1)(2)(3)直到收集到足够的用于接下来stage训练的负样本。一般来讲会生成和当前stage剩下的正样本等量的负样本。例如在第6个stage,只剩下10000正样本,那么收集的负样本数量也是10000。

再次申明,上面是我的个人理解,如果有问题欢迎指正or讨论。乍一看上面的策略好像没啥问题,但是当stage越来越多,当前分类器的fpr越来越小时,被错分的负样本就会越来越少,生成负样本也越来越难。例如:当前fpr=1e-5,如果正样本还剩10000,那么要生成出等量的负样本,就需要测试10e4/1e-5=10e9(10亿)。所以训练到最后,大部分的耗时都在生成负样本,而不是训练weak learner了。对于这种情况,我目前找的策略如下:

(1)尽量多收集负样本图片。

(2)如果内存允许,尽量多的把负样本图片读取进内存,这样在读取图片的时候会快很多,和运行分类器相比,磁盘读取和图片的解码就慢多了。

(3)如果cpu允许,openmp使劲开多线程。

 

4.训练集、验证集和测试集

vj的原论文和soft-cascade的论文中都提到,要把数据分成train set, validate set和test set。train set用于训练,validate set用于在每个stage训练完成后,测试当前分类器的tpr,fpr。test set用于最后测试分类器的实际性能。但在实际操作中,validate set这部分很少有人做,而缺少这部分训练出的分类器性能也是可以接受的,所以可以不用拘泥于这部分,毕竟数据那么有限,还是多放一些数据训练吧。

 

5.程序中的坑

6.如何测试程序正确性

你可能感兴趣的:(人脸检测的一些坑)