人脸检测(Face Detection)是各种人脸应用中的一项基本任务,目的是找出图像或视频中中所有人脸并给出精确定位。WIDER FACE共包括3万多张图片近40万个人脸,是目前国际上规模最大、场景最为复杂、难度和挑战性最高的人脸检测公开数据集。由于更高的难度、更准确的标注和评测信息,近年来WIDER FACE成为研究机构和公司争相挑战的业界标杆。2018年3月,百度视觉技术部基于PaddlePaddle实现的Pyramidbox模型在WIDER FACE的“Easy”、“Medium”和“Hard”三项评测子集中均荣膺榜首。
项目地址:https://github.com/PaddlePaddle/models/blob/v1.3/fluid/PaddleCV/face_detection/README_cn.md
四步体验Pyramidbox预测可视化
第一步:下载模型库代码
git clone https://github.com/PaddlePaddle/models.git
第二步:下载预发布模型,保存到第一步下载的models/fluid/PaddleCV/face_detection目录下的新建文件夹pre中。
第三步:准备图片
可以使用自己的生活照或者网上的人像照片,调低照片像素至600*x(h缩放至600,或者根据电脑配置调至更低)。
第四部:执行如下命令,注意替换模型路径和预测图片路径。
python3-u widerface_eval.py --infer=True --confs_threshold=0.15--model_dir=./pre/PyramidBox_WiderFace --image_path=./images/13.jpeg--use_gpu=False
按以上简单的四步,就可以在个人电脑里成功体验人脸检测的魔力了
检测原始图片来自网络
Pyramidbox详解
PyramidBox 是一种基于SSD的单阶段人脸检测器,利用上下文信息解决非受控场景中的小脸、模糊和遮挡的人脸检测的技术难题。在 FDDB 和 WIDER FACE 这两个常用的人脸检测基准上相比 state-of-the-art 表现优异。Pyramidbox模型可以在以下示例图片上展示鲁棒的检测性能,该图有一千张人脸,该模型检测出其中的880张人脸。
Pyramidbox网络结构
在不同层级的特征图上进行预测时,基于anchor的目标检测框架已被证明可以有效的处理不同尺度的人脸。同时,FPN结构在融合高级语义特征和低层纹理特征方面表现出较强的优势。PyramidBox的网络结构采用了与S3FD一样的扩展自 VGG16 骨架代码和 anchor 尺度设计,可以生成不同层级的特征图和等比例间隔的anchor。在该骨架上添加低层级FPN,并使用一个上下文敏感结构作为每个Pyramid 检测层的分支网络,以获得最终的输出。PyramidBox架构的关键在于设计了一种新的Pyramid anchor 方法,可以为不同层级的每个人脸生成一系列的anchor。
PyramidBox的网络结构,包括Scale-equitableBackbone Layers 、Low-level Feature Pyramid Layers (LFPN)、Context-sensitivePredict Layers 和 PyramidBox Loss Layer.
Scale-equitable 的主干网络层。我们使用S3fd相同的的基本卷积层和额外卷积层作为主干层,保留了VGG16的conv1_1到pool 5层,然后将VGG16的fc 6层和fc 7层转换为conv fc层,然后添加更多的卷积层使其更深。
低层特征金字塔层(Low-levelFeature Pyramid Networks)。为了提高人脸检测器处理不同尺度的人脸的处理性能,高分辨率的低层级特征起着关键作用。因此,很多当前效果最佳的工作在相同的框架内构建了不同的结构,以检测不同尺寸的人脸,高层级特征被用于检测尺寸较大的人脸,而低层级特征被用于检测尺寸较小的人脸。为了将高层级特征整合到高分辨率的低层级特征上,FPN提出了一种自上而下的架构以使用所有尺度的高层级语义特征图。FPN类型的框架在目标检测和人脸检测上都取得了很好的效果。
众所周知,所有这些构建FPN的工作都是从顶层开始的,并不是所有的高层级特征都对尺寸较小的人脸检测有帮助。首先,小尺寸的、模糊的、被遮挡的人脸与大尺寸的、清晰的、完整的人脸具有不同的纹理特征。因此,直接使用高层级特征来提升小尺寸人脸检测效果是简单粗暴的。其次,高层级特征是从具有很少纹理特征较少的区域提取,并且会引入噪声信息。例如, PyramidBox的主干层中,顶部两层conv7_2和conv6_2的感受野分别是724和468。请注意,训练图像的输入大小为640,这意味着前两层包含太多噪声上下文特征,因此它们可能无助于检测中小尺寸的人脸。LFPN(Low-levelFeature Pyramid Networks)从中间层开始做自上而下的融合,感受野接近输入尺寸的一半。此外,每个LFPN块的结构与FPN相同,详情见下图。
图:Low-level Feature PyramidNetworks
金字塔检测层(Pyramid DetectionLayers)。我们选择 lfpn_2、lfpn_1、lfpn_0、conv_fc7、conv6_2 和conv7_2 作为检测层,anchor 尺寸分别为 16、32、64、128、256 和 512。其中lfpn_2、lfpn_1 和 lfpn_0 分别是基于conv3_3,conv4_3 和conv5_3的 LFPN输出层。此外,与其他 SSD 类型的方法类似,使用L2归一化来重新调整LFPN 层。
预测层(Predict Layers)。每个检测层后跟一个上下文敏感结构(CPM),其输出用于监督pyramid anchors。实验中,它大致覆盖了人脸、头部和身体区域。输出多个通道的特征用于人脸、头部和身体的分类和回归,其中人脸分类需要4个通道(=cpl cnl),cpl和cnl分别是前景(foreground )和背景(background )的max-in-out输出。此外,头部和身体的分类需要两个通道,而人脸、头部和身体各由四个通道进行定位。
PyramidBox 损失层。对于每一个人脸检测目标,有一系列的 pyramid anchors 来同时监督分类和回归任务。设计的PyramidBox Loss,其中使用SoftMax损失进行分类,平滑L1损失进行回归。
图:PyramidBoxLoss
Pyramidbox创新点
Pyramid Anchors: 该算法使用半监督解决方案来生成与人脸检测相关的具有语义的近似标签,提出基于anchor的语境辅助方法,它引入有监督的信息来学习较小的、模糊的和部分遮挡的人脸的语境特征。使用者可以根据标注的人脸标签,按照一定的比例扩充,得到头部的标签(上下左右各扩充1/2)和人体的标签(可自定义扩充比例)。
基于anchor的目标检测和人脸检测算法的显著进展证明均衡采样策略有利于小尺寸的人脸检测,但anchor都是为人脸区域设计的,所以仍然忽略了每个尺度的上下文信息。对于每个人脸检测目标,PyramidAnchors会生成一系列anchor,这些anchor对应和人脸相关的较大区域,包含更多上下文信息,例如头部,肩部和身体。我们通过将区域大小与anchor大小相匹配来选择图层来设置anchors,这将监督更高层级的层以了解更低层级尺寸人脸的更多可表示特征。加上头部,肩部或身体的额外标签,我们可以准确地将anchors与ground truth相匹配以生成损失。由于添加额外标签是不公平的,我们假设不同人脸有相同的比率,偏移区域的上下文信息也相似,因此以半监督的方式实现。也就是说,PyramidBox使用一组统一的框来近似估算头部、肩膀和身体的实际区域,只要不同的人脸中这些框的特性在相似的即可。假设原图中人脸gtbox在region_target位置,anchor_ij定义为:第i层featuremap上的第j个anchor,其尺度为si版pyramid-anchor-ij的第k个标签为:
Spa为anchor的stride(取2),anchor_ij_si表示原图上anchor_ij对应的区域,anchor_ij_si/s_pa^k表示通过stride=s_pa的k次方后的进行采样得到的区域。
图:PyramidAnchors示例
得益于PyramidBox,人脸检测器可以更好地处理较小尺寸的、模糊的和部分遮挡的人脸。其中注意pyramid anchors是自动生成的,没有任何额外的标签,这种半监督学习帮助PyramidAnchors提取近似的上下文特征。在预测过程中,我们仅使用人脸分支的输出,因此与标准的基于anchor的人脸检测相比,在运行时不需要额外的计算成本。
LFPN: LFPN全称Low-level Feature Pyramid Networks, 在检测任务中,LFPN可以充分结合高层次的包含更多上下文的特征和低层次的包含更多纹理的特征。高层级特征被用于检测尺寸较大的人脸,而低层级特征被用于检测尺寸较小的人脸。为了将高层级特征整合到高分辨率的低层级特征上,我们从中间层开始做自上而下的融合,构建Low-level FPN。
CPM: CPM全称Context-sensitive Predict Module, 本方法设计了一种上下文敏感结构(CPM)来提高预测网络的表达能力。受Inception-ResNet的启发,与更广更深的网络相结合, CPM用DSSD的残差预测模块替换了SSH中上下文模块的卷积层。这样获得DSSD模块方法的所有优势的同时,保留来自SSH上下文模块的丰富上下文信息。
图:Context-sensitive PredictModule
Data-anchor-sampling: 设计了一种新的采样方法,简单地说,把图像中的一个随机的人脸变成一个随机的更小的 anchor 尺寸并改变了训练图像的尺寸。该方法可以增加训练样本在不同尺度上的多样性,改变训练样本的分布,重点关注较小的人脸。
基于PaddlePaddle实战
环境准备:请根据安装文档安装最新版本的PaddlePaddle
数据准备:本教程使用 WIDERFACE 数据集 来进行模型的训练测试工作。
WIDERFACE数据集包含32,203张图片,其中包含393,703个人脸,数据集的人脸在尺度、姿态、遮挡方面有较大的差异性。另外WIDER FACE数据集是基于61个场景归类的,然后针对每个场景,随机的挑选40%作为训练集,10%作为验证集,50%作为测试集。
首先,从官网训练集和验证集,放在data目录,官网提供了谷歌云和百度云下载地址,请依据情况自行下载。并下载训练集和验证集的标注信息:
代码语言:javascript复制br
准备好数据之后,data目录如下:
代码语言:javascript复制data
|-- download.sh
|-- wider_face_split
| |-- readme.txt
| |-- wider_face_train_bbx_gt.txt
| |-- wider_face_val_bbx_gt.txt
| `-- ...
|-- WIDER_train
| `-- images
| |-- 0--Parade
| ...
| `-- 9--Press_Conference
`-- WIDER_val
`-- images
|-- 0--Parade
...
`-- 9--Press_Conference
数据目录结构如下:
代码语言:javascript复制data/coco/
├── annotations
│ ├──instances_train2014.json
│ ├──instances_train2017.json
│ ├──instances_val2014.json
│ ├──instances_val2017.json
| ...
├── train2017
│ ├──000000000009.jpg
│ ├──000000580008.jpg
| ...
├── val2017
│ ├──000000000139.jpg
│ ├──000000000285.jpg
| ...
模型训练
下载预训练模型:基于VGGNet的主干网络,使用如下命令下载:
代码语言:javascript复制wget http://paddlemodels.bj.bcebos.com/vgg_ilsvrc_16_fc_reduced.tar.gz
tar -xf vgg_ilsvrc_16_fc_reduced.tar.gz && rm -f
vgg_ilsvrc_16_fc_reduced.tar.gz
开始训练:train.py 是训练模块的主要执行程序,调用示例如下:
代码语言:javascript复制python -u train.py --batch_size=16 --pretrained_model=vgg_ilsvrc_16_fc_reduced
可以通过设置 export CUDA_VISIBLE_DEVICES=0,1,2,3 指定想要使用的GPU数量,batch_size默认设置为12或16。
更多的可选参数见:
代码语言:javascript复制python train.py --help
模型训练150轮以上可以收敛。我们发布的模型使用Nvidia Tesla P40 GPU 4卡训练得到。
模型训练所采用的数据增强
数据增强:数据的读取行为定义在 reader.py 中,所有的图片都会被缩放到640x640。在训练时还会对图片进行数据增强,包括随机扰动、翻转、裁剪等,和物体检测SSD算法中数据增强类似,除此之外,增加了上面提到的Data-anchor-sampling
尺度变换(Data-anchor-sampling):随机将图片尺度变换到一定范围的尺度,大大增强人脸的尺度变化。具体操作为根据随机选择的人脸高(height)和宽(width),得到$v=sqrt{width* height}$,判断$v$的值位于缩放区间$[16,32,64,128,256,512]$中的的哪一个。假设$v=45$,则选定$32<v<64$,以均匀分布的概率选取$[16,32,64]$中的任意一个值。若选中$64$,则该人脸的缩放区间在 $[64 / 2,min(v * 2, 64 * 2)]$中选定。
注意:
本次开源模型中CPM模块与论文中有些许不同,相比论文中CPM模块训练和测试速度更快。
Pyramid Anchors模块的body部分可以针对不同情况,进行相应的长宽设置来调参。同时face、head、body部分的loss对应的系数也可以通过调参优化。
模型评估
验证集的评估需要两个步骤:先预测出验证集的检测框和置信度,再利用WIDER FACE官方提供的评估脚本得到评估结果。
预测检测结果
代码语言:javascript复制python -u widerface_eval.py --model_dir=output/159 --pred_dir=pred
更多的可选参数:
代码语言:javascript复制python -u widerface_eval.py --help
注意:widerface_eval.py中multi_scale_test_pyramid可用可不用,由于Data-anchor-sampling的作用,更加密集的anchors对性能有更大的提升。
评估AP指标
下载官方评估脚本,评估average precision(AP)指标:
代码语言:javascript复制wget http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace/support/eval_script/eval_tools.zipunzip eval_tools.zip && rm -f eval_tools.zip
修改eval_tools/wider_eval.m中检测结果保存的路径和将要画出的曲线名称:
代码语言:javascript复制# 此处修改存放结果的文件夹名字
pred_dir = './pred';
# 此处修改将要画出的曲线名称
legend_name = 'Fluid-PyramidBox';
wider_eval.m是评估模块的主要执行程序,命令行式的运行命令如下:
代码语言:javascript复制matlab -nodesktop -nosplash -nojvm -r "run wider_eval.m;quit;"
模型预测及可视化
模型推断可以获取图像中的物体及其对应的类别,infer.py是主要执行程序,调用示例如下:
代码语言:javascript复制python widerface_eval.py --infer=True --confs_threshold=0.15 --model_dir=pre/PyramidBox_WiderFace --image_path= images/1.jpg
代码语言:javascript复制
注意:请正确设置模型路径${ model_dir }和预测图片路径${ image_path }。默认使用GPU设备,可以通过设置--use_gpu=False使用CPU设备。
传送门:
PaddlePaddle Github:
https://github.com/PaddlePaddle
PyramidBox inPaddlePaddle Github:https://github.com/PaddlePaddle/models/blob/v1.3/fluid/PaddleCV/face_detection/README_cn.md
Reference:
PyramidBox: A Context-assisted SingleShot Face Detector
https://arxiv.org/pdf/1803.07737.pdf