MTCNN人脸识别趟坑实录2019

MTCNN人脸识别趟坑实录2019

  • MTCNN论文相关的基本原理
    • 从识别过程理解
      • P-Net的功能:
      • R-Net的功能
      • O-Net的功能
  • 数据集的准备
    • 负样本
  • 一些杂项
    • 网络输入输出结构的坑
  • 图片演示
  • 我的工程
  • 参考论文
  • 参考博客
  • 参考工程

MTCNN论文相关的基本原理

近期在研究MTCNN的人脸识别。感觉坑还是有一些的,值得备注下供大家参考。
论文里面的图就不贴了,阅读了很多博客,大部分都是从论文中大致翻译过来的内容,但是细节提得就不多了。
网络分为三个:P-Net、R-Net和O-Net。虽然每个网络的构造大致相同,功能却有很大区别,训练方式也大有不同。本文会详细描述。
单纯从网络构造和训练方式入手,思维略带跳跃性。从【识别过程】开始理解,会对整体网络的工作方式很有帮助。笔者一开始是正向理解,绕了很多弯路。

从识别过程理解

从输入一张图片开始
MTCNN人脸识别趟坑实录2019_第1张图片

P-Net的功能:

如果我们需要从大小无关的图片中提取出来脸部区域的大致位置,可以这样做。用成等比大小的【小格子组】从上到下,从左到右,扫遍整张图,如果有的格子的人脸评分很高,那么我们就找到了目标区域。P-Net即是实现这个功能。P-Net的训练过程将整张图缩成固定的12像素,传入网络,输出是人脸的得分,及人脸BoundingBox(以下简称BB)的回归值。通过P-Net,我们可以先将测试图按照论文中金字塔的缩减方式进行素材累加(相当于将【扫描基准格】按照金字塔比例进行放大),然后将所有金字塔图片成批的传入网络,输出的结果再除以对应的缩放比例,依据BB的回归值进行精调,即可获得原图中大致的人脸范围。关于BB的生成和回归值精调,牵扯到的一些算法,比如NMS(非极大值抑制)就不累述了,目的是去除很多因为金字塔生成的重叠BB。将P-Net输出的所有BB从原图中扣出来,统一放缩成24像素,成批输入R-Net
P-Net的输出
MTCNN人脸识别趟坑实录2019_第2张图片

R-Net的功能

P-Net的特点是快,而且参数少。R-Net的功能就更精细一些,这点和R-Net的构成有很大关系。P-Net的输入是12,R-Net的输入是24,所以精度上有所提升。并且最后使用全连接,可以很好的去除P-Net觉得像——但是里面有很大非人脸区域的BB。
。R-net会对这批输入源逐个打分,超过阈值(比如0.8)的我们保留下来。并将所有保留下来的BB再次做NMS和BB回归值精调。这里我们获得的区域一般是很精致的人脸区域了。将这些区域再从原图中扣出来,放缩成48像素,输入O-Net
R-Net的输出
MTCNN人脸识别趟坑实录2019_第3张图片

O-Net的功能

O-Net几乎不会对BB进行更改了,额外的功能是对5个特征值做回归——左右眼,鼻头,左右嘴角,或者应该可以是任何其他的特征点,只要数据集上有。当然我们可以再次通过打分进行筛选,NMS去除一些重复的BB(这里需要使用Min方法,前面的两次NMS都是Union)。BB的回归值精调也是很小范围的了。主要是对特征值进行回归精调并标记。至此,整个MTCNN的识别过程就结束了。
O-Net的输出
MTCNN人脸识别趟坑实录2019_第4张图片
接下来要说的,就是最大的坑,数据集的准备。

数据集的准备

笔者一上来接触数据集比较发蒙,找到了有人脸BB和特征值标注的数据集就着急打包成tfrecord了,可是忽略了最重要的部分。

负样本

我们在打包的时候,需要标注classification、boundingbox和landmark特征值三个回归量。classification是分类,表示是或不是,用【0,1】,第一位代表不是,第二位代表是。然后是用softmax交叉熵做回归。这里最重要的是准备各种的负样本。
负样本顾名思义,既没有脸的图片,如果有半边脸,也可以叫部分样本。负样本的classification是【1,0】,正样本是【0,1】。负样本充足了,才可以获得BB的正确打分。输出的结果再做一次softmax,即可获得0-1的打分值了。
也可按照IoU的方法来划定正负样本,这里再多说一下正样本
一定要有只有脸的正样本,或者脸的比例超过IoU一定值的训练素材,否则R-Net那里的打分会很低(相当于没有数据告诉R-Net到底什么样的是张合格的脸)。
剩下的就按照博客或论文中说的,P-Net的数据缩成12来训练,R-Net的缩成24,O-Net的缩成48。训练时Loss的计算,P和R不重视Landmark,landmark的比例可以低些,O-Net重视Landmark,所以比例高些。

一些杂项

网络输入输出结构的坑

P-Net使用时,输入可以是任意尺寸的图片,每个Pyramid层会输出【batch,bh,bw,3】的BB(比如【1,70,70,3】即代表该层有70x70个输出BB)。关于P-Net的使用,不需要进行特殊处理,直接输入图片即可。
R-Net使用时就有些问题了。笔者将模型保存成了PB文件,参数量固定,那么在进行全连接时,就需要固定的批次了。比如训练时是128一批,那么R-Net的输入也需要是128个,如果P-Net输出的合格BB只有100或多余128个,那么就需要进行补充或者裁剪后再输入R-Net了。同样的,O-Net也需要对R-Net的输出做同样的处理,对应上输入尺寸就好。

图片演示

笔者的数据集使用的是lfw_5590和net7876,数量有限,效果不是特别好,但是也能达到说明的目的了
这是输入的原图
MTCNN人脸识别趟坑实录2019_第5张图片
这是P-Net的输出
MTCNN人脸识别趟坑实录2019_第6张图片
R-net的输出
MTCNN人脸识别趟坑实录2019_第7张图片
O-Net的输出
MTCNN人脸识别趟坑实录2019_第8张图片
可以看到黑人的识别不是很准确,landmark的位置也只是参考。增大数据集,并对数据进行一些光照等多样化处理后会好很多。作为研究先告一段落了。
谢谢您的阅读。

我的工程

https://gitee.com/diamondcm/MTCNN

参考论文

ZhangK, Zhang Z, Li Z, et al. Joint Face Detection and Alignment using Multi-taskCascaded Convolutional Networks[J]. arXiv preprint arXiv:1604.02878, 2016.

参考博客

https://blog.csdn.net/FortiLZ/article/details/81396566

参考工程

https://github.com/wangbm/MTCNN-Tensorflow

你可能感兴趣的:(人脸识别)