作者简介

CW,广东深圳人,毕业于中山大学(SYSU)数据科学与计算机学院,毕业后就业于腾讯计算机系统有限公司技术工程与事业群(TEG)从事Devops工作,期间在AI LAB实习过,实操过道路交通元素与医疗病例图像分割、视频实时人脸检测与表情识别、OCR等项目。

目前也有在一些自媒体平台上参与外包项目的研发工作,项目专注于CV领域(传统图像处理与深度学习方向均有)。

前言

MTCNN(Multi-Task Cascaded Convolutional Networks)是2016年提出的,如其名,算法采用了级联CNN的结构实现了多任务学习——人脸检测 和 人脸对齐,最终能够预测出人脸框(bounding box)和关键点(landmarks)的位置。

MTCNN在 FDDB、WIDER FACE 和 AFLW 数据集上均取得了当时(2016年4月)最好的效果,而且速度也快(在当时来说),被广泛用于人脸识别流程中的前端部分。

总地来说,MTCNN的效果主要得益于以下几点:

1. 级联的CNN架构是一个coarse-to-fine(由粗到细)的过程;

2. 在训练过程中使用了在线困难样本挖掘(OHEM,Online Hard Example Mining)的策略;

3. 加入了人脸对齐的联合学习(Joint Face Alignment Learning)

下面,请诸位客官进入MTCNN的世界里进行参观。

MTCNN的“宣传海报”


网络结构

MTCNN由3个网络组成,共同构成级联的CNN架构。这3个网络依次为 P-Net、R-Net 和 O-Net,前者的输出会作为后者的输入。

P-Net(Proposal Network)

P-Net

顾名思义,这个网络主要用于输出包含的人脸候选区域。输出包含3部分:分类结果(二分类),代表是否人脸、检测到的人脸框(bbox)位置 以及 定位到的关键点(landmarks)位置。

需要注意的是,这里回归输出的bbox和landmarks并非是坐标值本身,而是归一化的offset,具体在后文会讲解,这里先埋个坑~

另外,P-Net是一个FCN(Fully Convolutonal Network),输出的是一个map,channel为2+4+10=16,2对应二分类的score,4对应bbox左上角和右下角横纵坐标的offset,而10则对应5个关键点(左、右眼、鼻、左、右嘴角)横纵坐标的offset,后续R-Net和O-Net的输出意义也与此相同。

或许你会疑惑,为何P-Net要设计成FCN呢?从上图可以看到,输入图像的size是12x12,最终输出的size变为1x1,完全没有必要嘛~其实仔细看下本文前言里展示的那幅图的最上面部分,应该就知道答案了。

R-Net(Refine Network)

R-Net

R-Net不再是FCN,最后使用全连接层,相比于P-Net,其输入size和每层的通道数也比较大,可以认为,其拟合的结果会更精确,主要作用是对P-Net的结果进行校正,消除其中的误判(FP,False-Positive)。

O-Net(Output Network)

O-Net

O-Net的结构与P-Net较为类似,只不过输入size、宽度以及深度都更大,因此可使最终输出结果更加精确。

从上述展示的结构中我们可以feel到,P-Net->R-Net->O-Net 是一个coarse-to-fine的过程。

推理过程

推理过程的pipeline依次是:对输入图像进行处理生成图像金字塔 -> 输入到P-Net -> 对P-Net的输出进行后处理 -> 输入到R-Nnet -> 对R-Net的输出进行后处理 -> 输入到O-Net -> 对O-Net的输出进行后处理得到最终预测结果。

另外,推理时P-Net和R-Net可以不必输出landmarks分量,因为此时预测的人脸框位置还不准,根据offset计算出对应的landmarks位置没有太大意义,而且也没有必要,最终的输出还是取决于O-Net。

图像金字塔

由上一节展示的P-Net网络架构可知,其是在单尺度(12x12 size)上做训练的,为了检测到不同尺寸的人脸,所以在推理时需要先生成图像金字塔,而P-Net为何设计成FCN的原因也在于此。

首先,设置一个想要检测的最小人脸尺寸min_size,比如20x20,其次,设定一个缩放因子fator,通常为0.707。

然后,将图像的最短边乘以 12 / 20,进行一次缩放,接着不断对前面缩放的尺寸乘以fator进行缩放,比如最短边初始为s,接下来就会缩放得到:s x 12 / 20、s x 12/ 20 x factor、s x 12 / 20 x factor ^2、...,直至s不大于12时停止。

记录下以上缩放过程中(最短边还大于12时)的各个scale:12 / 20、12 / 20 x factor、12 / 20 x factor^2、...,最后依次按照每个scale对图像采用双线性插值的方式进行缩放从而得到图像金字塔。提问时间到!为何缩放因子是0.707?

这个数字不觉得有点眼熟吗?是的,它约等于,那么这又代表什么呢?通常,按照我们凡夫俗子的思维,缩放系数都习惯于取0.5,如果边长都缩放0.5倍的话,那么矩形框面积就缩小了1/4,跨度未免有点大,可能会漏掉许多要检测的人脸。要知道,按照P-Net的意思,每个尺度对应的就是一张人脸。于是我们可以让面积缩放1/2,减小这之间的跨度,相应地,边长的缩放系数就为

十万个为什么系列之第二个灵魂拷问——min_size和factor对推理过程会产生什么样的影响?

由小学数学知识可知,min_size越大、fator越小,图像最短边就越快缩放到接近12,从而生成图像金字塔的耗时就越短,同时各尺度的跨度也更大。因此,加大min_size、减小factor能加速图像金字塔的生成,但同时也更易造成漏检。

好了,不问了,真要问十万个估计我的手要码到残废了..剩下的诸位自行yy。

由上述可知,图像金字塔的缺点就是慢!慢在需要不断resize生成各个尺寸的图像,还慢在这些图像是一张张输入到P-Net中进行检测的(每张的输出结果代表一张人脸候选区域),相当于做了多次推断过程,你说可不可怕..

P-Net获取人脸候选区域

将图像金字塔中每个尺寸的图像依次输入到P-Net,对于每个尺度的图像都会对应输出一个map,输出map的每点都会有分类score和回归的bbox offset。先保留置信度较高的一批位置点,然后将每点还原出对应的人脸区域,接着用NMS剔除重复的区域,得到所有尺寸图像保留下来的结果后,再用一次NMS进行去重(CW做过实验,不同scale下输出的图像之间NMS没有效果,说明不同scale下没有重复的,也符合不同scale检测不同尺寸人脸的意思),最后使用回归得到的offset对人脸候选区域进行校正得到bbox位置。十万个为什么系列再次上线——如何还原出输出map每点对应的人脸区域?

根据P-Net的结构设计可知,输出feature map的一点实际对应的是输入中12x12的区域,而P-Net中有一个池化层进行了2倍的下采样(对卷积层带来的尺寸损失不计),于是对于输出feature map的一点(x, y),我们可以这么做来进行还原:

i). 先还原出其在输入图像的位置:(x*2, y*2);

ii). 将其作为人脸区域的左上角,对应地,右下角为:(x*2 + 12, y*2 + 12);

iii). 由于在生成图像金字塔时进行了缩放,因此还要除以当时缩放的scale:(x1 = x*2 / scale, y1 = y*2 / scale)、(x2 = (x*2 + 12) / scale, y2 = (y*2 + 12) / scale)

以上(x1, y1, x2, y2)便是还原出来在原图上对应的人脸区域。

你们应该还没有吃饱,继续问——如何用回归得到的offset计算出人脸bbox位置?

x1_true = x1 + tx1*w

y1_true = y1 + ty1*h

x2_true = x2 + tx2*w

y2_true = y2 + ty2*h

使用以上公式就能计算得到结果,其中x*_true和y*_true代表人脸bbox的位置,tx*、ty*代表回归得到的offset,w和h就是人脸区域(x1, y1, x2, y2)的宽和高。

至于为什么能这么计算,这是由训练前制作label的时候决定的,在下一节讲训练过程时会说明,这里先hold着。

P-Net输出的bbox不够精准,仅作为包含人脸的候选区域,接下来交由R-Net进行校正。

R-Net基于P-Net的结果进一步校正

R-Net并不是直接将P-Net的输出结果拿来用,他还是个细心boy,先对这些输出“做了一番洗剪吹”,成为这条街上最靓的仔后再拿来用,处理过程如下:

i). 为了尽可能涵盖到人脸,将P-Net输出的候选区域都按其各自的长边resize方形;

ii). 检查这些区域的坐标是否在原图范围内,在原图内的像素值设置为原图对应位置的像素值,其它则置为0;

iii). 将以上处理得到的图片区域使用双线性插值resize到24x24大小

处理完后,所有输入都是24x24大小,网络输出的后处理与P-Net类似,先筛选置信度较高的一批结果,然后用NMS剔除重复的,最后使用offset计算出bbox位置。此处使用offset计算时用到的(x1,y1,x2,y2)就是P-Net输出的bbox。

又要问了——为何不直接对原图有效范围内的区域进行resize?

可以这么想,如果有效范围内的区域刚好正是人脸区域,丝毫不差,那么resize后必定会有像素损失,从而丢失细节。

O-Net检测出人脸和关键点位置

看到R-Net是个细心boy,O-Net当然也是很自觉地对R-Net的输出结果做了处理,处理方式与R-Net类似,只不过最终resize到的大小是48x48。

由于O-Net会输出landmarks的offset,因此还需要计算出landmarks的位置:

x_true = x_box + tx*w

y_true = y_box + ty*h

(x_true, y_true)代表一个关键点的位置,tx、ty代表对应的offset,(x_box, y_box)代表R-Net输出bbox的左上角位置,w、h代表bbox的宽、高。至于bbox位置的计算、后处理等这些也都和之前的类似,这里不再阐述了。

哦,另外,在此处NMS计算IoU时,分母可以不取并集,而是取当前置信度最高的bbox和其余bbox面积的较小者,这样分母会变大,从而导致IoU计算结果偏高,相当于变向降低NMS阀值,对重复检测的要求更为苛刻。

训练过程

MTCNN的三个网络是依次分别训练的,先训练P-Net,待其训练好后,将其检测结果用于R-Net的训练数据,然后对R-Net进行训练。同样地,R-Net训练完后,将其检测结果用于O-Net的训练数据,最后训练O-Net。

数据样本分类

MTCNN是集成了人脸检测和人脸对齐的多任务架构,通常使用两个数据集来训练,其中一个训练人脸检测,另一个训练人脸对齐(这部分其实也能训练人脸检测)。在处理训练数据时,会对图像进行随机裁剪,具体方法后文会讲解,这里再埋个坑。可以将训练样本分为4类:

i). Positive:裁剪后图片与人脸标注框 IoU >= 0.65,类别标签为1;

ii). Part:裁剪后图片与人脸标注框 IoU [0.4, 0.65),类别标签为-1;

iii). Negative:裁剪后图片与人脸标注框 IoU < 0.3,类别标签为0;

iv). Landmarks:来自训练人脸对齐的数据集,类别标签为-2

使用Positive和Negative样本计算分类损失,使用Positive和Part样本计算bbox回归损失,而仅使用Landmarks样本计算landmarks回归损失。

十万个为什么时间到——为何只使用Postive和Negative计算分类损失?

应该是考虑到这些正负样本与标注框的IoU差别明显,区分度大,使模型更易收敛。

标签制作

填坑时间到!之前埋下的2个坑会在这里填上,打起精神咯!

P-Net、R-Net和O-Net的标签处理过程有些许差别,下面依次介绍。

P-Net

负样本Negative

1. 对图像进行随机裁剪,裁剪后为方形,边长s=(12, min(H, W) ),H、W分别为图像的高和宽。将图像左上角向右下方进行移动,移动后横、纵坐标分别为

(0, W - s)、 (0, H - s),于是裁剪后图像右下角坐标为(x2=x1 + s, y2=y1 + s)。

2. 计算裁剪后图像与原图中所有标注框的IoU,若最大IoU<0.3,则将这张裁剪后的图像作为负样本Negative,resize至12x12大小,对应的类别标签记为0,保存下来待训练时用。

3. 重复1、2直至生成了50个负样本图像。

4. 对图像中的每个标注框重复5次随机裁剪,也是用于生成负样本。裁剪后边长s与1中的相同,移动bbox的左上角(x1, y1),移动后(nx1=x1 + delta_x, ny1=y1 + delta_y),其中delta_x [max(-s, -x1), w),delta_y [max(-s, -y1), h),也就是对标注框左上角随机进行上下左右移动,w、h分别bbox的宽和高。对应地,bbox右下角坐标变为(nx2=nx1 + s, ny2=ny1 + s)。若右下角坐标超出原图范围,则舍弃该裁剪图片,进行下一次裁剪。

正样本Positive和Part

5. 紧接着4,在一个标注框随机裁剪5次后,再重复随机裁剪20次,用于生成正样本Postive和Part。裁剪后图像边长s 即bbox短边的0.8倍至长边的1.25倍。对bbox的中心点随机进行左右上下移动,移动范围delta_[-0.2w, 0.2w),delta_ [-0.2h, 0.2h),于是移动后中心点坐标为, 相应地,左上角和右下角坐标为

()若右下角坐标超出原图范围,则舍弃此次裁剪的结果,继续执行下一次随机裁剪。

6. 若裁剪后图像与该bbox的IoU>=0.65,则作为正样本Positive,resize到12x12大小,类别标签记为1;否则若IoU>=0.4,则作为Part,同样也resize成12x12,类别标签记为-1;

7. 对于Postive和Part样本,计算bbox左上角和右下角的offset标签:

其中,(x, y)为标注框左上角/右下角的横、纵坐标,(nx, ny)为裁剪图片的左上角/右下角坐标,s为其边长。也就是标注框两个角相对于裁剪图片对应两角的归一化位移。最后将Postive和Part样本对应的裁剪图像、类别标签、offset标签保存下来待训练时用。

关键点样本Landmarks

8. Landmarks样本在另一个数据集中单独处理,每张图片是一个单独的人脸,对每张图重复10次随机裁剪,裁剪方式与生成Positive和Part样本时相同,若裁剪后图像右下角坐标不在原图范围内,或者裁剪后图像与标注框IoU<0.65,则舍弃此次裁剪结果,进行下一次随机裁剪。

9. 计算bbox和landmarks的offset标签,其中bbox的计算方式与Postive以及Part的相同,这里不再阐述,而landmarks的如下:

其中,(x, y)为标注的关键点坐标,为裁剪后图像的左上角坐标,s为裁剪后图像的边长,即标注的关键点相对于裁剪图像左上角的归一化位移。

R-Net

在R-Net的标签制作前需要使用训练好的P-Net的数据集进行检测,后续的数据处理过程与P-Net类似,下面进行介绍。

1. 使用训练好的P-Net对数据集的图片进行检测,将原图、标注框以及检测出的bbox位置对应保存下来。

2. 将原图、标注以及图中检测出的bbox依次取出,对每个bbox依次处理,若尺寸小于20(min_size,代表想要检测的最小人脸size)或者 坐标不在原图范围内,则舍弃该检测出的bbox,继续处理下一个bbox;否则,将bbox对应的区域从原图中裁出并resize到24x24备用。

负样本Negative

3. 计算bbox与所有标注框的IoU,若最大IoU<0.3且当前生成的负样本数量小于60个,则将裁剪出的图像作为负样本,类别标签记为0,保存下来待训练时用。

正样本Positive和Part

4. 否则,若最大IoU>=0.65或0.4<=最大IoU<0.65,则对应地将裁剪出的图像记为正样本Positive或Part,类别标签记为1或-1。同时,取出最大IoU对应的标注框,用于计算offset,计算方式与P-Net中提到的相同,最后将裁剪出的图像、类别标签、offset标签保存好待训练时使用。

O-Net

在制作O-Net的数据标签前需要依次使用训练好的P-Net和R-Net对数据集做检测,然后将R-Net预测的bbox和对应的原图以及标注保存下来供O-Net使用。

标签制作过程和R-Net的几乎相同,只不过没有最小负样本数量的限制(P-Net有50个、R-Net有60个)。另外,若landmarks数据集的标注框最长边小于40或坐标不在原图范围内,则舍弃这个样本。

Loss函数

loss由三部分组成:分类损失、bbox回归损失、landmarks回归损失。

每个网络的loss都由这3种loss加权而成,其中分类损失使用交叉熵损失,回归损失均使用L2距离损失。

上式中,j代表不同的任务(分类、bbox回归、landmarks回归),即不同任务对应的loss权重,对于P-Net和R-Net,它们的分类loss、bbox回归loss、landmarks回归loss的权重比为1:0.5:0.5,而O-Net中为1:0.5:1。是第i个样本在任务j中是否需要贡献loss,需要则为1,否则为0。例如,对于Negative样本,它在回归任务中这个β值就为0。

OHEM(Online Hard Example Mining)

在线困难样本挖掘的策略仅在计算分类loss时使用。直白来说,就是挑选损失最大的前70%作为困难样本,在反向传播时仅使用这70%困难样本产生的损失。作者在paper中的实验表明,这样做在FDDB数据集上能带来1.5个点的性能提升。

总结

最后,总结下MTCNN的整个pipeline:

首先,对待检测图片生成图像金字塔,输入P-Net,得到输出,通过分类置信度和NMS筛选出人脸候选区域;

然后,基于这些候选区域去原图crop出对应的图像,输入R-Net,得到输出后同样是使用分类置信度和NMS,过滤掉false-positive,得到更精准的一批候选;

最后,基于得到的这批候选去原图crop出对应的图像,输入O-Net,输出最终预测的bbox和landmark位置。


本文来自作者CW的原创投稿,如有任问题请及时留言,我们会第一时间处理。


往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
AI基础下载机器学习的数学基础专辑
本站qq群704220115,加入微信群请扫码:

【CV】MTCNN:3个CNN,胜过1个诸葛亮相关推荐

  1. 【CV面试】简述CNN、计算机视觉、人脸识别

    本文整理自多篇博客.虽然不是原创,但是也是费了心血整理的O(∩_∩)O 目录 CNN:图像.视频 1.CNN解决了什么问题? 1.1.将大数据量的图片降维成小数据量 1.2.保留图片特征,符合图片处理 ...

  2. 华为北大等联手打造的Transformer竟在CV领域超过了CNN:多项底层视觉任务达到SOTA...

    杨净 发自 凹非寺 量子位 报道 | 公众号 QbitAI 提起Transformer,就会想到BERT.GPT-3. 但其实,这个在各种自然语言处理任务中「混迹」,强大的无监督预训练模型,现在已经在 ...

  3. transformer在CV领域超越了CNN

    https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_9798279836266993892% ...

  4. CV:计算机视觉技最强学习路线之CV简介(传统视觉技术/相关概念)、早期/中期/近期应用领域(偏具体应用)、经典CNN架构(偏具体算法)概述、常用工具/库/框架/产品、环境安装、常用数据集、编程技巧

    CV:计算机视觉技最强学习路线之CV简介(传统视觉技术/相关概念).早期/中期/近期应用领域(偏具体应用).经典CNN架构(偏具体算法)概述.常用工具/库/框架/产品.环境安装.常用数据集.编程技巧 ...

  5. 如何看待Transformer在CV上的应用前景,未来有可能替代CNN吗?

    链接:https://www.zhihu.com/question/437495132 编辑:深度学习与计算机视觉 声明:仅做学术分享,侵删 目前已经有基于Transformer在三大图像问题上的应用 ...

  6. 【每周CV论文推荐】 深度学习人脸检测入门必读文章

    欢迎来到<每周CV论文推荐>.在这个专栏里,还是本着有三AI一贯的原则,专注于让大家能够系统性完成学习,所以我们推荐的文章也必定是同一主题的. 人脸图像是整个图像处理领域里面研究时间最长, ...

  7. fasterrcnn论文_【每周CV论文推荐】 深度学习人脸检测入门必读文章

    我的新书<深度学习之人脸图像算法>市了,欢迎大家关注! 言有三新书来袭,业界首次深入全面讲解深度学习人脸图像算法​mp.weixin.qq.com 欢迎来到<每周CV论文推荐> ...

  8. CV:计算机视觉技最强学习路线

    CV:计算机视觉技最强学习路线之CV简介(传统视觉技术/相关概念).早期/中期/近期应用领域(偏具体应用).经典CNN架构(偏具体算法)概述.常用工具/库/框架/产品.环境安装.常用数据集.编程技巧_ ...

  9. Vision Transformer 论文

    https://openreview.net/pdf?id=YicbFdNTTy AN IMAGE IS WORTH 16X16 WORDS: TRANSFORMERS FOR IMAGE RECOG ...

最新文章

  1. 浏览器时间久了重新登录_注意!今日开始打印一建准考证,附各地时间及常见问题汇总...
  2. Python学习之路 拓展篇 Pychram的应用
  3. 使用Lambda表达式重构委托
  4. 【Python】random库的使用
  5. DataGridView数据导入到Excel 中
  6. 深度学习-参数与超参数
  7. python执行批处理文件_如何从Python中执行批处理文件,从而改变调用进程的环境?...
  8. DPDK Qos之报文处理流水线
  9. Retrofit+Rxjava+OkHttp
  10. java代码隐藏面消除算法,java常面的几种排序算法
  11. 细数嵌入式开发与通用系统开发的不同
  12. 自动出报表,零代码做驾驶舱,我找到了Excel的顶级替代
  13. 我的.emacs(Ubuntu版)
  14. 机器学习降维之主成分分析
  15. 你不可不知的铠装光缆常识
  16. NIOSII 安装问题汇总
  17. javascript基础常识问答(二)
  18. WRF模式案例运行初体验--飓风示例全过程记录
  19. 穆利堂推荐机会来了你做好准备了吗?怎么让机会找到你?
  20. UOM Conversion Relationship Not Found

热门文章

  1. Android柳叶刀之Button之UI交互
  2. 动态规划--电路布线(circuit layout)
  3. 剖析Hadoop和Spark的Shuffle过程差异(一)
  4. 【深度学习】词的向量化表示
  5. Codeforces Round #374 (Div. 2) A , B , C 水,水,拓扑dp
  6. 今天 学习用到的一些知识(properties 读取,js 删除元素)
  7. ORB-SLAM(四)追踪
  8. cocos2dx打飞机项目笔记五:CCSpriteBatchNode 的使用
  9. Optimize Slow VBA Code
  10. MATLAB R2022 最新中英文版 数据处理