干货 | MTCNN实时人脸检测网络详解与代码演示

MTCNN模型概述

多任务卷积神经网络(MTCNN)实现人脸检测与对齐是在一个网络里实现了人脸检测与五点标定的模型,主要是通过CNN模型级联实现了多任务学习网络。整个模型分为三个阶段,第一阶段通过一个浅层的CNN网络快速产生一系列的候选窗口;第二阶段通过一个能力更强的CNN网络过滤掉绝大部分非人脸候选窗口;第三阶段通过一个能力更加强的网络找到人脸上面的五个标记点;完整的MTCNN模型级联如下:

该模型的特征跟HAAR级联检测在某些程度上有一定的相通之处,都是采用了级联方式,都是在初期就拒绝了绝大多数的图像区域,有效的降低了后期CNN网络的计算量与计算时间。MTCNN模型主要贡献在于: 1.提供一种基于CNN方式的级联检测方法,基于轻量级的CNN模型就实现了人 脸检测与点位标定,而且性能实时。 2.实现了对难样本挖掘在线训练提升性能 3.一次可以完成多个任务。

阶段方法详解

第一阶段 网络是全卷积神经网络是一个推荐网络简称 P-Net, 主要功能是获得脸部区域的窗口与边界Box回归,获得的脸部区域窗口会通过BB回归的结果进行校正,然后使用非最大压制(NMS)合并重叠窗口。 第二阶段 网络模型称为优化网络R-Net,大量过滤非人脸区域候选窗口,然后继续校正BB回归的结果,使用NMS进行合并。 第三阶段 网络模型称为O-Net,输入第二阶段数据进行更进一步的提取,最终输出人脸标定的5个点位置。

网络架构与训练

对CNN网络架构,论文作者发现影响网络性能的因素主要原因有两个:

1.样本的多样性缺乏会影响网络的鉴别能力 2.相比其它的多类别的分类与检测任务来说,人脸检测是一个二分类,每一层不需要太多filters,也就是说每层网络的feature maps个数不需要太多。

根据上述两个因素,作者设计网络每层的filter个数有限,但是它增加了整个网络的深度,这样做的好处是可以显著减少计算量,提升整个网络性能,同时全部改用3x3的filter更进一步降低计算量,在卷积层与全连接层使用PReLU作为非线性激活函数(输出层除外)整个网络架构如下:

训练这个网络需要如下三任务得到收敛

1.人脸二元分类 2.BB回归(bounding box regression) 3.标记定位(Landmark localization)

训练时候对于人脸采用交叉熵损失:

BB回归损失: 对每个候选窗口,计算它与标注框之间的offset,目标是进行位置回归,计算其平方差损失如下:

脸部landmark位置损失:

总计有五个点位坐标分别为左眼、右眼、鼻子、左嘴角、右嘴角 因为每个CNN网络完成不同的训练任务,所以在网络学习/训练阶段需要不同类型的训练数据。所以在计算损失的时候需要区别对待,对待背景区域,在R-Net与O-Net中的训练损失为0,因为它没有包含人脸区域,通过参数beta=0来表示这种类型。总的训练损失可以表示如下:

在P-Net中对人脸进行二元分类时候就可以在线进行难样本挖掘,在网络前向传播时候对每个样本计算得到的损失进行排序(从高到低)然后选择70%进行反向传播,原因在于好的样本对网络的性能提升有限,只有那些难样本才能更加有效训练,进行反向传播之后才会更好的提升整个网络的人脸检测准确率。作者的对比实验数据表明这样做可以有效提升准确率。在训练阶段数据被分为四种类型

负样本:并交比小于0.3 正样本:并交比大于0.65 部分脸:并交比在0.4~0.65之间 Landmark脸:能够找到五个landmark位置的

其中在负样本与部分脸之间并没有明显的差异鸿沟,作者选择0.3与0.4作为区间。

正负样本被用来实现人脸分类任务训练 正样本与部分脸样本训练BB回归 Landmark脸用来训练人脸五个点位置定位

整个训练数的比例如下:

负样本:正样本:部分脸:landmark脸=3:1:1:2

测试代码

加载网络

print('Creating networks and loading parameters')
with tf.Graph().as_default():
    gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_memory_fraction)
    sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
    with sess.as_default():
        pnet, rnet, onet = align.detect_face.create_mtcnn(sess, None)

人脸检测

def detection(image):
    minsize = 20  # minimum size of face
    threshold = [0.6, 0.7, 0.7]  # three steps's threshold
    factor = 0.709  # scale factor

    # detect with RGB image
    h, w = image.shape[:2]
    bounding_boxes, _ = align.detect_face.detect_face(image, minsize, pnet, rnet, onet, threshold, factor)
    if len(bounding_boxes) < 1:
        print("can't detect face in the frame")
        return None
    print("num %d faces detected"% len(bounding_boxes))
    bgr = cv.cvtColor(image, cv.COLOR_RGB2BGR)
    for i in range(len(bounding_boxes)):
        det = np.squeeze(bounding_boxes[i, 0:4])
        bb = np.zeros(4, dtype=np.int32)
        # x1, y1, x2, y2
        bb[0] = np.maximum(det[0] - margin / 2, 0)
        bb[1] = np.maximum(det[1] - margin / 2, 0)
        bb[2] = np.minimum(det[2] + margin / 2, w)
        bb[3] = np.minimum(det[3] + margin / 2, h)
        cv.rectangle(bgr, (bb[0], bb[1]), (bb[2], bb[3]), (0, 0, 255), 2, 8, 0)
    cv.imshow("detected faces", bgr)
    return bgr

实时摄像头检测

capture = cv.VideoCapture(0)
height = capture.get(cv.CAP_PROP_FRAME_HEIGHT)
width = capture.get(cv.CAP_PROP_FRAME_WIDTH)
out = cv.VideoWriter("D:/mtcnn_demo.mp4", cv.VideoWriter_fourcc('D', 'I', 'V', 'X'), 15,
                             (np.int(width), np.int(height)), True)
while True:
    ret, frame = capture.read()
    if ret is True:
        frame = cv.flip(frame, 1)
        cv.imshow("frame", frame)
        rgb = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
        result = detection(rgb)

        out.write(result)
        c = cv.waitKey(10)
        if c == 27:
            break
    else:
        break

cv.destroyAllWindows()

运行演示:

本来想上传视频的发现上传不了了,所以就把视频写成多张连续的图像,截屏显示各种效果,其实视频十分流畅,效果也非常的好。

有遮挡、部分脸检测

侧脸检测

角度俯仰脸检测

总结一下 整个模型的运行速度极快,即使在CPU上也可以完全达到实时性能,关键是其检测准确率与稳定性跟HAAR/LBP的方式相比,你就会感觉HAAR/LBP的方式就是渣,完全凉啦!

原文发布于微信公众号 - OpenCV学堂(CVSCHOOL)

原文发表时间:2018-11-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术翻译

用数学方法解密神经网络

在本文中,我们将讨论简单神经网络背后的数学概念。其主要目的是说明在建立我们自己的人工智能模型时,数学是如何发挥巨大作用的。

1550
来自专栏张俊红

机器学习中非平衡数据处理

总第97篇 这一篇主要说一下机器学习中非平衡数据的处理方式以及用python如何实现. 在前面的一篇推文中我们提到过,非平衡数据会影响最后的评判效果,严重的会...

3955
来自专栏人工智能头条

AI从入门到放弃:BP神经网络算法推导及代码实现笔记

1882
来自专栏贾志刚-OpenCV学堂

OpenCV金字塔图像分辨率重建与融合

图像金字塔是对一张输入图像先模糊再下采样为原来宽高的1/2(宽高缩小一半)、不断重复模糊与下采样的过程就得到了不同分辨率的输出图像,叠加在一起就形成了图像金字塔...

2095
来自专栏AI深度学习求索

传统特征:HOG特征原理

为了减少光照因素的影响,首先需要将整个图像进行规范化(归一化),有效地降低图像局部的阴影和光照变化。

1443
来自专栏和蔼的张星的图像处理专栏

3. 经典卷积网络之GooleInceptionNet

GooleInceptionNet首次出现是在2014年的ILSVRC的比赛中,当时是第一名,最大的特点就是控制计算量的同时获得了比较好的分类性能--top-5...

1462
来自专栏机器之心

业界 | 一文概览2017年Facebook AI Research的计算机视觉研究进展

选自skrish13 作者:Krish 机器之心编译 参与:路雪、刘晓坤 本文概述了 2017年Facebook AI 研究院(FAIR)在计算机视觉上的研究进...

3205
来自专栏机器之心

盘点 | 对比图像分类五大方法:KNN、SVM、BPNN、CNN和迁移学习

选自Medium 机器之心编译 参与:蒋思源、黄小天、吴攀 图像分类是人工智能领域的基本研究主题之一,研究者也已经开发了大量用于图像分类的算法。近日,Shiyu...

9708
来自专栏应用案例

从传统方法到深度学习,人脸关键点检测方法综述

人脸关键点检测是人脸识别和分析领域中的关键一步,它是诸如自动人脸识别、表情分析、三维人脸重建及三维动画等其它人脸相关问题的前提和突破口。近些年来,深度学习方法由...

1.1K8
来自专栏机器之心

学界 | 微软亚洲研究院CVPR 2017 Oral论文:逐层集中Attention的卷积模型

选自CVPR 2017 机器之心编译 参与:Smith、路雪、蒋思源 通过计算机视觉方法识别纹理细密的物体种类已经受到了学界的强烈关注。这一类任务往往是极具挑战...

3285

扫码关注云+社区