众志成城,抗击疫情。首先,我们向在一线抗击疫情的医护人员和各行各业的从业者致敬。祝愿我们早日战胜疫情,早日迎接春暖花开的那一天。
近一个月来,新冠肺炎疫情牵动着全国人民的心,一线医护工作者在最前线抗击疫情的同时,我们也可以看到很多科技行业和人工智能领域的从业者,也在贡献着他们的力量。近些天来,旷视、商汤、海康、百度都多家科技公司研发出了带有AI人脸检测算法的红外测温、口罩佩戴检测等设备,依图、阿里也研发出了通过深度学习来自动诊断新冠肺炎的医疗算法。可以说,各行各业的从业者都在为早日战胜这场疫情贡献着力量。
作为互联网+AI领域的创业团队,我们决定开源我们整理的口罩检测数据集和训练好的模型(提供keras版本和caffe版本)、代码,另外,我们也将模型转为了TensorFlow.js支持的格式,部署到了我们的网站aizoo.com上,方便大家在浏览器里面体验。
在文章末尾,有我们开源的所有资料的链接,如果您不想看文章内容,可以直接滑到文章底部查看资料链接。
视频中红色是未戴口罩,绿色是佩戴了口罩。可以看到,如果是双手捂住了嘴巴多半部分,模型会认为是未戴口罩(关于这一点,下文会有讨论)。
下面,我们将从模型结构、数据和TensorFlow.js部署三大方面介绍本项目。好了,废话不多说了,Let's go~
在深度学习时代之前,人脸检测一般采用传统的、基于手动设计特征的方法,其中最知名的莫过于Viola-Jones算法,至今部分手机和数码相机内置的人脸检测算法,仍旧采用Viola-Jones算法。然而,随着深度学习技术的蓬勃发展,基于深度学习的人脸检测算法逐步取代了传统的计算机视觉算法。
在人脸检测最常用的数据集——WIDER Face数据集的评估结果上来看,使用深度学习的模型在准确率和召回率上极大的超过了传统算法。下图的青线是Viola-Jones的Precision-Recall图。
下图是众多基于深度学习的人脸检测算法的性能评估PR曲线。可以看到基于深度学习的人脸检测算法的性能,大幅超过了VJ算法(曲线越靠右越好)。近两年来,人脸检测算法在WIDER Face的简单测试集(easy 部分)上可以达到95%召回率下,准确率也高达90%,作为对比,VJ算法在40%召回率下,准确率只有75%左右。
其实,基于深度学习的人脸检测算法,多数都是基于深度学习目标检测算法进行的改进,或者说是把通用的目标检测模型,为适应人脸检测任务而进行的特定配置。而众多的目标检测模型(Faster RCNN、SSD、YOLO)中,人脸检测算法最常用的是SSD算法,例如知名的SSH模型、S3FD模型、RetinaFace算法,都是受SSD算法的启发,或者基于SSD进行的任务定制化改进, 例如将定位层提到更靠前的位置,Anchor大小调整、Anchor标签分配规则的调整,在SSD基础上加入FPN等。在笔者个人看来,SSD是最优雅、简洁的目标检测模型,因此,我们实现的人脸口罩检测模型,也是采用SSD的思想,限于篇幅原因,本文不会详细介绍SSD的原理,只会进行简单的模型配置介绍。后面,元峰也会写一些详细介绍SSD算法和实现的文章,并开源笔者实现的极简的目标检测训练框架,以及SSD和YoloV3的对比分析等,我会发到我们的公众号上,欢迎大家关注AIZOO公众号。
在本项目中,我们使用的是SSD架构的人脸检测算法,相比于普通的人脸检测模型只有人脸一个类别,而人脸口罩检测,只不过是增加了一个类别,变成戴口罩人脸和不戴口罩的人脸两个类别而已。
我们开源的模型是一个非常小的模型,输入是260x260大小,主干网络只有8层,有五个定位和分类层,一共只有28个卷积层。而每个卷积层的通道数,是32、64、128这三种,所有这个模型总的参数量只有101.5万个参数。下图是网络的结构图。
其中,上面八个卷积层是主干网络,也就是特征提取层,下面20层是定位和分类层(注意,为了方便显示,我们没有画出BN层)。训练目标检测模型,最重要的合理的设置anchor的大小和宽高比,笔者个人在做项目时,一般会统计数据集的目标物体的宽高比和大小来设置anchor的大小和宽高比。例如,在我们标注的口罩人脸数据集上,我们读取了所有人脸的标注信息,并计算每个人脸高度与宽度的比值,统计得到高度与宽比的分布直方图,如下:
因为人脸的一般是长方形的,而很多图片是比较宽的,例如16:9的图片,人脸的宽度和高度归一化后,有很多图片的高度是宽度的2倍甚至更大。从上图也可以看出,归一化后的人脸高宽比集中在1~2.5之间。所以,根据数据的分布,我们将五个定位层的anchor的宽高比统一设置为1,0.62, 0.42。(转换为高宽比,也就是约1,1.6:1,2.4:1)
卷基层
| 特征图大小
| anchor大小
| anchor宽高比
|
第一层 | 33x33 | 0.04, 0.056 |
1, 0.62, 0.42 |
第二层 | | 0.08, 0.11 |
第三层 | 9x9 | 0.16, 0.22 |
第四层 | 5x5 | 0.32, 0.45 |
第五层 | 3x3 | 0.64, 0.72 |
笔者使用基于Keras实现的目标检测微框架训练的人脸口罩检测模型,为了避免一些网友提到的使用手挡住嘴巴就会欺骗部分口罩检测系统的情况,我们在数据集中加入了部分嘴巴被手捂住的数据,另外,我们还在训练的过程中,随机的往嘴巴部分粘贴一些其他物体的图片,从而避免模型认为只要露出嘴巴的就是没戴口罩,没露出嘴巴的就是带口罩这个问题,通过这两个规避方法,我们很好的解决了这个问题,大家可以在aizoo.com体验我们的模型效果。后处理部分主要就是非最大抑制(NMS),我们使用了单类的NMS,也就是戴口罩人脸和不戴口罩人脸两个类别一起做NMS,从而提高速度。
其实,做这个项目,笔者使用个人实现的检测框架,只用两个小时就搞定了训练部分。但是,为了整理数据,笔者花了整整两天的时间。如果我们花两天时间写代码,我们不觉得痛苦,但是如果花两天时间标注数据,那是一个相当痛苦的事情。
最初,笔者使用了B站一个本科生小伙公开的的1千多张图片训练了一个模型,但是该数据集比较单一,很容易出现用手捂住嘴巴,模型就认为是戴口罩这种问题,后面,笔者决定自己整理数据集。
人脸检测数据集非常多,其中最常用的莫过于WIDER Face数据集,我们从中选择了3894张图片,并进行了校验,主要是将部分戴口罩的人脸标注为戴口罩。对于戴口罩的人脸,我们使用了中科院信工所葛仕明老师开源的MAFA数据集,该数据集本是一个遮挡人脸的数据集,其中有各种被遮挡的人脸图片,大多数都是被口罩遮挡的人脸图片,我们从中选择了4064张人脸戴口罩的图片。
MAFA数据集的人脸位置定义与WIDER Face有较大区别,MAFA的人脸框在靠近眉毛上方,是正方形的,而且标注框不严格(框离脸部边缘有缝隙),而WIDER Face的人脸框在额头上方,如果不进行修改,会导致模型对于不戴口罩的人脸,检测框是到额头上方,而戴口罩的人脸,检测框只到眉毛上方。因此,我们重新标注了这部分MAFA数据。(标注数据真的是一个非常难受的过程~)。我们最终对数据进行了随机划分为训练集和验证集。下表是数据统计。
| 来自 WIDER Face | 来自 MAFA | 共计 |
训练集/张
| 3114
| 3006
| 6120
|
验证集/张
| 780
| 1059
| 1839
|
关于数据部分,我们就介绍到这里。需要的朋友可以在文末找到下载链接。或者在公众号回复“口罩数据集”也可以获取到链接。 为了便于在浏览器部署模型,我们特意将模型设计的非常小,这导致一个弊端就是模型会牺牲一部分性能,但是速度会非常快,在普通CPU上也可以做到实时性。最终的模型在验证集上的Precision-Recall曲线如下图所示:
因为WIDER Face本身是一个稍微复杂的数据集,再加上我们模型的输入和参数量比较小,所以,可以看到对于人脸的AP只有0.896。不过,这点可以通过设计大一点的模型改善性能。如果您有需要更高精度的模型,欢迎联系我们。
使用Keras训练好模型后,我们将其转换为TensorFlow.js格式,并使用JavaScript对口罩人脸检测模型进行了部署。模型的效果图如下图所示:
百度网盘链接: https://pan.baidu.com/s/1nsQf_Py5YyKm87-8HiyJeQ https://github.com/AIZOOTech/FaceMaskDetection
我是元峰,互联网+AI领域的创业者,欢迎扫描下方二维码,或者直接在微信搜索“AIZOO”关注我们的公众号AIZOO。
如果您是有算法需求,例如目标检测、人脸识别、缺陷检测、行人检测的算法需求,欢迎添加我们的微信号AIZOOTech与我们交流,我们团队是一群算法工程师的创业团队,会以高效、稳定、高性价比的产品满足您的需求。
如果您是算法或者开发工程师,也可以添加我们的微信号AIXZOOTech,请备注学校or公司名称-研究方向-昵称,例如“西电-图像算法-元峰”,元峰会拉您进我们的算法交流群,一起交流算法和开发的知识,以及对接项目。