赞
踩
论文:Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
论文链接:https://arxiv.org/abs/1604.02878
官方代码链接:https://github.com/kpzhang93/MTCNN_face_detection_alignment
其他代码实现(MXNet):https://github.com/pangyupo/mxnet_mtcnn_face_detection
这篇博客先介绍MTCNN算法,再介绍代码,结合起来看对算法的理解会更加深入。
MTCNN(Multi-task Cascaded Convolutional Networks)算法是用来同时实现face detection和alignment,也就是人脸检测和对齐。文章一方面引入了cascaded structure,另一方面提出一种新的 online hard sample mining。文章的核心思想是原文的这一句话:our framework adopts a cascaded structure with three stages of carefully designed deep convolutional networks that predict face and landmark location in a coarse-to-fine manner. 因此该算法的cascaded structure 主要包含三个子网络:Proposal Network(P-Net)、Refine Network(R-Net)、Output Network(O-Net),如Fig1所示,这3个stage对人脸的处理是按照一种由粗到细的方式,也就是原文中说的 a coarse-to-fine manner,在代码中体现得比较明显。另外要注意的是在Figure1中一开始对图像做了multi scale的resize,构成了图像金字塔,然后这些不同scale的图像作为3个stage的输入进行训练,目的是为了可以检测不同scale的人脸。
在Figure2中详细介绍了三个子网络的结构。
P-Net主要用来生成一些候选框(bounding box)。在训练的时候该网络的顶部有3条支路用来分别做人脸分类、人脸框的回归和人脸关键点定位;在测试的时候这一步的输出只有N个bounding box的4个坐标信息和score,当然这4个坐标信息已经用回归支路的输出进行修正了,score可以看做是分类的输出(是人脸的概率),具体可以看代码。
R-Net主要用来去除大量的非人脸框。这一步的输入是前面P-Net生成的bounding box,每个bounding box的大小都是24*24,可以通过resize操作得到。同样在测试的时候这一步的输出只有M个bounding box的4个坐标信息和score,4个坐标信息也用回归支路的输出进行修正了
O-Net和R-Net有点像,只不过这一步还增加了landmark位置的回归。输入大小调整为48*48,输出包含P个bounding box的4个坐标信息、score和关键点信息。
在训练时候,每个stage的顶部都包含3条支路,接下来简单过一下这3条支路的损失函数。
face classification支路的损失函数如公式1所示,采用的是交叉熵,这是分类算法常用的损失函数,在这里是二分类。
bounding box regression支路的损失函数如公式2所示,采用的是欧氏距离损失(L2 loss),这也是回归问题常用的损失函数。
facial landmark localization支路的损失函数如公式3所示,同样采用的是欧氏距离损失(L2 loss)。
因为在训练的时候并不是对每个输入都计算上述的3个损失函数,因此定义了公式4用来控制对不同的输入计算不同的损失。可以在出,在P-Net和R-Net中,关键点的损失权重(α)要小于O-Net部分,这是因为前面2个stage重点在于过滤掉非人脸的bbox。β存在的意义是比如非人脸输入,就只需要计算分类损失,而不需要计算回归和关键点的损失。
online hard sample mining 具体而言是这样做的:In particular, in each mini-batch, we sort the loss computed in the forward propagation phase from all samples and select the top 70% of them as hard samples. Then we only compute the gradient from the hard samples in the backward propagation phase.
实验结果:
训练过程中的4中不同的标注数据:here we use four different kinds of data annotation in our training process: (i) Negatives: Regions that the Intersec-tion-over-Union (IoU) ratio less than 0.3 to any ground-truth faces; (ii) Positives: IoU above 0.65 to a ground truth face; (iii) Part faces: IoU between 0.4 and 0.65 to a ground truth face; and (iv) Landmark faces: faces labeled 5 landmarks’ positions.
Figure4是本文算法在FDDB、WIDER FACE、AFLW数据集上和其他算法的对比结果。
这里采用第三方的MXNet实现版本:https://github.com/pangyupo/mxnet_mtcnn_face_detection。如果感兴趣可以看原论文的代码:https://github.com/kpzhang93/MTCNN_face_detection_alignment。
该项目可以用来测试,主要包含三个脚本:main.py、mtcnn_detector.py、helper.py。main.py是代码的入口,接下来按跑代码时候的调用顺序来记录。
在main.py中,先import相关模块,其中最重要的是MtcnnDetector这个类,该类在mtcnn_detector.py脚本中定义。通过调用MtcnnDetector类的__init__
函数可以初始化得到一个detector。
import mxnet as mx
from mtcnn_detector import MtcnnDetector
import cv2
import os
import time
detector = MtcnnDetector(model_folder='model', ctx=mx.cpu(0), num_worker = 4 , accurate_landmark = False)
MtcnnDetector类的__init__
函数做了哪些工作呢?如下是mtcnn_detector.py脚本下的MtcnnDetector类的__init__
函数。可以看出都是一些常规的初始化操作。比如models里面放的是训练好的模型路径,self.PNets、self.RNets、self.ONets分别表示论文中算法3个阶段的模型的初始化结果,self.LNet 是用来对关键点坐标进行进一步修正的网络,论文中未提及。这里要注意__init__
函数的输入中factor表示和图像金字塔相关的一个参数,表示图像金字塔的每相邻两层之间的倍数关系是factor。threshold参数是一个包含3个值的列表,这3个值在算法的3个stage中将分别用到,可以看到这3个threshold值是递增的,是因为在3个stage中对一个bbox是否是人脸的置信度要求越来越高。
def __init__(self,
model_folder='.',
minsize = 20,
threshold = [0.6, 0.7, 0.8],
factor = 0.709,
num_worker = 1,
accurate_landmark = False,
ctx=mx.cpu()):
"""
Initialize the detector
Parameters:
----------
model_folder : string
path for the models
minsize : float number
minimal face to detect
threshold : float number
detect threshold for 3 stages
factor: float number
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。