第3章 深度学习检测器:MTCNN 原理详解
P-Net / R-Net / O-Net 结构 · 训练与推理流程
1. MTCNN 概述
MTCNN (Multi-task Cascaded Convolutional Networks) 是一种经典的人脸检测与对齐框架,由三个级联的轻量网络组成:P-Net (Proposal Network)、R-Net (Refine Network) 和 O-Net (Output Network)。它同时输出人脸边界框、关键点(眼睛、鼻子、嘴角)坐标,并利用级联结构实现由粗到精的检测。
核心思想: 通过三个阶段的网络逐步筛选候选框,每个阶段都进行边界框回归和关键点回归,同时利用非极大值抑制 (NMS) 去除冗余框。
2. P-Net / R-Net / O-Net 结构
三个网络均包含卷积层、PReLU 激活和全连接层(或卷积等价),但输入尺寸和深度不同。下表总结了核心差异:
| 网络 | 输入尺寸 | 主要结构 | 输出任务 |
|---|---|---|---|
| P-Net | 12×12×3 | 全卷积 (FCN),3 个卷积层 | 人脸分类 (2)、边界框回归 (4)、关键点回归 (10) |
| R-Net | 24×24×3 | 卷积 + 全连接层,4 个卷积层 + 2 FC | 人脸分类 (2)、边界框回归 (4)、关键点回归 (10) |
| O-Net | 48×48×3 | 更深卷积 + 全连接,5 个卷积层 + 3 FC | 人脸分类 (2)、边界框回归 (4)、关键点回归 (10) |
P-Net 结构示意
3. 训练流程与多任务损失
MTCNN 使用三个任务联合训练:人脸分类、边界框回归、关键点定位。总损失函数为:
L = α · Lcls + β · Lbox + γ · Llandmark其中 α, β, γ 为任务权重(通常 α=1, β=0.5, γ=0.5)。分类损失使用交叉熵,回归损失使用欧氏距离。
训练数据采样策略: 每个 mini-batch 包含正样本(IoU > 0.65)、负样本(IoU < 0.3)、部分样本(0.3 < IoU < 0.65)和关键点样本,比例约为 1:3:1:2。
4. 推理流程
- 图像金字塔构建: 对输入图像进行多尺度缩放,生成图像金字塔,最小人脸尺寸通常设为 12×12。
- P-Net 阶段: 全卷积网络快速扫描所有尺度,输出大量候选框,经 NMS (阈值 0.7) 和边界框回归后保留约 1000 个框。
- R-Net 阶段: 将候选框缩放到 24×24 输入 R-Net,进一步分类和回归,NMS 后保留约 100 个高置信度框。
- O-Net 阶段: 将框缩放到 48×48 输入 O-Net,输出最终人脸框、置信度以及 5 个关键点坐标,最后 NMS (阈值 0.6) 得到最终结果。
5. 关键点回归与代码片段
MTCNN 输出 5 个关键点:左眼、右眼、鼻子、左嘴角、右嘴角。训练时使用归一化坐标。以下为 P-Net 前向推理的简化代码:
# P-Net 推理示例 (PyTorch 风格)
import torch
import torch.nn as nn
class PNet(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 10, 3, 1)
self.prelu1 = nn.PReLU(10)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(10, 16, 3, 1)
self.prelu2 = nn.PReLU(16)
self.conv3 = nn.Conv2d(16, 32, 3, 1)
self.prelu3 = nn.PReLU(32)
# 输出分支
self.cls = nn.Conv2d(32, 2, 1, 1)
self.bbox = nn.Conv2d(32, 4, 1, 1)
self.landmark = nn.Conv2d(32, 10, 1, 1)
def forward(self, x):
x = self.pool1(self.prelu1(self.conv1(x)))
x = self.prelu2(self.conv2(x))
x = self.prelu3(self.conv3(x))
cls = torch.softmax(self.cls(x), dim=1)
bbox = self.bbox(x)
landmark = self.landmark(x)
return cls, bbox, landmark