算法优化——如何将人脸检测的速度做到极致
2016-06-30 21:08
465 查看
零、检测与识别
首先要区分两个概念“人脸检测/face detection”和“人脸识别/face recognition”。“人脸检测”是从图像中确定人脸的位置和大小,如下图所示;“人脸识别”是识别图像中的人脸是张三还是李四,是身份识别。人脸检测是一个非常经典的问题,很多人认为这是一个“已经解决”了的问题。人脸检测最经典的方法是Haar+AdaBoost。采用开源的Haar+AdaBoost实现(如OpenCV中的训练和检测程序),我们可以很容易的训练一个还算不错的人脸检测器。
但是,一旦将人脸检测技术投入实际应用,一系列问题便会冒出来。如(1)误检(把非人脸的物体当作人脸)较多,非人脸图像当作人脸送入后续算法,会引起一系列不良后果。(2)漏检问题,例如戴墨镜、大胡子、逆光条件、黑种人、倾斜姿态较大的脸无法检测到。(3)速度问题,虽很多人脸检测算法的速度已经很快,但在一个人脸分析(如人脸识别)系统中,人脸检测步骤的计算量往往超过50%。大部分检测算法采用窗口扫描的方式,窗口数目巨大,所以计算量居高不下。
下面介绍一下设计Boosting人脸检测方法的一些技巧:
一、特征设计
特征设计是重中之重,如果特征从原理上就是计算量大,后面无论如何优化,都很难降计算量。先说Haar特征,毫无疑问Haar特征用在人脸检测里具有里程碑式的意义。但现在看Haar特征,会发现它有一些明显的缺点。Haar特征是一种很弱的特征,这意味着需要很多特征组合在一起才能构成强分类器,对提升速度不利;如果正样本分布比较分散比较难区分时(例如正面侧面人脸全放进去),用这种弱特征分类会比较吃力。此外,在Haar特征的实现中,为了解决亮度归一化问题,需计算像素值的平方和(square sum),平方和需要64位整数来存储;还需要开方(sqrt)运算。64位整数运算和开方运算,对很多嵌入式系统来讲,都是高计算量操作。
HOG特征是一个描述能力特别强的特征,也可以用在人脸检测上。HOG特征需要计算梯度的方向和长度。计算方向需要ctan三角函数(可用查表法加速)以及开方操作。统计直方图时,为了效果好,需要soft voting加权投票。因此HOG是强描述特征,但特征提取的计算量较大。
LBP是一个好特征,描述能力强,特征提取仅需要逻辑运算和加法运算,值得推荐!LBP依然有吐槽点。如果你实现Multi-Block LBP,需要积分图来加速。积分图是很多算法的加速武器,但构建积分图时,很难用SIMD(单指令多数据)指令优化。
前面三种特征的对比分析,是为了说明好的特征要表达能力强且计算简单。很多二值特征(Binary feature)符合这一特点。二值特征还可以天然地解决图像的亮度变化问题,不需要事先对图像进行亮度均衡化。(例如使用Haar+AdaBoost检测人脸前,先对图像做直方图均衡化再检测,效果会好很多。)
二、样本
很多论文中会洋洋洒洒地介绍算法的先进性,但很少有论文分析样本对结果的影响。可能分析样本显得很工程化很low吧。而描述样本在高维特征空间的分布,应该是很多模式识别问题的核心问题。好,不谈理论谈经验。样本选择是一般人不提的重要事情。如果你用手机自拍照片训练人脸检测器,应用在视频监控中,一般效果不会太好;如果你对所有人脸样本进行人脸对齐,要求双目绝对水平,那么训练出的分类器速度会比较快,但不能处理人脸姿态变化。即人脸样本越单一,训练出的分类器的速度会越快,但正确检测率低;如果样本复杂,速度变慢但检测率升高。如何平衡样本的复杂性和检测速度,需要针对具体应用斟酌。
此外负样本也很关键。如果你从几千张风景图里抠图作为负样本进行训练,那么基本上会overfitting,即训练时误检率很低,但实际应用时误检率比较高。要准确刻画非人脸图像,负样本的规模一定要大,负样本的内容一定要多样化!我们平时训练用的负样本图像大约有20GB,包含各种内容的图像。
三、分类器训练
这个可说的不多,Boosting方法就那些,可以尝试各种Boosting方法和各种参数,找到合适的。四、代码优化:
消灭重复计算 |
int b1 = pixels[y*step + x] - pixels[y*step + x + 1]; int b2 = pixels[y*step + x + 2] - pixels[y*step + x + 3];
可以写为
int offset = y *step + x; int b1 =pixels[offset] - pixels[offset+1]; int b2 = pixels[offset+2] - pixels[offset+3];
展开循环 |
利用SIMD指令 |
多核并行运算 |
举给例子:如果两个矩阵相加,按像素进行并行操作,加速效果会很糟糕;如果按行并行,效果会好很多,但不要按列并行!
定点化 |
GPU优化 |
五、未来展望
到目前为止,Boosting方法在人脸检测中依然具有明显的速度优势。但基于深度学习的目标检测方法进展迅速,不容小视。深度学习的方法可以很容易地获得非常高的准确率,如在FDDB人脸检测评库上,传统方法能达到85%准确率就非常高了,但深度学习方法可以轻松超过90%,甚至超过95%。如果想兼顾速度和准确率,传统方法和深度学习的方法结合也许是一个思路,现在已经有一些这样的尝试了。此外,CNN专用硬件应可以弥补深度学习方法的劣势。相关文章推荐
- MySQL 优化
- 书评:《算法之美( Algorithms to Live By )》
- Google排名优化的几个影响因素
- 动易2006序列号破解算法公布
- DB2优化(简易版)
- Mysql limit 优化,百万至千万级快速分页 复合索引的引用并应用于轻量级框架
- C#中尾递归的使用、优化及编译器优化
- 对优化Ruby on Rails性能的一些办法的探究
- C#递归算法之分而治之策略
- 优化Ruby脚本效率实例分享
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- Asp编码优化技巧
- 如何监测和优化OLAP数据库
- mysql -参数thread_cache_size优化方法 小结
- C#算法函数:获取一个字符串中的最大长度的数字
- 深入学习SQL Server聚合函数算法优化技巧
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二