MTCNN算法与代码理解

前言

原作主页https://kpzhang93.github.io/MTCNN_face_detection_alignment/index.html

arxiv论文https://arxiv.org/abs/1604.02878

代码官方matlab版C++ caffe版

其他框架代码pytorchtensorflowmxnet

MTCNN 《Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks》,采用级联CNN结构,通过多任务学习,同时完成–人脸检测和人脸对齐,输出人脸的BoundingBox和人脸5个关键点(双眼、鼻子、双嘴角)的位置。

MTCNN在提出时在FDDBWIDER FACE和AFLW数据集上取得了当时(2016年4月)的SOTA速度又快,现在仍被广泛使用作为人脸识别的前端,如InsightFace和facenet。

论文提到,MTCNN的效果主要来自3个主要原因:

1.精心设计的级联CNN结构(carefully designed cascaded CNNs architecture)

2.在线难样本挖掘策略(online hard sample mining strategy)

3.人脸检测与对其联合学习(joint face alignment learning)

Tips:个人建议在看这篇文章的时候,对照着pytorch的实现代码理解,尤其是里面的 try_mtcnn_step_by_step.ipynb非常有助于理解整个文章的流程。

算法流程(概略)

Inference阶段

图像金字塔

1、对于给定的输入图像进行scale操作, 得到若干个不同scale的输入图像,这一步的目的是能够针对不同大小人脸进行候选框的检测。

P-Net

2.1、将不同scale的图像输入到P-Net中。

2.2、 设定阈值,根据face classification的结果,选出可能含有目标框的点 。

2.3、 将这些在不同尺度下可能是目标框的点映射到原始没有经过scale的图中,得到了很多候选区域。

2.4、 使用nms算法对目标框进行筛选,并且根据P-Net中输出的offset(对应bounding box regression)对候选框进行微调,校准。

R-Net

3、 将上一步得到所有候选框提取出来,并resize到24*24的大小,输入至R-Net中,并根据face classification的值,进一步对候选进行筛选,类似于2-4中的操作,对目标框位置进行筛选校准

O-Net

4、 类似于第3步的操作,进一步对目标框进行筛选,并得到最终的输出结果,并且根据Facial landmark的输出得到5个landmark。

PS: 在P-Net和R-Net中,都没有输出Facial landmark localization,只在最终的O-Net中输出了 。

算法流程(详解)

MTCNN方法主要为:图像金字塔+3个级联CNN网络

算法流程图如下所示:

pipeline

图像金字塔

图像金字塔(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,意味着利用的信息越来越多。

nets

其中 P-Net:Fast Proposal NetworkR-Net:Refinement NetworkO-Net:Output NetworkMP:max poolingConv:convolution

P-Net

该网络的主要任务是获得人脸区域的候选窗口边界框的回归向量。并用该边界框做回归,对候选窗口进行校准,然后通过非极大值抑制(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.通过10个$3\times 3\times 3$的卷积核,$2\times 2$的Max Pooling(stride=2)操作,生成10个$5\times 5$的特征图。

2.通过16个$3\times 3\times 10$的卷积核,生成16个$3\times 3$的特征图。

3.通过32个$3\times 3\times 16$的卷积核,生成32个$1\times 1$的特征图

4.针对32个$1\times 1$的特征图

  • 通过2个$1\times 1\times 32$的卷积核,生成2个$1\times 1$的特征图用于人脸的分类;
  • 通过4个$1\times 1\times 32$的卷积核,生成4个$1\times 1$的特征图用于回归框判断;
  • 通过10个$1\times 1\times 32$的卷积核,生成10个$1\times 1$的特征图用于人脸关键点的判断。

模型训练

1、P-Net 的层数很浅,主要作用是尽可能多的把人脸框都选进来,宁愿错误拿来好多个,也不丢掉一个。

2、P-Net的训练数据主要由4部分组成:其中比例为$pos:part:neg:landmark=1:1:3:2$

  • pos正label数据(IoU>0.65,面部Landmark特征值为0)
  • neg负label数据(IoU<0.40,面部Landmark特征值为0,回归框值为0)
  • part中间数据(0.40<IoU<0.65,面部Landmark特征值为0)
  • landmark面部Landmark数据(回归框值为0)

3、训练数据的由来:

pos,part,neg是随机和人脸的数据裁剪得到的,裁剪图片与人脸框最大的iou值大于0.65的为pos图像,大于0.4的为part图像,小于0.4的为neg图像,landmark截取的是带有关键点的图像。

  • pos,part的label含有它们的类别1,-1还有人脸框相对于图像左上角的偏移量,偏移量除以图像大小做了归一化;

  • neg的label只含有类别0;

  • landmark的label含有类别-2和5个关键点的坐标偏移也是进行了归一化的。

这四种图像都resize成$12\times 12$作为PNet的输入,通过P-Net得到了是否有人脸的概率[batch,2],人脸框的偏移量[batch,4],关键点的偏移量[batch,10]。

4、四种不同数据的训练方式:

  • 对于是否存在人脸的类别损失只通过neg和pos数据来对参数进行更新,具体办法是通过label中的类别值做了一个遮罩来划分数据,只计算neg和pos的损失,不计算其他数据的损失;
  • 人脸框的损失只计算pos和part数据的;
  • 关键点的损失只计算landmark的
  • Tips: Online Hard Example Mining(OHEM) 在训练过程中,对每个mini-batch,取loss最大的70%进行反向传播,忽略那些简单的样本。说是模型准确率会有提升,在代码中也都有体现,具体实现可以参考代码。

R-Net

该网络的主要任务还是通过边界框回归和NMS来去掉那些false-positive区域。该网络是单纯的卷积神经网络(CNN),先将P-Net认为可能包含人脸的Bounding Box 双线性插值到24×24,输入R-Net,判断是否包含人脸,如果包含人脸,也回归出Bounding Box,同样经过NMS过滤。只是由于该网络结构和P-Net网络结构有差异,多了一个全连接层,所以会取得更好的抑制false-positive的作用。

O-Net

该网络的主要任务是对人脸区域进行了更多的监督,同时输出5个人脸landmark。该网络也是单纯的卷积神经网络(CNN),该网络比R-Net又多了一层卷基层,所以处理的结果会更加精细。作用和R-Net层作用一样,并输出5个人脸landmark。

Face classification

人脸的检测可以看作是一个局部二分类问题(该区域存在/不存在人脸)。

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}$为该区域的真实标签。

Bounding box regression

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)

Facial Landmark Localization

与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}$.

Multi-source training

整个训练可以表示为:

$$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的宽高,这里先建立起初步的印象,具体可以参看后面准备训练数据部分和预测部分的代码细节。

优点(改进)

  • 减少卷积核数量(每层内部)
  • 将$5\times5$的卷积核替换为$3\times3$,并增加网络深度
  • 在线难样本挖掘(Online hard sample mining)
    • 传统的难样本的处理方法是检测过一次以后,手动检测哪些困难的样本无法被分类,本文采用online hard sample mining的方法。具体就是在每个mini-batch中,取loss最大的70%进行反向传播,忽略那些简单的样本。
  • 人脸检测和对齐联合学习(joint face detecion and alignment)

代码

mtcnn人脸检测

实现效果

环境:
Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz
Logitech HD Pro Webcam c920
图像大小:640*640
效果:(compressed gif)
mtcnn


参考

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.cnblogs.com/helloworld0604/p/9808795.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


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!