深度学习之Mtcnn网络详解(人脸检测)

Mtcnn的预测过程(大体流程介绍)

深度学习之Mtcnn网络详解(人脸检测)
这是论文中的原图,揭示了MTCNN预测时的主体流程,主要分为4个部分:图像金字塔、PNet、RNet、ONet

  1. 首先对test的图片进行resize,得到图片金字塔。

输入:test的图片,输出:n张大小不同的图标。
按照resize_factor(如0.709,这个具体根据数据集人脸大小分布来确定,基本确定在0.70-0.80之间会比较合适,设的比较大,容易延长推理时间,小了容易漏掉一些中小型人脸)对test图片进行resize,直到大等于Pnet要求的12*12大小。这样子你会得到原图、原图 x resize_factor、原图 x resize_factor2 … 至图片缩减至12 x 12)这些不同大小的图片,堆叠起来的话像是金字塔,简单称为图片金字塔,并将这些图像金字塔一幅一幅输入到Pnet中。
【注1、为什么代码设定的resize_factor是0.709呢,网上解释说,若选为0.5,则总体面积会变成原图的0.25,改变太大,所以选取12\frac{1}{\sqrt{2}}; 2、为什么缩减至12 x 12呢,因为Pnet训练时输入的图片大小统一为12 x 12】。

  1. 图片金字塔输入Pnet,粗略的进行检测,并获得大量比较粗糙的候选位置

输入:步骤1得到的图片金字塔;输出:(m, n, 6)【注6 = 2 + 4, 2是否有存在人脸的概率,4是图片左上角与右下角的偏移量】。
根据步骤1得到的图片金字塔,将所有图片输入到Pnet,得到输出map形状是(m, n, 6)【注6 = 2 + 4, 2是否有存在人脸的one-hot,4是】。首先,根据分类得分筛选掉小于阈值的一大部分的bboxes,再根据得到的4个偏移量对bbox进行校准后得到bbox在原图对应的左上右下的坐标(根据偏移量矫正先埋个坑,描述训练阶段的时候补)。在对这些bbox根据IOU值再进行非极大值抑制(NMS)筛选掉一大部分候选(在bbox映射到原图的基础上算IOU)。详细的说就是根据分类得分从大到小排,得到(num_left, 4)的张量,即num_left个bbox的左上、右下绝对坐标。每次以队列里最大分数值的bbox坐标和剩余的bboexes坐标求出iou,干掉iou大于0.6(阈值是提前设置的)的框,重复这个操作,最终得到(num_left_after_nms, 6)个候选,根据这些候选的坐标去原图截出图片后,resize为24*24输入到Rnet。

  1. Pnet裁剪出来的候选区域图片输入Pnet,进行较为精细的检测及调整,得到较少量质量不错的候选位置

根据Pnet输出的坐标,去原图上截取出图片(截取图片有个细节是需要截取bbox最大边长的正方形,这是为了保障resize的时候不产生形变和保留更多的人脸框周围细节),resize为24*24,输入到Rnet,进行精调。Rnet仍旧会有2个输出(是否含人脸的概率)、bbox的坐标偏移量4个输出,根据二分类得分干掉大部分不是人脸的候选、对截图的bbox进行偏移量调整后(说的简单点就是对左上右下的x、y坐标进行上下左右调整),再次重复Pnet所述的IOU NMS干掉大部分的候选。最终Pnet输出的也是(num_left_after_Rnet, 16),根据bbox的坐标再去原图截出图片输入到Onet,同样也是根据最大边长的正方形截取方法,避免形变和保留更多细节。

  1. Rnet裁剪出来的候选区域图片输入Onet,进行最后的精修,得到准确的人脸坐标和landmark坐标。

大体可以重复Rnet的过程,根据Rnet输出坐标,去原图截取出图片,resize为48 x 48,输入到Onet,进行精调。Onet输出:2(是否含人脸概率)+ 4(bbox的偏移量)+ 10(5个关键点坐标)。

Mtcnn的训练过程

预测的流程上述已经介绍过了,但是网络要怎么训练呢,训练数据怎么获取呢?下面来介绍一下。
Pnet 、Rnet、Onet三个网络都是单独训练的,训练好Pnet后训练Rnet,再训练Onet,前者的训练输出是后者的训练输入。训练集的图片大小分别为,Pnet是12123, Rnet是24243, Onet是48483的图片。
深度学习之Mtcnn网络详解(人脸检测)
Pnet经过几层的conv,最终输出112、4、10,注意这个Pnet输出和后面Rnet、Onet有点不同。区别在于Pnet是输出的map,比如图片是h*w大小,那么经过这个网络就会输出也大体是图片的1/2(这个不一定,看你使用的conv和pooling,大体会计算得出一个feature map 大小为:(h_new, w_new, 16))。而Rnet和Onet输出的是每个阶段(num_of_left, 16)个candidate。这也就解释了为什么Pnet的输出是方块,而Rnet和Onet输出是长条形。

训练数据准备
  • 先讲一个统一的东西,每个网络的输入我们会有4种训练数据输入:

Positive face数据:图片左上右下坐标和label的IOU>0.65的图片,label = 1;
part face数据:图片左上右下坐标和label的0.65>IOU>0.4的图片,label = -1;
negative face 数据:图片左上右下坐标和lable的IOU<0.3的图片,label = 0;
landmark face数据:图片带有5个关键点的landmark label的图片 ,label = -2;
这4种数据如何组织呢?
深度学习之Mtcnn网络详解(人脸检测)
数量之比依次为3:1:1:2,其中,Negatives、Positives和Part faces通过WIDER FACE数据集crop得到,landmark faces通过CelebA数据集crop得到

  • 不同任务使用不同的数据集

网络做人脸分类的时候,使用postives 和negatives的图片来做,为什么只用这两种?因为这两种数据分得开,中间隔着个part face+0.1 IOU的距离,容易使模型收敛;
网络做人脸bbox的偏移量回归的时候,使用positives 和parts的数据,为什么不用neg数据?论文里面没提,个人认为是因为neg的数据几乎没有人脸,用这个数据来训练人脸框offset的回归挺不靠谱的,相反pos和part的数据里面人脸部分比较大,用来做回归,网络还能够看到鼻子、眼睛、耳朵啥的来进行乖乖的回归;
网络做人脸landmark 回归的时候,就只使用landmark face;

  • Pnet网络的数据集制作

Pnet数据集的训练样本,即12*12大小的图片,如何得到的呢?根据WIDER和CelebA数据集中的label(格式见下图),上下左右随机微调,再将图片resize为12 x 12大小的图片得到。
Pnet数据集的训练label:计算刚刚微调后的框与WIDER和CelebA数据集中label框的大小,得到Pnet数据集对应的分类laebl;计算微调框与WIDER和CelebA数据集中label框的偏移量,得到Pnet数据集对应的偏移label;同理得到landmard的偏移label
深度学习之Mtcnn网络详解(人脸检测)

  • Rnet、Onet网络的数据集制作

待上述Pnet训练完成,我们将所有的WIDER数据和CelebA数据输入到Pnet,会得到很多的候选,去原图截图,计算截图和label的IOU,按照上述四种数据的分类标准分别区分开,同时标注好label(1,0,-1,-2)。我们经过Pnet就可以得到Rnet所需的24 x 24大小的训练数据了。我们继续训练好Rnet。
同理,Onet的输入是WIDER数据集和CelebA数据集经过Pnet、Rnet后得到的在原图上截取的图片,根据IOU的不同进行分类,并resize为48 x 48。这样子我们再把Onet给训练好。

损失函数

以上3个网络,每个网络均有3个任务,1个分类和2个回归,分别为face classification、bounding box regression以及facial landmark localization,分类的损失函数使用交叉熵损失,回归的损失函数使用欧氏距离损失,如下:
深度学习之Mtcnn网络详解(人脸检测)

对于第i个样本,Ldeti为判断是不是人脸的交叉熵损失,Lboxi为bounding box回归的欧式距离损失,Llandmarki为关键点定位的欧氏距离损失,任务间权重通过αj协调,配置如下:
深度学习之Mtcnn网络详解(人脸检测)

同时,训练数据中有含人脸的、有不含人脸的、有标注了关键点的、有没标注关键点的,不同数据能参与的训练任务不同,比如不含人脸的负样本自然无法用于训练bounding box回归和关键点定位,于是有了βji∈{0,1},指示每个样本能参与的训练任务,例如对于不含人脸的负样本其βdeti=1,βboxi=0,βlandmarki=0。

参考:

  1. https://zhuanlan.zhihu.com/p/58825924
  2. https://www.cnblogs.com/shine-lee/p/10115582.html
  3. 源码解析
  4. 视频讲解