OpenCV学习:CNN 人脸检测
前言 :前面几篇我们学习了 dlib 的 HOG 人脸检测器、68 个关键点检测、轮廓绘制、表情识别,以及疲劳检测。这些内容全部基于 dlib 的 HOG 检测器。本篇我们再来认识 dlib 的另一种人脸检测器------CNN 人脸检测器。它使用卷积神经网络(Convolutional Neural Network)替代传统的 HOG 特征,对小脸、侧脸、遮挡人脸的检测效果更好,准确率更高,是 dlib 中精度最高的人脸检测方案。
目录
- 一、dlib 的两种人脸检测器
- 二、CNN 人脸检测原理
- 三、模型文件说明
- 四、返回值结构详解
- 五、完整代码
- 六、CNN 与 HOG 对比
- 七、参数调优建议
- 八、总结
一、dlib 的两种人脸检测器
dlib 提供了两种人脸检测器,各有特点:
| 检测器 |
原理 |
优点 |
缺点 |
| HOG 检测器 |
HOG 特征 + 线性分类器 |
速度快,CPU 即可运行 |
对小脸、侧脸、遮挡效果一般 |
| CNN 检测器 |
卷积神经网络 |
准确率高,对小脸、侧脸效果好 |
速度较慢,GPU 上运行更快 |
1.1 HOG 检测器回顾
detector = dlib.get_frontal_face_detector()
这是我们前面几篇用到的检测器,速度快,适合实时场景。但在实际使用中,HOG 检测器也有明显的短板:
- 小脸检测难:图像中占比很小的脸容易漏检
- 侧脸检测差:正脸检测效果最好,侧脸效果明显下降
- 遮挡敏感:人脸被口罩、眼镜、帽子遮挡时容易检测失败
1.2 CNN 检测器
detector = dlib.cnn_face_detection_model_v1("mmod_human_face_detector.dat")
CNN 检测器使用 MMOD(Max-Margin Object Detection) 算法,通过卷积神经网络自动学习人脸特征,能有效解决 HOG 检测器的上述短板。
"MMOD" 是什么? MMOD 是 dlib 作者 Davis King 提出的一种目标检测算法,其核心思想是让预测框与真实框之间的"边缘"最大化,从而提升检测精度。它不需要区域提议(RPN),直接对整张图进行检测,速度比 R-CNN 类算法快。
二、CNN 人脸检测原理
2.1 基本原理
CNN 检测器通过多层卷积和池化操作,自动从图像中提取人脸特征,然后使用全连接层判断每个位置是否包含人脸,并回归出人脸的边界框。
| 层级 |
作用 |
| 卷积层 |
提取边缘、纹理、五官等局部特征 |
| 池化层 |
降低特征图尺寸,减少计算量 |
| 全连接层 |
综合特征进行判别和边框回归 |
2.2 相比 HOG 的优势
| 优势 |
说明 |
| 特征学习能力强 |
神经网络可以自动学习复杂的特征,比人工设计的 HOG 特征更丰富 |
| 多尺度检测 |
通过上采样和不同尺度的特征图,能检测到更小的人脸 |
| 抗遮挡 |
即使部分人脸被遮挡,CNN 仍能通过其他部位识别 |
| 侧脸检测 |
训练数据中包含了大量侧脸样本,检测效果更好 |
2.3 代价
| 代价 |
说明 |
| 计算量大 |
卷积操作比 HOG 计算更耗时 |
| 内存占用高 |
模型文件约 700KB,运行时需要更多内存 |
| 无 GPU 时速度慢 |
纯 CPU 环境下,一帧可能需要几百毫秒 |
三、模型文件说明
3.1 模型下载
CNN 人脸检测需要预训练模型 mmod_human_face_detector.dat,可从 dlib 官方渠道下载。
3.2 模型信息
| 项目 |
说明 |
| 文件名 |
mmod_human_face_detector.dat |
| 大小 |
约 700KB |
| 格式 |
dlib 专用的二进制格式 |
| 训练数据 |
大量带标注的人脸图片 |
| 检测精度 |
比 HOG 检测器高很多 |
3.3 模型调用
detector = dlib.cnn_face_detection_model_v1(r"models\mmod_human_face_detector.dat")
cnn_face_detection_model_v1:dlib 提供的 CNN 人脸检测模型类
- 传入参数:模型文件路径
四、返回值结构详解
4.1 HOG 检测器的返回值
faces = hog_detector(img, 0)
for face in faces:
x1 = face.left() # face 直接就是 rectangle 对象
y1 = face.top()
HOG 检测器直接返回 rectangle 对象列表 ,所以可以直接调用 left()、top() 等方法。
4.2 CNN 检测器的返回值
faces = cnn_detector(img, 0)
for d in faces:
rect = d.rect # 必须先取 .rect 属性
x1 = rect.left() # 再调用方法
y1 = rect.top()
CNN 检测器返回的是 mmod_rectangle 对象列表,每个对象包含:
| 属性 |
说明 |
.rect |
人脸矩形框(rectangle 对象) |
.confidence |
该检测结果的置信度 |
为什么这么设计? 因为 MMOD 算法不仅要给出人脸位置,还要给出置信度,所以用一个包装类来同时携带这两个信息。
4.3 两种检测器对比
| 检测器 |
返回值 |
获取坐标方式 |
| HOG |
rectangle |
直接 face.left() |
| CNN |
mmod_rectangle |
先 d.rect,再 rect.left() |
注意 :如果直接用 CNN 检测器返回的对象调用 left() 会报错。
五、完整代码
import dlib
import cv2
# ==================== 加载 CNN 人脸检测器 ====================
# cnn_face_detection_model_v1 是 dlib 提供的 CNN 检测器
# 它使用卷积神经网络进行人脸检测,比 HOG 检测器精度更高
# 参数:模型文件路径
cnn_face_detector = dlib.cnn_face_detection_model_v1(r"models\mmod_human_face_detector.dat")
# ==================== 读取图片 ====================
img = cv2.imread(r"photo\faces.png")
# 缩小图片:CNN 检测计算量大,缩小图片可以显著加快检测速度
# fx=0.2, fy=0.2 表示宽高都缩小到原来的 20%
img = cv2.resize(img, None, fx=0.2, fy=0.2)
# ==================== 执行人脸检测 ====================
# 参数 2:上采样次数
# - 0:不上采样,速度最快,适合人脸较大的场景
# - 1:上采样一次,适合人脸较小的场景
# - 2:上采样两次,适合人脸非常小的场景,但速度最慢
# 返回值 faces:mmod_rectangle 对象列表,需要通过 .rect 属性获取矩形
faces = cnn_face_detector(img, 2)
# ==================== 绘制人脸框 ====================
for d in faces:
# 从 mmod_rectangle 对象中取出 rect 属性(这才是 rectangle 对象)
rect = d.rect
# 获取人脸矩形的四个边界坐标
left = rect.left() # 左边界 x 坐标
top = rect.top() # 上边界 y 坐标
right = rect.right() # 右边界 x 坐标
bottom = rect.bottom() # 下边界 y 坐标
# 绘制人脸框
# pt1:矩形左上角坐标;pt2:矩形右下角坐标
# color=(0, 255, 0):绿色;thickness=3:线条粗细
cv2.rectangle(img, pt1=(left, top), pt2=(right, bottom),
color=(0, 255, 0), thickness=3)
# 打印置信度(mmod_rectangle 独有的属性)
print(f"检测到人脸,置信度: {d.confidence:.2f}")
# ==================== 显示结果 ====================
cv2.imshow("result", img)
k = cv2.waitKey() # 等待按键,按任意键退出
cv2.destroyAllWindows()
六、CNN 与 HOG 对比
| 对比维度 |
HOG 检测器 |
CNN 检测器 |
| 原理 |
HOG 特征 + 线性分类器 |
卷积神经网络(MMOD) |
| 准确率 |
一般 |
更高 |
| 速度 |
快(几十毫秒) |
较慢(几百毫秒,CPU 环境) |
| 小脸检测 |
一般 |
更好 |
| 侧脸检测 |
一般 |
更好 |
| 遮挡处理 |
一般 |
更好 |
| 返回值 |
直接返回 rectangle |
返回 mmod_rectangle(需 .rect) |
| 返回值附带信息 |
无 |
有置信度(confidence) |
| 模型文件 |
内置(无需下载) |
需要下载 .dat 文件 |
| 适用场景 |
实时检测、CPU 环境 |
高精度场景、GPU 环境 |
七、参数调优建议
7.1 上采样次数
| 上采样次数 |
效果 |
建议场景 |
| 0 |
速度最快,小脸容易漏检 |
人脸较大的近景图片 |
| 1 |
速度适中,精度较好 |
一般场景 |
| 2 |
精度最高,速度最慢 |
人脸很小的远景图片 |
7.2 图像预处理
| 建议 |
说明 |
| 缩小图像 |
CNN 计算量大,缩小图像能显著提升速度 |
| 灰度转换 |
虽然 CNN 可以处理彩色图,但灰度图速度更快 |
| 降低分辨率 |
人脸检测不需要太高的分辨率,适当降低即可 |
7.3 使用场景建议
| 场景 |
推荐检测器 |
| 实时摄像头 |
HOG(速度快) |
| 照片人脸检测 |
CNN(精度高) |
| 小脸/侧脸多的图片 |
CNN(HOG 容易漏检) |
| 无 GPU 环境 |
HOG 或缩小图片后的 CNN |
八、总结
核心函数速查
| 函数 |
用途 |
dlib.cnn_face_detection_model_v1(path) |
加载 CNN 人脸检测模型 |
detector(img, upsample) |
执行检测,返回人脸列表 |
d.rect |
从检测结果中取出矩形对象 |
d.confidence |
获取该检测结果的置信度 |
rect.left() / top() / right() / bottom() |
获取矩形边界坐标 |
cv2.rectangle() |
绘制人脸框 |
两种检测器返回值速查
| 检测器 |
返回值 |
获取坐标方式 |
是否有置信度 |
| HOG |
rectangle |
直接 face.left() |
否 |
| CNN |
mmod_rectangle |
先 d.rect,再 rect.left() |
是(d.confidence) |
注意事项
| 要点 |
说明 |
| 模型文件 |
mmod_human_face_detector.dat 需提前下载 |
| 上采样参数 |
值越大检测越细,但速度越慢 |
| 图片尺寸 |
CNN 计算量大,建议缩小图片加快检测 |
| 返回值差异 |
CNN 检测器需要 .rect 属性获取坐标 |
| 使用场景 |
CNN 精度高,HOG 速度快,按需选择 |
| 置信度 |
CNN 检测器独有的 confidence 属性可用于进一步筛选 |
系列直达