MTCNN 《 Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks 》,采用级联 CNN 结构,通过多任务学习,同时完成–人脸检测和人脸对齐,输出人脸的 BoundingBox 和人脸 5 个关键点(双眼、鼻子、双嘴角)的位置。
MTCNN 在提出时在 FDDB 、 WIDER FACE 和 AFLW 数据集上取得了当时(2016 年 4 月) 的SOTA速度又快,现在仍被广泛使用作为人脸识别的前端,如 InsightFace 和 facenet。
论文提到,MTCNN 的效果主要来自 3 个主要原因:
Tips:个人建议在看这篇文章的时候,对照着 pytorch 的实现代码理解,尤其是里面的 try_mtcnn_step_by_step.ipynb 非常有助于理解整个文章的流程。
Inference 阶段
图像金字塔
P-Net
R-Net
O-Net
PS: 在 P-Net 和 R-Net 中,都没有输出 Facial landmark localization,只在最终的 O-Net 中输出了 。
MTCNN 方法主要为:图像金字塔+3 个级联 CNN 网络。
算法流程图如下所示:

图像金字塔( image pyramid ) :主要是保证了多尺度的人脸数据的训练和检测(其中也有很多的 trick)
Q:请问为什么输入 PNET 为什么是图片金字塔吗?能简单解释一下吗? A:我的理解是:train 的时候并不是图片金字塔,而是在 predict 或者说 inference 时是图片金字塔,因为训练的时候每个样本大小是 12×12,而 predict 时是原图大小可能很大比如 1920×1080,在图片中人脸占用像素可能 200×200,这样使用训练好的模型去识别就识别不了,这时如果缩小图片使得人脸大概是 12×12 左右的话,就可以识别了。而由于我们并不知道实际原图中人脸大小是多少,也就不知道图片需要缩小多少倍,所以会按不同的比例缩放多种尺寸,形成图片金字塔,这样总有几种尺寸可以满足要求
3 个阶段的级联的 CNN 网络作为主要的任务网络分别是P-Net,R-Net,O-Net,三个网络级联前一个网络的输出是后一个网络的输入,从而完成对人脸由粗到细(coarse-to-fine) 的检测。并且可以看到随着网络层数逐渐加深,输入图像的尺寸(感受野)在逐渐变大 12→24→48,最终输出的特征维数也在增加 32→128→256,意味着利用的信息越来越多。

其中 P-Net:Fast Proposal Network , R-Net:Refinement Network , O-Net:Output Network , MP:max pooling , Conv:convolution
该网络的主要任务是获得人脸区域的候选窗口和边界框的回归向量。并用该边界框做回归,对候选窗口进行校准,然后通过非极大值抑制(NMS)来合并高度重叠的候选框。该网络是整个网络的起始输入端,是一个**全卷积神经网络( FNC ),前向传播得到的特征图在每个位置是个 32 维的特征向量,用于判断每个位置处约 12×12 大小的区域内是否包含人脸,如果包含人脸,则回归出人脸的 Bounding Box,进一步获得 Bounding Box 对应到原图中的区域,通过NMS **保留分数最高的 Bounding box 以及移除重叠区域过大的 Bounding Box。
P-Net 的网络结构是一个全卷积神经网络的网络结构。
FCN(全卷积神经网络)
全卷积网络就是去除了传统卷积网络的全连接层,然后对其进行反卷积对最后一个卷积层(或者其他合适的卷积层)的 feature map 进行上采样,使其恢复到原有图像的尺寸(或者其他),并对反卷积图像的每个像素点都可以进行一个类别的预测,同时保留了原有图像的空间信息。同时,在反卷积对图像进行操作的过程中,也可以通过提取其他卷积层的反卷积结果对最终图像进行预测,合适的选择会使得结果更好、更精细。
输入(Input) 可以是任意大小的图片
输入是一个\( 12\times 12 \)大小的图片,所以训练前需要把生成的训练数据(通过生成 bounding box,然后把该 bounding box 剪切成\( 12\times 12 \)大小的图片),转换成\( 12\times 12\times 3 \)的结构。
1、P-Net 的层数很浅,主要作用是尽可能多的把人脸框都选进来,宁愿错误拿来好多个,也不丢掉一个。
2、P-Net 的训练数据主要由 4 部分组成:其中比例为\( pos:part:neg:landmark=1:1:3:2 \)
3、训练数据的由来:
pos,part,neg 是随机和人脸的数据裁剪得到的,裁剪图片与人脸框最大的 iou 值大于 0.65 的为 pos 图像,大于 0.4 的为 part 图像,小于 0.4 的为 neg 图像,landmark 截取的是带有关键点的图像。
这四种图像都 resize 成\( 12\times 12 \)作为 PNet 的输入,通过 P-Net 得到了是否有人脸的概率[batch,2],人脸框的偏移量[batch,4],关键点的偏移量[batch,10]。
4、四种不同数据的训练方式:
该网络的主要任务还是通过边界框回归和 NMS 来去掉那些 false-positive 区域。该网络是单纯的卷积神经网络(CNN),先将 P-Net 认为可能包含人脸的 Bounding Box 双线性插值到 24×24,输入R-Net,判断是否包含人脸,如果包含人脸,也回归出 Bounding Box,同样经过 NMS 过滤。只是由于该网络结构和 P-Net 网络结构有差异,多了一个全连接层,所以会取得更好的抑制 false-positive 的作用。
该网络的主要任务是对人脸区域进行了更多的监督,同时输出 5 个人脸 landmark。该网络也是单纯的卷积神经网络(CNN),该网络比R-Net又多了一层卷基层,所以处理的结果会更加精细。作用和R-Net层作用一样,并输出 5 个人脸 landmark。
人脸的检测可以看作是一个局部二分类问题(该区域存在/不存在人脸)。
MTCNN 采用的是交叉熵作为 loss:
\( L_i^{det}=-(y_i^{det}log(p_i)+(1-y_i^{det})(1-log(p_i))) \)
其中,\( p_i \)为该网络表示样本\( x_i \)是人脸的概率,\( y_i^{det}\in {0,1} \)为该区域的真实标签。
MTCNN 通过每个样本\( x_i \)的欧氏距离作回归损失:
\( L_i^{box}=||\hat y_i^{box}-y_i^{box}||_2^2 \)
其中,\( \hat y_i^{box} \)为对于第\( i \)个样本该网络预测得到的回归目标,\( y_i^{box} \)为第\( i \)个样本实际的真实的背景坐标。其中\( y_i \)为(左上角 x,左上角 y,长,宽)/(left,top,height,width) 组成的四元组。
在训练过程中,\( \hat y_i^{box} \)和\( y_i^{box} \)的交并集 IoU( Intersection-over-Union ) 比例为:
| 训练样本比例 | 负样本:正样本:part 样本:Landmark = 3:1:1:2 |
|---|---|
| 非人脸 | (0,0.3) |
| Part 人脸 | (0.4,0.65) |
| 人脸 | (0.65,1.00) |
| Landmark | (0.3,0.4) |
与 bounding box regression 任务类似人脸特征点定位也是一个回归问题采用同样的欧式距离作为 loss:
\( L_i^{landmark}=||\hat y_i^{landmark}-y_i^{landmark}||_2^2 \)
其中,\( \hat y_i^{landmark} \)为对于第\( i \)个样本该网络预测得到的回归目标,\( y_i^{landmark} \)为第\( i \)个样本实际的真实的坐标。人脸特征点包括(left eye, right eye, nose, left mouse corner, right mouse corner),即\( y_i^{landmark}\in \mathbb{R}^{10} \).
整个训练可以表示为:
\( min\sum _{i=1}^N\sum _{j\in {det,box,landmark}}\alpha _j\beta_i^jL_i^j,\beta_i^j\in{0,1} \)
\( P-Net,R-Net: (\alpha _{det}=1,\alpha _{box}=0.5,\alpha _{landmark}=0.5) \)
\( O-Net:(\alpha_{det}=1,\alpha_{box}=0.5,\alpha_{landmark}=1) \)
其中,N为训练样本数,\( \alpha_j \)为任务的重要性,\( \beta_j \)为样本标签,\( L_j \)为前面三个任务(face classification、bounding box regression、facial landmark localization)对应的 loss 函数。
在训练阶段,3 个网络都会将关键点位置作为监督信号来引导网络的学习, 但在预测阶段,P-Net 和 R-Net 仅做人脸检测,不输出关键点位置(因为这时人脸检测都是不准的),关键点位置仅在 O-Net 中输出。
Bounding box和关键点输出均为归一化后的相对坐标,Bounding Box 是相对待检测区域(R-Net 和 O-Net 是相对输入图像),归一化是相对坐标除以检测区域的宽高,关键点坐标是相对 Bounding box 的坐标,归一化是相对坐标除以 Bounding box 的宽高,这里先建立起初步的印象,具体可以参看后面准备训练数据部分和预测部分的代码细节。
环境:
Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz
Logitech HD Pro Webcam c920
图像大小:640*640
效果:(compressed gif)

Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
https://www.cnblogs.com/shine-lee/p/10115582.html
https://zhuanlan.zhihu.com/p/31913064
https://www.cnblogs.com/shine-lee/p/10115582.html
https://blog.csdn.net/qq_14845119/article/details/52680940
http://www.sfinst.com/?p=1683
https://blog.csdn.net/qq_36782182/article/details/83624357
训练:
https://github.com/dlunion/mtcnn/tree/master/train
https://www.cdsy.xyz/computer/programme/artificial_intelligence/250318/cd73919.html
https://joshua19881228.github.io/2018-09-11-training-mtcnn/
https://github.com/dlunion/mtcnn
https://github.com/BobLiu20/mtcnn_tf
实现
https://github.com/imistyrain/MTCNN/blob/master/MTCNN-light/src/main.cpp
https://github.com/cpuimage/MTCNN
https://github.com/AITTSMD/MTCNN-Tensorflow/blob/master/train_models/mtcnn_model.py
https://github.com/davidsandberg/facenet/blob/master/src/align/detect_face.py
https://github.com/TropComplique/mtcnn-pytorch
https://github.com/LeslieZhoa/tensorflow-MTCNN
https://github.com/imistyrain/MTCNN
https://github.com/davidsandberg/facenet
https://github.com/AlphaQi/MTCNN-light
https://github.com/BobLiu20/mtcnn_tf
https://github.com/LucyLu-LX/MTCNN_face_detection_caffe
https://github.com/pangyupo/mxnet_mtcnn_face_detection
https://github.com/Longqi-S/ncnn-mtcnn
https://github.com/githublet/mtcnn/blob/master/caffemodel2txt/caffemodel2txt.py
原作主页: https://kpzhang93.github.io/MTCNN_face_detection_alignment/index.html
arxiv 论文: https://arxiv.org/abs/1604.02878
代码: 官方 matlab 版 、 C++ caffe 版
其他框架代码: pytorch 、 tensorflow 、 mxnet

