人脸检测_人脸检测识别 - CSDN
人脸检测 订阅
《人脸检测》一书由黄福珍,苏剑波所著。本书全方位介绍了人脸检测的基本问题、研究思路和方法、经典的算法和技术,然后介绍了作者的一些研究成果,最后指出了该领域的未来发展方向。 展开全文
《人脸检测》一书由黄福珍,苏剑波所著。本书全方位介绍了人脸检测的基本问题、研究思路和方法、经典的算法和技术,然后介绍了作者的一些研究成果,最后指出了该领域的未来发展方向。
信息
作    者
黄福珍,苏剑波 [1]
定    价
12.00元
书    名
人脸检测
出版时间
2006-4-1
出版社
上海交通大学出版社
ISBN
9787313043665 [1]
人脸检测内容简介
人脸检测的研究具有重要的学术价值,人脸是一类具有相当复杂的细节变化的自然结构目标,对此类目标的挑战性在于:人脸由于外貌、表情、肤色等不同,具有模式的可变性;一般意义下的人脸上,可能存在眼镜、胡须等附属物;作为三维物体的人脸影像不可避免地受由光照产生的阴影的影响。因此,如果能够找到解决这些问题的方法,成功地构造出人脸检测系统,将为解决其他类似的复杂模式的检测问题提供重要的启示。本书对人脸检测的基本问题、研究思路和方法、经典的算法和技术全方位地做了深入系统的介绍,着重介绍了作者在利用活动轮廓模型方法进行人脸检测方面的一些研究成果,指出了该领域的未来发展方向。可作为高等学校有关专业的研究生、高年级本科生、研究院所和有关单位广大科技工作者和工程技术人员的参考书。本书首先对人脸检测的基本问题、研究思路和方法、经典的算法和技术全方位地做了深入系统的介绍,然后着重介绍了作者在利用活动轮廓模型方法进行人脸检测方面的一些研究成果,最后指出了该领域的未来发展方向。本书可作为高等学校有关专业的研究生、高年级本科生、研究院所和有关单位广大科技工作者和工程技术人员的参考书。 [1] 
收起全文
精华内容
参与话题
  • 人脸检测人脸检测算法综述

    万次阅读 2018-07-05 20:50:20
    问题描述人脸检测的目标是找出图像中所有的人脸对应的位置,算法的输出是人脸外接矩形在图像中的坐标,可能还包括姿态如倾斜角度等信息。下面是一张图像的人脸检测结果:虽然人脸的结构是确定的,由眉毛、眼睛、鼻子...

    https://blog.csdn.net/SIGAI_CSDN/article/details/80751476

    问题描述

    人脸检测的目标是找出图像中所有的人脸对应的位置,算法的输出是人脸外接矩形在图像中的坐标,可能还包括姿态如倾斜角度等信息。下面是一张图像的人脸检测结果:


    虽然人脸的结构是确定的,由眉毛、眼睛、鼻子和嘴等部位组成,近似是一个刚体,但由于姿态和表情的变化,不同人的外观差异,光照,遮挡的影响,准确的检测处于各种条件下的人脸是一件相对困难的事情。

    人脸检测算法要解决以下几个核心问题:

     人脸可能出现在图像中的任何一个位置
     人脸可能有不同的大小
     人脸在图像中可能有不同的视角和姿态
     人脸可能部分被遮挡
    

    评价一个人脸检测算法好坏的指标是检测率和误报率。我们将检测率定义为:

    算法要在检测率和误报率之间做平衡,理想的情况是有高检测率,低误报率。

    经典的人脸检测算法流程是这样的:用大量的人脸和非人脸样本图像进行训练,得到一个解决2类分类问题的分类器,也称为人脸检测模板。这个分类器接受固定大小的输入图片,判断这个输入图片是否为人脸,即解决是和否的问题。人脸二分类器的原理如下图所示:

    由于人脸可能出现在图像的任何位置,在检测时用固定大小的窗口对图像从上到下、从左到右扫描,判断窗口里的子图像是否为人脸,这称为滑动窗口技术(sliding window)。为了检测不同大小的人脸,还需要对图像进行放大或者缩小构造图像金字塔,对每张缩放后的图像都用上面的方法进行扫描。由于采用了滑动窗口扫描技术,并且要对图像进行反复缩放然后扫描,因此整个检测过程会非常耗时。

    由于一个人脸附件可能会检测出多个候选位置框,还需要将检测结果进行合并去重,这称为非极大值抑制(NMS)。多尺度滑动窗口技术的原理如下图所示:




    典型应用

    人脸检测是机器视觉领域被深入研究的经典问题,在安防监控、人证比对、人机交互、社交等领域都有重要的应用价值。数码相机、智能手机等端上的设备已经大量使用人脸检测技术实现成像时对人脸的对焦、图集整理分类等功能,各种虚拟美颜相机也需要人脸检测技术定位人脸,然后才能根据人脸对齐的技术确定人脸皮肤、五官的范围然后进行美颜。在人脸识别的流程中,人脸检测是整个人脸识别算法的第一步。

    早期算法

    我们将整个人脸检测算法分为3个阶段,分别是早期算法,AdaBoost框架,以及深度学习时代,在接下来将分这几部分进行介绍。

    早期的人脸检测算法使用了模板匹配技术,即用一个人脸模板图像与被检测图像中的各个位置进行匹配,确定这个位置处是否有人脸;此后机器学习算法被用于该问题,包括神经网络,支持向量机等。以上都是针对图像中某个区域进行人脸-非人脸二分类的判别。

    早期有代表性的成果是Rowley等人提出的方法[1][2]。他们用神经网络进行人脸检测,用20x20的人脸和非人脸图像训练了一个多层感知器模型。文献[1]的方法用于解决近似正面的人脸检测问题,原理如下图所示:


    文献[2]的方法解决多角度人脸检测问题,整个系统由两个神经网络构成,第一个网络用于估计人脸的角度,第二个用于判断是否为人脸。角度估计器输出一个旋转角度,然后用整个角度对检测窗进行旋转,然后用第二个网络对旋转后的图像进行判断,确定是否为人脸。系统结构如下图所示:

    Rowley的方法有不错的精度,由于分类器的设计相对复杂而且采用的是密集滑动窗口进行采样分类导致其速度太慢。


    AdaBoost框架

    接下来介绍AdaBoost框架之后的方法,boost算法是基于PAC学习理论(probably approximately correct)而建立的一套集成学习算法(ensemble learning)。其根本思想在于通过多个简单的弱分类器,构建出准确率很高的强分类器,PAC学习理论证实了这一方法的可行性,感谢大神Leslie-Valiant!!我们首先来看FDDB上各种检测算法的ROC曲线,接下来的介绍将按照这些ROC曲线上的算法进行展开。


    在2001年Viola和Jones设计了一种人脸检测算法[10]。它使用简单的Haar-like特征和级联的AdaBoost分类器构造检测器,检测速度较之前的方法有2个数量级的提高,并且保持了很好的精度,我们称这种方法为VJ框架。VJ框架是人脸检测历史上第一个最具有里程碑意义的一个成果,奠定了基于AdaBoost目标检测框架的基础,所以作为重点和大家唠唠。

    用级联AdaBoost分类器进行目标检测的思想是:用多个AdaBoost分类器合作完成对候选框的分类,这些分类器组成一个流水线,对滑动窗口中的候选框图像进行判定,确定它是人脸还是非人脸。

    在这一系列AdaBoost分类器中,前面的强分类器设计很简单,包含的弱分类器很少,可以快速排除掉大量的不是人脸的窗口,但也可能会把一些不是人脸的图像判定为人脸。如果一个候选框通过了第一级分类器的筛选即被判定为人脸,则送入下一级分类器中进行判定,以此类推。如果一个待检测窗口通过了所有的强分类器,则认为是人脸,否则是非人脸。下图是分类器级联进行判断的示意图:



    这种思想的精髓在于用简单的强分类器在初期快速排除掉大量的非人脸窗口,同时保证高的召回率,使得最终能通过所有级强分类器的样本数很少。这样做的依据是在待检测图像中,绝大部分都不是人脸而是背景,即人脸是一个稀疏事件,如果能快速的把非人脸样本排除掉,则能大大提高目标检测的效率。

    出于性能考虑,弱分类器使用了简单的Haar-like特征,这种特征源自于小波分析中的Haar小波变换,Haar小波是最简单的小波函数,用于对信号进行均值、细节分解。这里的Haar-like特征定义为图像中相邻矩形区域像素之和的差值。下图是基本Haar-like特征的示意图:


    Haar-like特征是白色矩形框内的像素值之和,减去黑色区域内的像素值之和。以图像中第一个特征为例,它的计算方法如下:首先计算左边白色矩形区域里所有像素值的和,接下来计算右边黑色矩形区域内所有像素的和,最后得到的Haar-like特征值为左边的和减右边的和。

    这种特征捕捉图像的边缘、变化等信息,各种特征描述在各个方向上的图像变化信息。人脸的五官有各自的亮度信息,很符合Haar-like特征的特点。

    为了实现快速计算,使用了一种称为积分图(Integral Image)的机制。通过积分图可以快速计算出图像中任何一个矩形区域的像素之和,从而计算出各种类型的Haar-like特征。假设有一张图像,其第i行第j列处的像素值为,积分图定义为:

    即原始图像在任何一点处的左上角元素之和。在构造出积分图之后,借助于它可以快速计算出任何一个矩形区域内的像素之和,以下图中的矩形框为例:

    在上图中,要计算黑色矩形框内的像素值之和。假设上面四个矩形的右下角的坐标分别为

    之所以这样,是因为黑色区域内的像素值之和等于这4个矩形框内的像素值之和,减去上面两个矩形框的像素值之和,再减去左边两个矩形框的像素值之和,这样做的话,左上角的矩形框被减了两遍,因此要加一遍回来。在计算出任何一个矩形区域的像素值之和后,可以方便的计算出上面任何一种Haar-like特征。下图是通过AdaBoost算法自动筛选出来的对区分人脸和非人脸有用的Haar-like特征,基本符合人类的直观感受:

    弱分类器采用最简单的深度很小的决策树,甚至只有一个内部节点。决策树的训练算法此处不做详细的阐述,需要注意的是这里的特征向量是稀疏的,即每一棵决策树只接受少量特征分量的输入,根据它们来做决策。

    强分类器和前面讲述的是一样的,不同的是这里的强分类器加上了一个调节阈值:


    这个式子表明增加分类器的级数会降低检测率。对于前者,可以理解为一个负样本被每一级分类器都判定为正样本的概率;对于后者,可以理解为一个正样本被所有分类器都判定为正样本的概率。

    在VJ算法问世之后,较好的解决了近似正面人脸的检测问题。此后出现了大量改进方案,在深度学习技术出现之前,一直是人脸检测算法的主流框架。这些方案的改进主要在以下几个方面:

    新的特征,包括扩展的Haar特征[4],ACF特征[15]等,它们比标准的Haar-like特征有更强的描述能力,同时计算成本也很低。

    使用其他类型的AdaBoost分类器。VJ框架中采用的是离散型的AdaBoost算法,除此之外,还有实数型,Logit型,Gentle型等各种方案。实数型、Logit型和Gentle型AdaBoost算法不仅能输出分类标签值,还能给出置信度,有更高的精度。

    分类器级联结构,如Soft Cascade,将VJ方法的多个强分类器改成一个强分类器(该算法后面会有介绍)。另外,检测处于各种角度和姿态的人脸是研究另一个重点,VJ方法的分类器级联只有一条路径,是瀑布模型,改进的方案有树状级联,金字塔级联等,篇幅所限这里不做过多解释,各种级联方案如下图所示:

    在深度学习出现以前工业界的方案都是基于VJ算法。但VJ算法仍存在一些问题:

    (1)Haar-like特征是一种相对简单的特征,其稳定性较低;
    (2)弱分类器采用简单的决策树,容易过拟合。因此,该算法对于解决正面的 人脸效果好,对于人
        脸的遮挡,姿态,表情等特殊且复杂的情况,处理效果不理想(虽然有了一些改进方案,但还是
        不够彻底!!)。
    (3 基于VJ-cascade的分类器设计,进入下一个stage后,之前的信息都丢弃了,分类器评价一个
        样本不会基于它在之前stage的表现----这样的分类器鲁棒性差。
    

    ACF[15](Aggregate ChannelFeatures for Multi-view Face Detection)是一种为分类提供足够多的特征选择的方法。在对原图进行处理后,得到多通道的图像,这些通道可以是RGB的通道,可以是平滑滤波得到的,可以是x方向y方向的梯度图等等。将这些通道合起来,在此基础上提取特征向量后续采用Soft-Cascade分类器进行分类。

    相较于VJ-cascade的设计,Soft-Cascade采用几个改进的方案:

    (1)每个stage的决策函数不是二值而是标量值(scalar-valued) ,且与该样本有多"容易"通过这个
         stage以及在这个stage的相对重要性成比例。
    (2)生成的决策函数是需要通过之前每个阶段的值而不单单是本阶段来判定。
    (3)文中把检测器的运行时间-准确率权衡通过一个叫ROC surface的3维曲面清楚的展示出来,方便
        调节参数,可以明确的知道动了哪个参数会对这个检测器的性能会有些什么影响。

    DMP模型

    DPM(Deformable Part Model),正如其名称所述,可变形的组件模型,是一种基于组件的检测算法,其所见即其意。该模型由Felzenszwalb在2008年提出,并发表了一系列的CVPR,NIPS会议。并且还拿下了2010年,PASCAL VOC的“终身成就奖”。

    由于DPM算法[16]本身是一种基于组件的检测算法,所以对扭曲,性别,多姿态,多角度等的人脸都具有非常好的检测效果(人脸通常不会有大的形变,可以近似为刚体,基于DMP的方法可以很好地处理人脸检测问题)。


    DPM的方法采用的是FHOG进行特征的提取,作者对HOG进行了很大的改动,没有直接采用4*9=36维向量,而是对每个8x8的cell提取18+9+4=31维特征向量。作者还讨论了依据PCA(Principle Component Analysis)可视化的结果选9+4维特征,能达到HOG 4*9维特征的效果。基于DPM的方法在户外人脸集上都取得了比Viola-Jones更好的效果,但是由于该模型过于复杂,判断时计算复杂,很难满足实时性的要求。后续有了一些列改进的流程,比如加入级联分类器,针对特征计算采用了积分图的方法等,但都还没有达到VJ方法的效率。


    DPM模型一个大的问题是速度太慢,因此在工程中很少使用,一般采用的是AdaBoost框架的算法。

    基于经典的人工设计特征本身稳定性并不稳定,容易受外界环境的影响(光照、角度、遮挡等),所以在复杂场景下的人脸检测性能很难的到保证,只能应用到受限的场景中。深度学习出现以后,DCNN(深度卷积神经网络)能很好的学习到图像中目标物各个层级的特征,对外界的抗干扰能力更强,后序的人脸检测方法基本都基于DCNN的特征来优化了。

    基于深度学习的方法在FDDB上基本饱和了,是时候抛出一个新的benchmark了!!!WIDERFace测试集上各种算法的性能:

    深度学习框架

    卷积神经网络在图像分类问题上取得成功之后很快被用于人脸检测问题,在精度上大幅度超越之前的AdaBoost框架,当前已经有一些高精度、高效的算法。直接用滑动窗口加卷积网络对窗口图像进行分类的方案计算量太大很难达到实时,使用卷积网络进行人脸检测的方法采用各种手段解决或者避免这个问题。

    Cascade CNN

    Cascade CNN[17]可以认为是传统技术和深度网络相结合的一个代表,和VJ人脸检测器一样,其包含了多个分类器,这些分类器采用级联结构进行组织,然而不同的地方在于,Cascade CNN采用卷积网络作为每一级的分类器。

    构建多尺度的人脸图像金字塔,12-net将密集的扫描这整幅图像(不同的尺寸),快速的剔除掉超过90%的检测窗口,剩下来的检测窗口送入12-calibration-net调整它的尺寸和位置,让它更接近潜在的人脸图像的附近。

    采用非极大值抑制(NMS)合并高度重叠的检测窗口,保留下来的候选检测窗口将会被归一化到24x24作为24-net的输入,这将进一步剔除掉剩下来的将近90%的检测窗口。和之前的过程一样,通过24-calibration-net矫正检测窗口,并应用NMS进一步合并减少检测窗口的数量

    将通过之前所有层级的检测窗口对应的图像区域归一化到48x48送入48-net进行分类得到进一步过滤的人脸候选窗口。然后利用NMS进行窗口合并,送入48-calibration-net矫正检测窗口作为最后的输出。




    12x12,24x24,48x48尺寸作为输入的矫正(calibration)CNN网络结构。其中输出为45中种矫正模式的类别。

    文中影响区域位置和大小的因素有三种:尺度、X方向偏移、Y方向偏移。总共构成了5x3x3=45种模式。



    Cascade CNN一定程度上解决了传统方法在开放场景中对光照、角度等敏感的问题,但是该框架的第一级还是基于密集滑动窗口的方式进行窗口过滤,在高分辨率存在大量小人脸(tiny face)的图片上限制了算法的性能上限。

    DenseBox

    文献[18]提出了一种称为DenseBox的目标检测算法,适合人脸这类小目标的检测。这种方法使用全卷积网络,在同一个网络中直接预测目标矩形框和目标类别置信度。通过在检测的同时进行关键点定位,进一步提高了检测精度。

    检测时的流程如下:
    1.对待检测图像进行缩放,将各种尺度的图像送入卷积网络中处理,以检测不同大小的目标。
    2.经过多次卷积和池化操作之后,对特征图像进行上采样然后再进行卷积,得到最终的输出图像,这张
      图像包含了每个位置出现目标的概率,以及目标的位置、大小信息。
    3.由输出图像得到目标矩形框。
    4.非最大抑制,得到最终的检测结果。
    

    在检测时卷积网络接受 m\times n 的输入图像,产生5个通道的 m/4\times n/4 输出图像。假设目标矩形左上角 p_{t} 的坐标为 (x_{t},y_{t}) ,右下角 p_{b} 的坐标为 (x_{b},y_{b}) 。输出图像中位于点( x_{i},y_{i} )处的像素用5维向量描述了一个目标的矩形框和置信度信息:


    第一个分量是候选框是一个目标的置信度,后面4项分别为本像素的位置与矩形框左上角、右下角的距离。每个像素都转化成一个矩形框和置信度值,然后对置信度值大于指定阈值的矩形框进行非最大抑制,得到最终检测结果。

    backbone从VGG 19网络改进得到,包含16个卷积层。前12个卷积层用VGG 19的模型进行初始化。卷积层conv4_4的的输出被送入4个 的卷积层中。第一组的两个卷积层产生1通道的输出图像作为置信度得分;第二组的两个卷积层产生4通道的输出图像作为矩形框的4个坐标。网络的输出有两个并列的分支,分别表示置信度和矩形框位置预测值。整个网络的结构如下图所示:


    DenseBox的网络结构

    为了提高检测精度,采用了多尺度融合的策略。将conv3_4和conv_4_4的卷积结果拼接起来送入后面处理。由于两个层的输出图像大小不同,在这里用了上采样和线性插值对小的图像进行放大,将两种图像尺寸变为相等。

    由于输出层有两个并列分支,损失函数由两部分组成。第一部分输出值为分类置信度即本位置是一个目标的概率,用表示。真实的类别标签值为,取值为0或者1,分别表示是背景和目标。分类损失函数定义为:


    Faceness-Net

    Faceness-Net[19]是一个典型的由粗到精的工作流,借助了多个基于DCNN网络的facial parts分类器对人脸进行打分,然后根据每个部件的得分进行规则分析得到Proposal的人脸区域,最后通过一个Refine的网络得到最终的人脸检测结果。整体流程如图 Faceness(b)。




    系统主要包含了2个阶段:

    第1阶段:生成partness map,由局部推理出人脸候选区域。

    根据attribute-aware深度网络生成人脸部件map图(partness map),如上图Faceness(a)中的颜色图,文章共使用了5个部件:hair,eye,nose,mouth,beard. 通过part的结合计算人脸的score.部件与部件之间是有相对位置关系的,比如头发在眼睛上方,嘴巴在鼻子下方,因此利用部件的spatial arrangement可以计算face likeliness. 通过这个打分对原始的人脸proposal进行重排序. 如图Faceness(b)。

    第2阶段:Refining the face
    hypotheses

    上一阶段proposal生成的候选框已经有较高的召回率,通过训练一个人脸分类和边界回归的CNN可以进一步提升其效果。

    Faceness的整体性能在当时看来非常令人兴奋。此前学术界在FDDB上取得的最好检测精度是在100个误检时达到84%的检测率,Faceness在100个误检时,检测率接近88%,提升了几乎4个百分点;除了算法本身的精度有很大提升,作者还做了很多工程上的优化比如:通过多个网络共享参数,降低网络参数量 83%;采用多任务的训练方式同一网络实现不同任务等。

    MTCNN

    MTCNN[20]顾名思义是多任务的一个方法,它将人脸区域检测和人脸关键点检测放在了一起,同Cascade CNN一样也是基于cascade的框架,但是整体思路更加巧妙合理,MTCNN总体来说分为三个部分:PNet、RNet和ONet,如下图所示:

    Cascade CNN第一级的12-net需要在整张图片上做密集窗口采样进行分类,缺陷非常明显;MTCNN在测试第一阶段的PNet是全卷积网络(FCN),全卷积网络的优点在于可以输入任意尺寸的图像,同时使用卷积运算代替了滑动窗口运算,大幅提高了效率。下图为不同尺度图像经过PNet的密集分类响应图,亮度越高代表该区域是人脸的概率越大(dense prediction
    response map)。

    除了增加人脸5个关键点的回归任务,另外在calibration阶段采用了直接回归真实位置坐标的偏移量的思路替代了Cascade CNN中的固定模式分类方式,整个思路更为合理。

    MTCNN的整体设计思路很好,将人脸检测和人脸对齐集成到了一个框架中实现,另外整体的复杂度得到了很好的控制,可以在中端手机上跑20~30FPS。该方法目前在很多工业级场景中得到了应用。

    先抛出一张据说是目前世界上人数最多的合照吓吓大家。一眼望过去能估计下有多少人吗?因为本文对小目标人脸检测有很多独到的理解,我们下面会多花点笔墨去分析!


    HR

    之前我们讲过的一些方法都没有针对小目标去分析,小目标检测依然是检测领域的一个难题,[21]本文作者提出的检测器通过利用尺度,分辨率和上下文多种信息融合来检测小目标,在上图的总共1000个人脸中成功检测到约800个,检测器的置信度由右侧的色标表示。

    针对小目标人脸检测,作者主要从三个方面做了研究:尺度不变,图像分辨率和上下文,作者的算法在FDDB和WIDERFace取得了当时最好的效果。

    作者分析了小目标人脸检测的三个问题:

    Multi-task modeling of scales

    一方面,我们想要一个可以检测小人脸的小模板;另一方面,我们想要一个可以利用详细特征(即面部)的大模板来提高准确性。取代“一刀切”的方法,作者针对不同的尺度(和纵横比)分别训练了检测器。虽然这样的策略提升了大目标检测的准确率,但是检测小目标仍然具有挑战性。

    How to generalize pre-trained networks?

    关于小目标检测的问题,作者提出了两个见解。

    如何从预训练的深度网络中最佳地提取尺度不变的特征。

    虽然许多应用于“多分辨率”的识别系统都是处理一个图像金字塔,但我们发现在插值金字塔的最底层对于检测小目标尤为重要。

    因此,作者的最终方法是:通过尺度不变方式,来处理图像金字塔以捕获大规模变化,并采用特定尺度混合检测器,如下图:


    (a)单一尺度模板和图像金字塔
    (b)不同尺度模板和单一图像
    (c)粗略尺度模板和粗略图像金字塔,(a)和(b)的结合
    (d)含有上下文信息的固定大小多尺度模板和粗略图像金字塔
    (e)定义了从深度模型的多个层中提取的特征模板,也就是foveal descriptors

    How best to encode context?

    作者证明从多个层中提取的卷积深度特征(也称为 “hypercolumn” features)是有效的“ foveal”描述符,其能捕获大感受野上的高分辨率细节和粗略的低分辨率线索。


    从输入图像开始,首先创建一个图像金字塔(2x插值)。然后我们将缩放的输入图像输入到CNN中,获得不同分辨率下人脸预测响应图(后续用于检测和回归)。最后将在不同尺度上得到的候选区域映射回原始分辨率图像上,应用非极大值抑制(NMS)来获得最终检测结果。

    Face R-CNN

    [22]该方法基于Faster R-CNN框架做人脸检测,针对人脸检测的特殊性做了优化。

    对于最后的二分类,在softmax的基础上增加了center loss。通过加入center loss使得类内的特征差异更小(起到聚类的作用),提高正负样本在特征空间的差异性从而提升分类器的性能。

    加入在线困难样本挖掘(OHEM),每次从正负样本中各选出loss最大的N个样本加入下次训练,提高对困难样本的的分类能力。

    多尺度训练,为了适应不同尺度影响(或者更好地检测小目标),训练阶段图片会经过不同尺度缩放。


    SSH

    [23] SSH最大的特色就是尺度不相关性(scale-invariant),比如MTCNN这样的方法在预测的时候,是对不同尺度的图片分别进行预测,而SSH只需要处以一个尺度的图片就可以搞定。实现方式就是对VGG网络不同level的卷积层输出做了3个分支(M1,M2,M3),每个分支都使用类似的流程进行检测和分类,通过针对不同尺度特征图进行分析,变相的实现了多尺度的人脸检测。


    M1和M2,M3区别有点大,首先,M1的通道数为128,M2,M3的通道数为512,这里,作者使用了1*1卷积核进行了降维操作。其次,将conv4_3卷积层输出和conv5_3卷积层输出的特征进行了融合(elementwise sum),由于conv5_3卷积层输出的大小和conv4_3卷积层输出的大小不一样,作者对conv5_3卷积层的输出做了双线性插值进行上采样。

    其中,M模块如上图所示,包含了分类和回归2个任务,其中Context Module的为了获得更多的上下文信息,更大的感受野,对该模块使用了等价的5*5和7*7的卷积分别进行操作,然后进行特征的concat最终形成了上图的Context Module。(由于大的卷积核效率问题,根据INCEPTION的思想,使用2个3*3的卷积核替代一个5*5的卷积核,使用3个3*3的卷积核替换1个7*7的卷积核)。

    PyramidBox

    这张图又出现了!!!这一次是百度的“PyramidBox”[24]跑出来的结果。880个人脸!!!


    PyramidBox从论文看主要是已有技术的组合应用,但是作者对不同技术有自己很好的理解,所以能组合的很有效,把性能刷的非常高。


    Architecture of PyramidBox

    针对之前方法对上下文信息的利用不够充分的问题,作者提出了自己的优化方案:

    1. 提出了一种基于 anchor 的上下文信息辅助方法PyramidAnchors,从而可以引入监督信息来学习较小的、模糊的和部分遮挡的人脸的上下文特征(下图中紫色的人脸框为例可以看到P3,P4,P5的层中框选的区域分别对应face、head、body)。

    2. 设计了低层特征金字塔网络 ( Low-level Feature
    Pyramid Networks ) 来更好地融合上下文特征和面部特征,该方法在一次前向过程中(in a single shot)可以很好地处理不同尺度的人脸。

    3. 文中提出了一种上下文敏感的预测模块,该模块由一个混合网络结构和max-in-out层组成,该模块可以从融合特征中学习到更准确的定位信息和分类信息(文中对正样本和负样本都采用了该策略,针对不同层级的预测模块为了提高召回率对正负样本设置了不同的参数)。max-in-out参考的maxout激活函数来自GAN模型发明人Ian J,Goodfellow,它对上一层的多个feature map跨通道取最大值作为输出,在cifar10和cifar100上相较于ReLU取得了更好的效果。

    4. 文中提出了尺度敏感的Data-anchor-采样策略,改变训练样本的分布,重点关注了较小的人脸。

    结束语

    人脸做为计算机视觉的一个大的研究方向,很多科研人员在上面投入了大量精力,每年出来上百篇相关论文,本文中不一一列举,文中讲述分析如有不妥之处请多包涵指正!


    展开全文
  • 要实现人脸对比,首先要实现的是人脸检测,在摄像头拍摄到的一张图片中,正确的检测到人脸的位置,并且将人脸提取出来。考虑到免费开源,OpenCV 就可以很好的实现这个功能。OpenCVC 在linux 的安装可以参考前面的...

        人脸对比是现在比较常用的功能,比如出租车司机人脸与司机驾照照片对比,门禁系统中进入者的人脸与人脸库中的人脸进行对比。要实现人脸对比,首先要实现的是人脸检测,在摄像头拍摄到的一张图片中,正确的检测到人脸的位置,并且将人脸提取出来。考虑到免费开源,OpenCV 就可以很好的实现这个功能。OpenCVC 在linux 的安装可以参考前面的博客:ubuntu 16.04 OpenCV3.2.0完全编译安装

    (一)人脸检测的实现:

        下面的代码由OpenCVC实例改进而来,它能够实现人脸检测和人眼睛的检测,将检测到的结果用圆圈圈出来。代码如下:

    /*============================================================================= 
    #     FileName: facecheck.cpp
    #         Desc: detect faces and eyes by opencv ,and then cut the face      
    #       Author: Licaibiao 
    #      Version:  
    #   LastChange: 2017-10-31 
    #      History: 
    =============================================================================*/ 
    #include <opencv2/objdetect/objdetect.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <iostream>
    #include <stdio.h>
    
    using namespace std;
    using namespace cv;
     
    #define CASCADENAME			"./modle/haarcascade_frontalface_alt2.xml"
    #define NESTEDCASCADENAME	"./modle/haarcascade_eye_tree_eyeglasses.xml"
    #define FACEPHOTO_FACENAME  "./image/result.jpg"
    #define DETECT_IMAGE		"./image/001.jpg"
    
     
    void detectAndDraw( Mat& img, CascadeClassifier& cascade,
    	CascadeClassifier& nestedCascade, double scale, bool tryflip )
    {
        double t = 0;
        vector<Rect> faces, faces2;
    	/* 定义七种颜色用于人脸标记 */
        const static Scalar colors[] =
        {
            Scalar(255,0,0),
            Scalar(255,128,0),
            Scalar(255,255,0),
            Scalar(0,255,0),
            Scalar(0,128,255),
            Scalar(0,255,255),
            Scalar(0,0,255),
            Scalar(255,0,255)
        };
    	
        Mat gray, smallImg;
    	
    	/* 因为用的是类haar特征,所以都是基于灰度图像的,这里要转换成灰度图像 */
        cvtColor( img, gray, COLOR_BGR2GRAY );
    	
    	/* 将图片缩小,加快检测速度 */
        double fx = 1 / scale;
    	/* 将尺寸缩小到1/scale, 用线性插值 */
        resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR );
    	/* 直方图均衡 */
        equalizeHist( smallImg, smallImg );
     
    	/* 用来计算算法执行时间 */
        t = (double)getTickCount();
    	
    	/*人脸检测
    		smallImg:输入的原图
    		faces	:表示检测到的人脸目标序列
    		1.1		:每次图像尺寸减小的比例为1.1
    		2		:每一个目标至少要被检测到3次才算是真的目标
    		CV_HAAR_SCALE_IMAGE:表示不是缩放分类器来检测,而是缩放图像
    		Size(30, 30) 目标的最大最小尺寸
    	*/
        cascade.detectMultiScale( smallImg, faces, 1.1, 2, CASCADE_SCALE_IMAGE, Size(30, 30) );
        if( tryflip )
        {
            flip(smallImg, smallImg, 1);
            cascade.detectMultiScale( smallImg, faces2,1.1, 2, 0|CASCADE_SCALE_IMAGE,Size(30, 30) );
            for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); ++r )
            {
                faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
            }
        }
    	
    	/* 相减为算法执行的时间 */
        t = (double)getTickCount() - t;
        printf( "detection time = %g ms\n", t*1000/getTickFrequency());
        
    	for ( size_t i = 0; i < faces.size(); i++ )
        {
            Rect r = faces[i];
            Mat smallImgROI;
            vector<Rect> nestedObjects;
            Point center;
            Scalar color = colors[i%8];
            int radius;
    		
    		/* 人脸长宽比例,在0.75-1.3 间画圆,其他范围画矩形 */
            double aspect_ratio = (double)r.width/r.height;
            if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
            {
    			/*还原原来尺寸 计算圆心和圆半径 */
                center.x = cvRound((r.x + r.width*0.5)*scale);
                center.y = cvRound((r.y + r.height*0.5)*scale);
                radius = cvRound((r.width + r.height)*0.25*scale);
    			/* 画出人脸检测区域 画圆 */
                circle( img, center, radius, color, 3, 8, 0 );
            }
            else
    		{
    			/* 画出检测区域,画矩形 */
    			rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)),
    				cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), color, 3, 8, 0);
    		}
    		
    		/* 检测到人眼,在人脸上画出人眼 */
            if( nestedCascade.empty())
    		{
    			continue;
    		}
                
            smallImgROI = smallImg( r );
    		
    		/* 人眼检测 */
            nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 1.1, 2, CASCADE_SCALE_IMAGE, Size(30, 30) );	
            for ( size_t j = 0; j < nestedObjects.size(); j++ )
            {
                Rect nr = nestedObjects[j];
    			/*还原原来尺寸 计算圆心和圆半径 */
                center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);
                center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);
                radius = cvRound((nr.width + nr.height)*0.25*scale);
                /* 画出人眼检测区域 画圆*/
    			circle( img, center, radius, color, 3, 8, 0 );
            }
        }
    	/* 显示图像 img */
        imshow( "result", img );
    }
     
     
    int main( int argc, const char** argv )
    {
        Mat frame, image;
        bool tryflip;
        CascadeClassifier cascade, nestedCascade;
        double scale = 1.3;
     
    	/* 加载分类器 */
        if ( !nestedCascade.load( NESTEDCASCADENAME ) )
    	{
    		cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
    	}   
        if( !cascade.load( CASCADENAME ) )
        {
            cerr << "ERROR: Could not load classifier cascade" << endl;
            return -1;
        }
    	
    	/* 加载图片 */
    	image = imread(DETECT_IMAGE, 1 );
        if(image.empty()) 
    	{
    		cout << "Couldn't read iamge" << DETECT_IMAGE  <<  endl;
    		
    	}
    	
        cout << "Detecting face(s) in " << DETECT_IMAGE << endl;
        
    	/* 检测人脸及眼睛并画出检测到的区域 */
    	if( !image.empty() )
        {
            detectAndDraw( image, cascade, nestedCascade, scale, tryflip );
            waitKey(0);
        }
        return 0;
    }
    

    要编译运行上面的代码需要注意几个地方
    (1)haarcascade_frontalface_alt2.xml 和haarcascade_eye_tree_eyeglasses.xml 是opencv 中提供的文件。
    (2)由于opencv源码安装的时候需要下载一些文件,网速慢的地方安装容易失败。如果使用sudo apt-get install libopencv-dev python-opencv 命令直接安装的,编译的时候需要带参数`pkg-config --cflags --libs opencv`

    编译运行结果:

    licaibiao@ubuntu:~/OpenCV/FaceTest$ make DetectDraw 
    g++ FaceDetect_Draw.cpp -o TestDetectDraw `pkg-config --cflags --libs opencv` 
    licaibiao@ubuntu:~/OpenCV/FaceTest$ ls
    FaceCheck.cpp  FaceCheck_Draw.cpp  FaceDetect.cpp  FaceDetect_Draw.cpp  image  Makefile  modle  out  TestDetectDraw
    licaibiao@ubuntu:~/OpenCV/FaceTest$ ./TestDetectDraw 
    Detecting face(s) in ./image/001.jpg
    detection time = 423.166 ms
    

    实际检测效果如下:

    上面是比较正常的一张图片,人脸明显,图片背景比较的干净,所以检测出来的人脸和人的眼睛都是正确的。尝试换一张比较复杂的图片,它的检测功能就没有那么的好了。同样的代码,同样的训练文件,结果如下:

        从上图可以看出可以检测到人脸,但没有全部检测出来,同时还有好几个是误判的。从这里可以看出,使用Opencv原始的训练文件做人脸检测,可以检测到人脸,但是检测的效果并不是很好。

        在实际的使用OpenCVC做人脸检测的时候,为了提高识别率,可以通过检测到人脸再检测判断是否有人眼睛来加以判断。如果是在嵌入式设备中,还是不建议使用OpenCV来做人脸检测和人脸抠图这样的处理。一是OpenCV依赖的文件比较多,需要比较大的存储空间来放库文件和训练文件。二十它的检测效果并不是很好。

        接下来将介绍MTCNN,这也是一套开源的人脸识别代码,全用C和C++编写,代码量小,检测效果好,下一篇介绍。

        这一张的测试代码可以在这里下载:OpenCV测试代码

        里面有一套在可以在海思开发板上跑的和一些在PC机测试测代码,比较乱没有整理,有需要的可以参考一下,使用代码前需要在电脑上正确安装OpenCV。

    licaibiao@ubuntu:~/OpenCV$ tree -L 2
    .
    ├── arm_test
    │   ├── 001.jpg
    │   ├── example.cpp
    │   ├── haarcascade_eye_tree_eyeglasses.xml
    │   ├── haarcascade_frontalface_alt2.xml
    │   ├── include
    │   ├── lib
    │   ├── Makefile
    │   ├── OpencvFaceAPI.cpp
    │   ├── OpencvFaceAPI.h
    │   └── OpencvTestMain.cpp
    ├── face_test
    │   ├── detect.cpp
    │   ├── example_1.cpp
    │   ├── example.cpp
    │   ├── example.cpp_ok
    │   ├── face_detect1.cpp
    │   ├── face_detect.cpp
    │   ├── facedetect.cpp
    │   ├── haarcascade_eye_tree_eyeglasses.xml
    │   ├── haarcascade_eye.xml
    │   ├── haarcascade_frontalface_alt2.xml
    │   ├── haarcascade_frontalface_default.xml
    │   ├── Makefile
    │   ├── run.sh
    │   └── test
    └── FaceTest
        ├── FaceCheck.cpp
        ├── FaceCheck_Draw.cpp
        ├── FaceDetect.cpp
        ├── FaceDetect_Draw.cpp
        ├── image
        ├── Makefile
        ├── modle
        ├── out
        └── TestDetectDraw
    
    8 directories, 28 files
    licaibiao@ubuntu:~/OpenCV$ 

    展开全文
  • 人脸检测算法

    千次阅读 2018-08-27 10:42:12
    人脸识别各论文参考   知乎一个栏目: https://zhuanlan.zhihu.com/p/25025596   首先介绍一下常用人脸检测的常用数据库: FDDB和WIDER FACE   FDDB总共2845张图像,51...

    https://handong1587.github.io/deep_learning/2015/10/09/object-detection.html

    人脸识别各论文参考

     

    知乎一个栏目:

    https://zhuanlan.zhihu.com/p/25025596

     

    首先介绍一下常用人脸检测的常用数据库:

    FDDB和WIDER FACE

     

    FDDB总共2845张图像,5171张,人脸非约束环境,人脸的难度较大,有面部表情,双下巴,光照变化,穿戴,夸张发型,遮挡等难点,是目标最常用的数据库。有以下特点:

    • 图像分辨率较小,所有图像的较长边缩放到450,也就是说所有图像都小于450*450,最小标注人脸20*20,包括彩色和灰度两类图像;
    • 每张图像的人脸数量偏少,平均1.8人脸/图,绝大多数图像都只有一人脸;
    • 数据集完全公开,published methods通常都有论文,大部分都开源代码且可以复现,可靠性高;unpublished methods没有论文没有代码,无法确认它们的训练集是否完全隔离,持怀疑态度最好,通常不做比较。(扔几张FDDB的图像到训练集,VJ也可以训练出很高的召回率。。需要考虑人品能不能抵挡住利益的诱惑)
    • 有其他隔离数据集无限制训练再FDDB测试,和FDDB十折交叉验证两种,鉴于FDDB图像数量较少,近几年论文提交结果也都是无限制训练再FDDB测试方式,所以,如果要和published methods提交结果比较,请照做。山世光老师也说十折交叉验证通常会高1~3%。
    • 结果有离散分数discROC和连续分数contROC两种,discROC仅关心IoU是不是大于0.5,contROC是IoU越大越好。鉴于大家都采用无限制训练加FDDB测试的方式,detector会继承训练数据集的标注风格,继而影响contROC,所以discROC比较重要,contROC看看就行了,不用太在意。

    WIDER FACE:

     

    WIDER FACE总共32203图像,393703标注人脸,目前难度最大,各种难点比较全面:尺度,姿态,遮挡,表情,化妆,光照等。有以下特点有:

    • 图像分辨率普遍偏高,所有图像的宽都缩放到1024,最小标注人脸10*10,都是彩色图像;
    • 每张图像的人脸数据偏多,平均12.2人脸/图,密集小人脸非常多;
    • 分训练集train/验证集val/测试集test,分别占40%/10%/50%,而且测试集的标注结果(ground truth)没有公开,需要提交结果给官方比较,更加公平公正,而且测试集非常大,结果可靠性极高;
    • 根据EdgeBox的检测率情况划分为三个难度等级:Easy, Medium, Hard。

     

    有关人脸识别,主要分为两个步骤算法,人脸检测算法和人脸识别算法。本文总结介绍最近几年常用的人脸检测算法,方便自己以后参考。

    1.SSD

    这篇博文介绍了SSD跑自己数据的做法

    https://blog.csdn.net/wfei101/article/details/78821575

    SSD关键点分为两类:模型结构和训练方法。模型结构包括:多尺度特征图检测网络结构和anchor boxes生成;训练方法包括:ground truth预处理和损失函数。

    文章的核心之一是作者同时采用lower和upper的feature map做检测。假定有8×8和4×4两种不同的feature map。第一个概念是feature map cell,feature map cell 是指feature map中每一个小格子,假设分别有64和16个cell。另外有一个概念:default box,是指在feature map的每个小格(cell)上都有一系列固定大小的box,如下图有4个(下图中的虚线框,仔细看格子的中间有比格子还小的一个box)。假设每个feature map cell有k个default box,那么对于每个default box都需要预测c个类别score和4个offset,那么如果一个feature map的大小是m×n,也就是有m*n个feature map cell,那么这个feature map就一共有(c+4)*k * m*n 个输出。这些输出个数的含义是:采用3×3的卷积核对该层的feature map卷积时卷积核的个数,包含两部分(实际code是分别用不同数量的3*3卷积核对该层feature map进行卷积):数量ckmn是confidence输出,表示每个default box的confidence,也就是类别的概率;数量4kmn是localization输出,表示每个default box回归后的坐标)。训练中还有一个东西:prior box,是指实际中选择的default box(每一个feature map cell 不是k个default box都取)。也就是说default box是一种概念,prior box则是实际的选取。训练中一张完整的图片送进网络获得各个feature map,对于正样本训练来说,需要先将prior box与ground truth box做匹配,匹配成功说明这个prior box所包含的是个目标,但离完整目标的ground truth box还有段距离,训练的目的是保证default box的分类confidence的同时将prior box尽可能回归到ground truth box。 举个列子:假设一个训练样本中有2个ground truth box,所有的feature map中获取的prior box一共有8732个。那个可能分别有10、20个prior box能分别与这2个ground truth box匹配上。训练的损失包含定位损失和回归损失两部分。

    SSD算法的缺点:优势是速度快,在GPU上能实时,缺点是对密集小目标的检测比较差,而人脸刚好是密集小目标,这类方法的研究重点是提高密集小目标的检测性能,同时速度也需要尽可能快,GPU实时算法在应用中依然受限。

     

    2.S3FD

    github代码:

    https://github.com/sfzhang15/SFD

    这篇文章对anchor对小人脸检测率低的问题进行了分析和改进。

    基于anchor方法的缺点:

    Anchor-based方法没有scale-invariant(尺度不变性).对大物体检测的好,对小物体不行。

    没有尺度不变性的原因:

     

    • 不适当的网络结构:后面的步长会变很大,会忽略掉一部分小的物体
    • anchor合适问题:因为anchor设计的问题,导致有些小脸没有足够多的anchor与其相匹配,故而降低了检测率。
    • anchor尺寸问题:若降低anchor的尺度(如在conv3_3加入小尺度的anchor),会大大增加负样本数量。

    改进:

     

    • 作者重新设置了anchor的尺度。并且作者认为stride决定了anchor的间隔。所以设置每层stride的大小为每层anchor尺度的1/4.作者称其为equal-proportion interval principle。
    • 为了使某些小物体有足够多的anchor与其相匹配,所以适当降低了阈值。

    速度比较慢。

     

    3.MTCNN

     

    该算法直接实现了人脸检测和人脸对其。其结构是是三个CNN级联:

    ​ P-net R-net O-net

    ​ 主要是人脸landmark检测

     

    Stage 1:使用P-Net是一个全卷积网络,用来生成候选窗和边框回归向量(bounding box regression vectors)。使用Bounding box regression的方法来校正这些候选窗,使用非极大值抑制(NMS)合并重叠的候选框。全卷积网络和Faster R-CNN中的RPN一脉相承。

    Stage 2:使用N-Net改善候选窗。将通过P-Net的候选窗输入R-Net中,拒绝掉大部分false的窗口,继续使用Bounding box regression和NMS合并。

     

    Stage 3:最后使用O-Net输出最终的人脸框和特征点位置。和第二步类似,但是不同的是生成5个特征点位置。

     


    该代码实现了mtcnn人脸检测部分:(最终结果为画框)

     

    https://github.com/DuinoDu/mtcnn

     

    该代码实现了mtcnn python版本:(还没跑过)

    https://github.com/dlunion/mtcnn

    展开全文
  • 人脸检测

    万次阅读 2019-12-06 16:46:21
    人脸检测 人脸检测目的就是在一张图中找到所有的人脸。本次分享只针对人脸检测,不涉及到人脸识别。 人脸检测几种常用的方法: ①早期的人脸检测方法是利用人工提取特征,训练分类器,进行人脸检测。例如...

    人脸检测

           人脸检测目的就是在一张图中找到所有的人脸。本次分享只针对人脸检测,不涉及到人脸识别。

     

    人脸检测几种常用的方法:

    ①  早期的人脸检测方法是利用人工提取特征,训练分类器,进行人脸检测。例如opencv源码中自带的人脸检测器就是利用haar特征进行的人脸检测。这类方法的缺点就是在环境变化强烈的时候检测效果不理想,例如弱光条件,人脸不全。

    ②  从通用的目标检测算法中继承过来的人脸检测算法。例如利用faster-RCNN来检测人脸。效果不错,可以适应环境变化和人脸不全等问题,但是时间消耗很高。

    ③  鉴于以上两种方法的优劣势,就有人专门研究了人脸检测的算法,同时规避了以上两种的劣势,兼具时间和性能两个优势。级联结构的卷积神经网络,例如,cascadeCNN,MTCNN。MTCNN效果要比cascadeCNN要好。

     

    目前人脸检测任务主要是有两个方面的挑战:

    ①   召回率:复杂背景下的人脸的尺度变化和光照等外部因素变化导致的人脸分类困难。

           (在CNN方法下解决此类问题一般都是通过加入此类样本进行训练解决问题。)

    ②  耗时:人脸多尺度位置定位导致的时间消耗。

     

    MTCNN算法介绍

           MTCNN(多任务级联卷积神经网络)由三个部分组成,P-Net(proposal Network),R-Net(refineNet),O-Net(outputNet)。这三个部分是相互独立的三个网络结构,相互串联的关系。每个阶段的网络都是一个多任务网络,处理的任务有三个:人脸/非人脸的判断、人脸框回归、特征点定位。

     

           流程说明:

           原始待检测图像经过resize,生成不同尺寸的图像构建图像金字塔作为网络的输入。

    构建的图像金字塔,其层数由两个因素决定,第一个是设置的最小人脸minSize,第二个是缩放因子factor,最小人脸表示min(w,h),论文中说明最小人脸不能小于12,给出的缩放因子0.709可以根据公式计算图像金字塔的层数

    minL=org_L*(12/minsize)*factor^(n),n={0,1,2,3,...,N}

    其中n就是金字塔的层数,org_L是输入原始图像的最小边min(W,H),minisize是人为根据应用场景设定,在保证minL大于12的情况下,所有的n就构成金字塔的层。所以minsize的值越小,n的取值范围就越大,计算量就相应地增加,能够检测到的人脸越小。

     

     

    第一阶段,通过浅层的CNN(P-Net)快速生成候选窗口,该网络全部由卷积层实现,获取到候选人脸窗和人脸窗的回归向量,基于人脸窗的回归向量对人脸窗进行校正,然后对所有人脸窗进行NMS(非极大值抑制),合并高度重叠的人脸窗。其具体过程就是通过图像金字塔生成的各种尺寸大小的图片,每一张图都进行一次前向传播,在每个图上得到的结果之后利用设置的阈值去掉一部分,剩下的根据缩放尺度还原到原图上的坐标,将所有的坐标信息汇总,然后NMS去除一部分冗余。

           第二阶段,通过一个更复杂的CNN来处理第一阶段中被误认为人脸的“人脸窗”从而精细化人脸窗,第一阶段的输出作为第二阶段的输入,第一阶段最后产生了大量的bbox,将这些bbox根据缩放因子回推到原图上之后,将他们全部resize到24x24大小,作为第二阶段的输入。第二阶段经过网络之后同样产生大量的bbox,同样的根据阈值去掉一部分,再利用nms去掉一部分。

     

           第三阶段,使用第二阶段中最后留下来的bbox,还原到原来的图片上之后,全部resize到48x48大小,然后输入到第三阶段,使用更为复杂的CNN进一步精细化结果并输出人脸上的5个特征点。

           通过三阶的级联卷积神经网络对任务进行从粗到细的处理,并提出一种新的在线困难样本生成策略提升性能,最终输出人脸框位置和五个特征点位置。整个过程中会用到三次人脸窗回归和NMS,三个网络独立工作。

     

    关于NMS

           简单来说,输入一个图片,分类器会产生多个候选框,每个候选框会有一个得分,分数就是此框是人脸的概率。

           例如这张图,一共产生了4个候选框,每个候选框都有一个得分。右下角的框得分最低,如果我们这是NMS阈值为0.6,那么这个框直接被干掉,然后川普脸上还有两个框,有一定重叠,要想去掉一个框那就得用上NMS了。一般有两种种计算方式。IOU交/并,IOM交/max。如果比值大于阈值,那么直接干掉得分低的那个框。这里手上的框没有与其他框有交集,所以它不会被NMS干掉。

           其实这样传统的NMS直接干掉分数低的有点简单粗暴了,有一篇论文专门针对NMS进行了改进优化,称之为soft-nms。如果某一个框的分数较低,那么不直接将这个框干掉而是降低其置信度,通过高斯加权的方式再进行排除。文章中指出在常规算法(faster-RCNN, MTCNN)中MAP值上升一个百分点。

     

    文章接: Improving Object Detection With One Line of Code

    Github链接: https://github.com/bharatsingh430/soft-nms

           MTCNN方法在FDDB数据库上测试的结果是0.95。(在1000次误检情况下的准确率)

           但是,MTCNN仍然具有一些缺点。

    ①  MTCNN的检测速度跟待检测人脸的数量有很大关系,当人脸数量变多之后,检测耗时上升会非常明显。

    ②  在CPU上时间消耗比较严重

    ③  侧脸进行人脸对齐的时候,特征点位置不准确。

     

           针对MTCNN的优化版本已经有很多了,例如我用过两种

    1,MTCNN-light,作者将caffemodel文件转成了txt,不再依赖caffe框架,只依赖openmp,在cpu平台下运行,多线程处理速度不错,但是检测效果略有下降。

    2,MTCNN-AccelerateONet,专门针对最后的ONet网络进行了加速,在GPU上加速很明显。但是速度依然会受人脸数量的影响。

     

           MTCNN,MTCNN-light,MTCNN-Accelerate三者实验对比

    方法

    输入分辨率

    硬件平台

    1个人脸耗时

    8人脸耗时

    MTCNN

    VGA

    GTX1070

    13ms

    23ms

    MTCNN-Acce

    VGA

    GTX1070

    8ms

    14ms

    MTCNN-light

    VGA

    i5 CPU

    33ms

    45ms

     

    方法

    输入分辨率

    硬件平台

    20人脸脸耗时

     

    MTCNN

    5184*3456

    GTX1070

    1.25 s

     

    MTCNN-Acce

    5184*3456

    GTX1070

    570 ms

     

    MTCNN-light

    5184*3456

    I5CPU

    3.66 s

     

             经过对比三种方法,MTCNN-light适合应用于没有gpu的硬件平台,在VGA分辨率情况下,适当调整minSize,可以做到实时检测。

              对比MTCNN和MTCNN-Acce,后者的时间消耗几乎是前者的一半,在FDDB上进行测试,后者的检测效果略差于前者。如下图所示:

           上面两种方法本质都是一样的,只不过加速版在最后O-Net网络结构上面进行了修改,然后重新训练得到一个新模型。在网络结构方面,加速版只是在原始版本上将第五个卷积层后面的dropout层去掉了,然后在前面卷积层的输出参数上进行了缩减,前5个卷积层的num_output都减少了一半,从而减少了计算量。如下图所示:

           dropout层在神经网络中的应用目的就是防止网络层数过多出现过拟合,根据设置的dropout_ratio参数随机停止部分神经元工作,然后输出多种情况下的平均值,这样防止出现训练过拟合。这里的改动直接将卷积层输出参数去掉一半,然后不要dropout,重新训练就可以得到和原网络差不多的效果。这种方法可以值得我们借鉴。 

     

     

           由于MTCNN系列的方法耗时都对待检测人脸数量敏感,并且在CPU上的表现不好。所以,faceBoxes这个方法就出现了。论文中说使用的方法可以很大幅度提高检测速度,并且不受人脸数量的影响。在FDDB上准确率0.96,但是没有人脸对齐

     

    faceBoxes介绍

           faceBoxes主要包含两个部分:RDCL和MSCL

    RDCL的全名是 Rapidly Digested Convolutional Layers,主要负责快速性

    MSCL的全名是 Multiple Scale Convolutional Layers,主要负责多尺度检测

           如上图所示,输入一张图,会在三个分支检测人脸,这样解决多尺度的问题。

           在网络的前半部分,RDCL主要是加速,快速缩小特征图。

    ①    Conv1,Pool1, Conv2 和 Pool2 的stride分别是4,2, 2 和 2。这样整个RDCL的stride就是32,就是说原始的输入尺寸被缩小了32次。

    ②   另外,通过设计合适的核尺寸来加速计算。卷积核或者池化核尺寸太大就会导致计算量增加,尺寸太小又会导致覆盖的信息不足,所以文章中直接选择了7×7,5×5 , 3×3, 3×3分别对应 Conv1, Conv2 ,Pool1,Pool2 。

    ③   最后,由于为了减少计算量,减少了卷积核的数量。为了保证输出维度不变,通过使用CReLU来保持输出维度不变。

     

           关于CReLU,CReLU论文的大致意思是在神经网络中靠前的部分,参数的分布具有很强的负相关性,随着网络的变深,这种负相关性越来越弱。在网络的前部,网络更加倾向于同时捕捉正负相位的信息,但是由于ReLU的特性将负响应抹掉了,这样造成了卷积核会存在一定冗余。

     

     

    上图中,红色曲线是假设随机高斯分布生成的卷积核得到的相似度统计。蓝色的直方图是对所有的卷积核寻找其pair filter,按照相似度和数量画出的。这个图说明了随着网络深度加深,负相关性越来越小。

           在网络的后半部分,MSCL主要是解决人脸多尺度的问题,这种方法增加了小人脸的召回率。

    ①  在网络的不同层进行检测,类似于SSD。

    ②  采用Inception模块。由于Inception包含多个不同的卷积分支,因此可以进一步使得感受野多样化。

           Faster-RCNN中RPN对小目标检测效果不好,一定程度上是因为RPN中的anchor只跟卷积层后面几层有关系,并且小目标所能对应的anchor比较少。

           最后采用增加anchor密度的方法来提高多尺度人脸的召回率

           根据计算anchor密度的方法,密度=anchor大小/stride,原始Inception3网络结构中anchor大小分别为32,64,128,stride为32,所以其密度为1,2,4。Conv3_2和Conv4_2的密度都是4。为了anchor的密度均衡,所以对密度不足的anchor进行均衡化。

    论文的效果还没有复现出来,目前github上开源的代码,FDDB上的检测效果只有0.91,在cpu上的时间消耗在180ms左右,640X480分辨率。

     

    关注我的公众号,分享资源
    公众号搜索: 卡本特

       
    扫码关注
    ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pLmxvbGkubmV0LzIwMTkvMTIvMDYveHJqT29RZHZFSzRQRkJWLnBuZw?x-oss-process=image/format,png)

     

    展开全文
  • 学习笔记:人脸检测和人脸识别

    万次阅读 2018-07-24 12:37:34
    人脸检测( Face Detection )和人脸识别技术是深度学习的重要应用之一。本章首先会介绍MTCNN算法的原理, 它是基于卷积神经网络的一种高精度的实时人脸检测和对齐技术。接着,还会介绍如何利用深度卷积网络提取人脸...
  • 人脸检测MTCNN详解

    万次阅读 2018-05-28 09:14:36
    《Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks》论文解读。本文来自于中国科学院深圳先进技术研究院,目前发表在arXiv上,是2016年4月份的文章,算是比较新的文章。...
  • 人脸识别之人脸检测(一)--综述

    千次阅读 2018-07-23 00:01:37
    这里作为一个系列,先说haar分类器。 原文: ... 非常感谢作者这一篇总结性文章,对OpenCV人脸识别的详细完整总结,让我自愧不如。同样作为一个本科生,作者的态度,让人钦佩。...人脸检测属于计算机...
  • 人脸检测与识别

    千次阅读 2019-07-18 04:12:57
    人脸检测( Face Detection )和人脸识别技术是深度学习的重要应用之一。本章首先会介绍MTCNN算法的原理, 它是基于卷积神经网络的一种高精度的实时人脸检测和对齐技术。接着,还会介绍如何利用深度卷积网络提取人脸...
  • 一个简单的人脸检测Demo

    千次阅读 多人点赞 2019-03-12 14:08:33
    放假回来,闲着翻了下电脑看见一个人脸识别的Demo 照着做了下,遇到了一些小麻烦,好在做出来了,挺有意思。 说一下环境: 安装好了Tensorflow Pycharm 等环境,在网上看到了这份代码 ...然后复制到Pycharm中,...
  • 人脸检测:RetinaFace(开源简化版)详细解读

    万次阅读 多人点赞 2019-08-21 16:08:54
    Insight Face在2019年提出的最新人脸检测模型,原模型使用了deformable convolution和dense regression loss, 在 WiderFace 数据集上达到SOTA。截止2019年8月,原始模型尚未全部开源,目前开源的简化版是基于传统...
  • 人脸检测——DDFD

    万次阅读 多人点赞 2017-08-03 09:03:16
    本文所介绍的人脸检测,主要学习和实现了ICMR-2015年雅虎实验室的文章”Multi-view Face Detection Using Deep Convolutional Neural Networks”.这是我接触和实现的第一个深度学习案例,本文除了讲解该文的算法以外,...
  • 视频人脸检测只是从摄像头读出每帧图像,然后采用静态图像中的人脸检测方法进行检测。至于视频人脸检测涉及到的其他处理过程,例如轨迹跟踪,将在以后完善。本文只介绍视频人脸检测,对于静态人脸检测,可通过本文...
  • Android使用OpenCV实现「人脸检测」和「人脸识别」

    万次阅读 多人点赞 2016-11-25 09:54:58
    Android使用OpenCV实现「人脸检测」和「人脸识别」DEMOOpenCV+JavaCV实现人脸识别—————————-分割线———————————效果图 先上效果图,不好弄gif 在网上找了在Android平台上使用OpenCV相关的教程,...
  • Matlab人脸检测方法(Face Parts Detection)详解

    万次阅读 多人点赞 2018-04-20 19:41:06
    今天同学让我帮忙制作一个人脸表情识别的样本库,其中主要是对人脸进行裁剪,这里用到了一个相对较新的Matlab人脸检测方法Face Parts Detection,网上百度了一下发现关于Matlab人脸检测的代码和资源并不多,故此专门...
  • 人脸检测(十九)--人脸检测综述(2018.2)

    万次阅读 多人点赞 2018-08-16 14:43:48
    这篇文章,偏工程实用...《人脸检测背景介绍和常用数据库》,介绍人脸检测的背景,常用数据库和评价指标,重点介绍各类算法的发展现状和各数据库上目前算法的性能速度水平; 《非深度学习的人脸检测》,介绍以VJ为...
  • 人脸检测---基于肤色检测的实现

    万次阅读 多人点赞 2015-10-17 21:05:42
    在2015年本科毕业的时候,当时因为保送研究生的时候,选择了图像处理的研究方向,因此本科的毕业设计就选择了人脸检测的课题。人脸检测是一个研究得比较深入得一门方向了,对于人脸识别的重要性不言而喻,人脸都检测...
  • 人脸检测--基于Adaboost算法的实现

    万次阅读 多人点赞 2016-03-09 22:57:46
    毕设的时候,做了基于肤色特征的人脸检测之后,通过肤色建模和肤色分割发现检测率并没有预想中的那么好,于是为了提高人脸检测的效率,对基于肤色特征的人脸检测算法那进行了改进,也就是基于模板匹配的人脸检测算法...
  • 基于 MTCNN/TensorFlow 实现人脸检测

    万次阅读 热门讨论 2017-08-31 21:32:07
    人脸检测方法有许多,比如opencv自带的人脸Haar特征分类器和dlib人脸检测方法等。对于opencv的人脸检测方法,有点是简单,快速;存在的问题是人脸检测效果不好。正面/垂直/光线较好的人脸,该方法可以检测出来,而...
  • 人脸检测在百度百科里被定义为人脸检测是指对任意一幅给定的人脸图像,采用一定的策略对其进行搜索以确定其中是否含有人脸,如果是则返回确认人脸的位置、大小和姿态。那,对于人脸检测算法是什么?会有哪些难点?由...
  • 一个自主的人脸检测项目需要首先创建人脸信息特征库,这就给想体验一下人脸检测新鲜感的朋友设下了一个门槛。但是也就是说我们可以利用别人已经训练好的特征库来进行自己的项目。 这个小项目就是利用一份已经训练好...
1 2 3 4 5 ... 20
收藏数 54,006
精华内容 21,602
关键字:

人脸检测