3、深度学习人脸检测(一):基于滑动窗口的CNN方法、OverFeat、多尺度检测策略
说实话,在深度学习还没火起来那会儿,做人脸检测基本靠手工特征加分类器。Viola-Jones 框架、HOG + SVM,这些我都调过。但到了 2013 年左右,大家发现卷积神经网络在图像分类上表现太猛了,自然就有人想:能不能把 CNN 也用到检测上?
嗯,这条路最开始走得挺朴素的。说白了就是——把分类器当检测器用。
3.1 从分类到检测:滑动窗口的朴素思想
你想想看,图像分类的任务是判断一张图里有没有人脸。那检测呢?检测不仅要判断有没有,还得告诉我人脸在哪儿。最直接的想法就是:把图像切成很多小窗口,每个窗口送进 CNN 分类器,判断是不是人脸。
这就是基于滑动窗口的 CNN 方法。我在 2014 年刚接触这个思路时,觉得挺笨的,但确实管用。
核心流程:
- 定义固定大小的检测窗口(比如 64×64 像素)
- 在图像上以固定步长滑动这个窗口
- 每个窗口区域送入 CNN 做二分类(人脸 / 非人脸)
- 收集所有被判定为人脸的窗口位置
- 用非极大值抑制(NMS)合并重叠的检测框
这里有个坑,我踩过。窗口大小和步长怎么选?窗口太小,大脸检测不到;窗口太大,小脸又漏了。步长设小了,计算量爆炸;步长设大了,定位精度下降。我曾经在一个项目里为了调这两个参数,跑了整整两天的实验。
我的经验:步长一般设为窗口尺寸的 10%~20%。比如 64×64 的窗口,步长取 8~12 像素比较合理。这样既不会漏检太多,计算量也能接受。
3.2 多尺度检测策略:解决尺度变化问题
人脸在图像里的尺寸变化太大了。近景人脸可能占几百像素,远景人脸可能只有几十像素。固定窗口肯定不行。
怎么办?两个思路:
- 图像金字塔:把输入图像缩放到多个尺度,在每个尺度上跑固定窗口
- 特征金字塔:在 CNN 的不同层上做检测,利用网络自身的多尺度特征
2013 年那会儿,大家主要用图像金字塔。我做过一个实验,把一张 1920×1080 的图像缩放了 8 个尺度,每个尺度跑一遍滑动窗口。结果呢?一张图跑了 40 多秒。嗯,那时候 GPU 也没现在这么强。
| 尺度策略 | 优点 | 缺点 | 典型应用 |
|---|---|---|---|
| 图像金字塔 | 实现简单,检测精度高 | 计算量大,内存消耗高 | OverFeat、早期 CNN 检测 |
| 特征金字塔 | 计算共享,效率高 | 深层特征分辨率低,小目标差 | SSD、FPN |
| 多尺度训练 | 模型自适应尺度变化 | 训练复杂度高 | MTCNN、RetinaFace |
图像金字塔的缩放因子一般取 0.7~0.9。我习惯用 0.8,这样每层尺度变化不大,检测框的连续性比较好。
3.3 OverFeat:滑动窗口 CNN 的集大成者
2013 年,纽约大学的 Sermanet 等人提出了 OverFeat。说实话,这篇我反复读了好几遍。它把滑动窗口、多尺度检测和 CNN 整合到了一个框架里,算是那个时代的标杆。
OverFeat 的核心贡献有三个:
- 全卷积化:把 CNN 最后的全连接层改成卷积层,这样网络可以接受任意尺寸的输入
- 多尺度推理:对输入图像构建金字塔,每个尺度都过一遍网络
- 联合训练:分类、定位、检测三个任务共享特征提取层
注意:OverFeat 的全卷积化思想后来被广泛应用。但它的多尺度推理是在测试时做的,训练时还是用固定尺寸。这意味着训练和测试的分布其实不完全一致。我在复现时发现,如果训练时加入多尺度数据增强,检测效果能再提升 2~3 个点。
OverFeat 的检测流程是这样的:
- 输入图像经过 5 个卷积层提取特征
- 在最后一层卷积特征图上,用滑动窗口做分类和回归
- 每个空间位置预测一个类别分数和边界框偏移
- 在不同尺度上重复这个过程
- 最后合并所有尺度的检测结果
我记得当时在 LFW 数据集上跑 OverFeat,检测率能到 90% 以上。虽然现在看这个数字不高,但在 2013 年,这已经是碾压传统方法了。
3.4 知识结构图:滑动窗口 CNN 检测流程
下面这张图展示了基于滑动窗口的 CNN 人脸检测的完整流程。我把它画出来,方便你理解各个模块之间的关系。
3.5 滑动窗口 CNN 的局限性
虽然滑动窗口 CNN 在当年取得了不错的效果,但它的缺点也很明显。我总结了几点:
- 计算冗余:相邻窗口有大量重叠区域,CNN 重复提取特征,效率很低
- 窗口数量爆炸:一张 1080p 图像,如果步长 8 像素,缩放 6 层,窗口数量轻松超过 10 万
- 定位精度差:滑动窗口的步长决定了定位的离散程度,步长越大,定位越粗糙
- 难以处理极端宽高比:固定窗口假设人脸是正方形的,但实际人脸可能有倾斜、遮挡
一个真实案例:我曾经在一个安防项目中用滑动窗口 CNN 检测监控画面中的人脸。1080p 的视频流,每帧要处理 15 万个窗口,在 GTX 1080 上只能跑到 3 FPS。后来我改用全卷积网络,直接回归检测框,速度提升到了 25 FPS。嗯,这就是技术迭代的力量。
3.6 从滑动窗口到全卷积的演进
OverFeat 的一个重要贡献是证明了全卷积化的可行性。为什么全卷积能提速?
你想想看,滑动窗口的本质是在输入图像的不同位置重复计算相同的卷积操作。而全卷积网络一次前向传播就能计算出所有位置的响应。说白了,就是把循环计算变成了矩阵运算,GPU 最喜欢这种模式了。
OverFeat 的做法是:
- 把最后三个全连接层改成 1×1 和 3×3 的卷积层
- 这样网络可以接受任意尺寸的输入
- 输出特征图上的每个空间位置对应一个检测结果
这个思路后来被 YOLO、SSD 等单阶段检测器继承和发展。可以说,OverFeat 是连接传统滑动窗口和现代全卷积检测器的桥梁。
我的建议:如果你想深入理解现代人脸检测算法,一定要把 OverFeat 的吃透。它虽然简单,但包含了检测任务的所有核心要素:多尺度、滑动窗口、回归、NMS。后面的算法再花哨,底层逻辑都没变。
3.7 本章小结
基于滑动窗口的 CNN 方法虽然现在看来有些笨重,但它奠定了深度学习人脸检测的基础。OverFeat 作为这个时期的代表作,提出了全卷积化、多尺度推理等关键思想,影响了后续几乎所有检测算法。
在实际项目中,如果你需要快速验证一个检测思路,滑动窗口 + 轻量 CNN 仍然是一个可行的方案。但如果是生产环境,我建议直接上全卷积网络或者基于锚点的检测器。毕竟,效率就是生命。