多任务级联CNN:MTCNN人脸检测与关键点对齐全解析
论文信息
- 标题:Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
- 会议:IEEE Signal Processing Letters 2016
- 单位:中国科学院深圳先进技术研究院、香港中文大学
- 代码:https://kpzhang93.github.io/MTCNN_face_detection_alignment/index.html
- 论文:https://kpzhang93.github.io/MTCNN_face_detection_alignment/paper/spl.pdf
前言
在无约束场景里做人脸检测+关键点定位,一直被姿态、光照、遮挡搞得头疼。传统方法要么检测不准,要么对齐拉胯,MTCNN直接用三级联CNN+多任务联合学习,把检测、框回归、关键点定位串在一起,又快又准,直到今天还是工业界落地标配。这篇就带你把MTCNN从头到尾啃透。
一、核心创新点
MTCNN最狠的三个地方:
- 三级联CNN:从粗到细筛选候选框,速度拉满
- 多任务联合学习:检测+框回归+关键点定位一起训,互相涨点
- 在线难例挖掘:训的时候自动抓难样本,不用手动挑
二、整体框架(从粗到细三级过滤)
MTCNN是图像金字塔+三级CNN的流水线,一步步过滤背景,精修人脸框和关键点。
分析:先把图像做成多尺度金字塔→P-Net快速产候选框→R-Net剔除大量误检→O-Net精修并输出5点关键点,越往后网络越大、筛选越严。
2.1 三级网络分工
- P-Net(Proposal Network)
- 输入:12×12图像块
- 输出:人脸置信度、框偏移量
- 作用:全卷积快速生成候选框,做NMS初步去重
- R-Net(Refine Network)
- 输入:24×24图像块
- 输出:人脸置信度、框偏移量
- 作用:过滤大量非人脸框,精修框位置
- O-Net(Output Network)
- 输入:48×48图像块
- 输出:人脸置信度、框偏移量、5个面部关键点
- 作用:最终精修,输出检测结果+关键点
三、网络结构设计
MTCNN把5×5卷积换成3×3,减少计算、加深网络提升性能,激活用PReLU,比ReLU更软,防止梯度塌陷。
分析:网络越小越靠前,P-Net最轻量最快,O-Net最深最准,三级结构兼顾速度与精度。
四、训练细节:多任务损失+在线难例挖掘
4.1 三大任务损失函数
MTCNN同时训人脸分类、框回归、关键点定位三个任务,加权求和。
(1)人脸分类损失(交叉熵)
Lidet=−(yidetlog(pi)+(1−yidet)(1−log(pi)))L_{i}^{det} = -\left(y_{i}^{det} log(p_{i})+(1-y_{i}^{det})(1-log(p_{i}))\right)Lidet=−(yidetlog(pi)+(1−yidet)(1−log(pi)))
- LidetL_{i}^{det}Lidet:第i个样本的分类损失
- yidety_{i}^{det}yidet:真实标签,人脸=1,背景=0
- pip_{i}pi:网络输出的人脸概率
通俗解释:判断这张图是不是人脸,错了就罚。
(2)框回归损失(欧式损失)
Libox=∥y^ibox−yibox∥22L_{i}^{box} = \left\| \hat{y}_{i}^{box}-y_{i}^{box} \right\|_{2}^{2}Libox=y^ibox−yibox22
- y^ibox\hat{y}_{i}^{box}y^ibox:网络预测的框偏移(左上、宽、高)
- yiboxy_{i}^{box}yibox:真实框偏移
通俗解释:把预测框往真实框拉,越准罚得越少。
(3)关键点定位损失(欧式损失)
Lilandmark=∥y^ilandmark−yilandmark∥22L_{i}^{landmark} = \left\| \hat{y}_{i}^{landmark}-y_{i}^{landmark} \right\|_{2}^{2}Lilandmark=y^ilandmark−yilandmark22
- y^ilandmark\hat{y}_{i}^{landmark}y^ilandmark:预测的5个关键点坐标(共10维)
- yilandmarky_{i}^{landmark}yilandmark:真实关键点坐标
通俗解释:把左眼、右眼、鼻子、左嘴角、右嘴角定位准。
(4)总损失
min∑i=1N∑j∈{det,box,landmark}αjβijLijmin \sum_{i=1}^{N} \sum_{j \in \{det,box,landmark\}} \alpha_{j}\beta_{i}^{j}L_{i}^{j}mini=1∑Nj∈{det,box,landmark}∑αjβijLij
- αj\alpha_{j}αj:任务权重
- βij\beta_{i}^{j}βij:样本掩码,不是该任务样本则为0
权重设置: - P-Net/R-Net:αdet=1,αbox=0.5,αlandmark=0.5\alpha_{det}=1,\alpha_{box}=0.5,\alpha_{landmark}=0.5αdet=1,αbox=0.5,αlandmark=0.5
- O-Net:αdet=1,αbox=0.5,αlandmark=1\alpha_{det}=1,\alpha_{box}=0.5,\alpha_{landmark}=1αdet=1,αbox=0.5,αlandmark=1(关键点更重)
4.2 在线难例挖掘
每批训练里:
- 前向传播算出所有样本的损失
- 取**损失最高的70%**作为难样本
- 只回传这些样本的梯度
通俗解释:自动盯着“难认的脸/背景”学,简单样本直接跳过,又快又准。
4.3 训练数据划分(IoU标准)
- 负样本:IoU<0.3
- 正样本:IoU>0.65
- 部分人脸:0.4≤IoU≤0.65
- 关键点人脸:带5点标注
比例:负:正:部分人脸:关键点 =3:1:1:2
五、实验结果与分析
5.1 在线难例挖掘效果
表格1 网络速度与验证精度
| 分组 | 网络 | 300次前向时间 | 验证精度 |
|---|---|---|---|
| Group1 | 12-Net[19] | 0.038s | 94.4% |
| P-Net | 0.031s | 94.6% | |
| Group2 | 24-Net[19] | 0.738s | 95.1% |
| R-Net | 0.458s | 95.4% | |
| Group3 | 48-Net[19] | 3.577s | 93.2% |
| O-Net | 1.347s | 95.4% |
表格1 出处:MTCNN原文
分析:MTCNN的网络比传统CNN更快、精度更高,轻量化设计见效。
分析:
- 在线难例挖掘:FDDB上涨约1.5%
- 联合关键点学习:同时提升检测和框回归
5.2 人脸检测 benchmark
分析:在FDDB、WIDER FACE的Easy/Medium/Hard子集,MTCNN全面碾压Faceness、ACF、Cascade CNN等SOTA。
5.3 人脸对齐效果
分析:平均误差低于ESR、SDM、TCDCN等方法,5点定位精度顶尖。
5.4 运行速度
表格2 速度对比
| 方法 | GPU | 速度 |
|---|---|---|
| MTCNN | Nvidia Titan Black | 99 FPS |
| Cascade CNN[19] | Nvidia Titan Black | 100 FPS |
| Faceness[11] | Nvidia Titan Black | 20 FPS |
| DP2MFD[27] | Nvidia Tesla K20 | 0.285 FPS |
表格2 出处:MTCNN原文
分析:MTCNN接近100帧,实时性拉满,适合端侧部署。
六、核心代码实现(PyTorch简化版)
importtorchimporttorch.nnasnnimporttorch.nn.functionalasF# P-Net 结构classPNet(nn.Module):def__init__(self):super().__init__()self.conv1=nn.Conv2d(3,10,3,1)self.prelu1=nn.PReLU()self.pool1=nn.MaxPool2d(2,2)self.conv2=nn.Conv2d(10,16,3,1)self.prelu2=nn.PReLU()self.conv3=nn.Conv2d(16,32,3,1)self.prelu3=nn.PReLU()# 输出:人脸分类、框回归、关键点self.conv4_1=nn.Conv2d(32,1,1)# 人脸置信度self.conv4_2=nn.Conv2d(32,4,1)# 框偏移self.conv4_3=nn.Conv2d(32,10,1)# 5点坐标defforward(self,x):x=self.pool1(self.prelu1(self.conv1(x)))x=self.prelu2(self.conv2(x))x=self.prelu3(self.conv3(x))cls=torch.sigmoid(self.conv4_1(x))box=self.conv4_2(x)landmark=self.conv4_3(x)returncls,box,landmark# 在线难例挖掘:取loss前70%defonline_hard_mining(loss,ratio=0.7):num_hard=int(loss.size(0)*ratio)loss_sorted,_=torch.sort(loss,descending=True)threshold=loss_sorted[num_hard]mask=loss>=thresholdreturnmask# IoU计算defiou(box1,box2):x1=torch.max(box1[:,0],box2[:,0])y1=torch.max(box1[:,1],box2[:,1])x2=torch.min(box1[:,0]+box1[:,2],box2[:,0]+box2[:,2])y2=torch.min(box1[:,1]+box1[:,3],box2[:,1]+box2[:,3])inter=torch.clamp(x2-x1,0)*torch.clamp(y2-y1,0)union=box1[:,2]*box1[:,3]+box2[:,2]*box2[:,3]-interreturninter/union七、全文总结
- 三级级联CNN:从粗到细过滤,速度与精度平衡
- 多任务联合学习:检测+框回归+关键点定位一起训,互相增益
- 在线难例挖掘:自动提升模型判别力,不用人工处理数据
- 性能拉满:FDDB/WIDER FACE检测SOTA,AFLW对齐SOTA,近百帧实时
- 工业标配:至今仍是人脸门禁、美颜、抓拍等场景的首选算法
