我正在解决的面部识别疑问,须要选用一个面部检测模型。面部检测是面部识别流水线的第一步,准确识别图像中的面部至关关键。Garbage in, garbage out。
但是,泛滥的选项让我感到手足无措,而且关于这一主题的零散写作还不够详细,不可协助我选择选用哪种模型。比拟各种模型破费了我很多精神,因此我以为传播我的钻研或许会协助处于相似状况的人们。
面部检测器的选用要点是什么?
选用面部检测模型时的关键掂量是准确性和功能之间的平衡。但还有其余起因须要思考。关于面部检测模型的大少数文章要么是模型创立者写的,通常宣布在期刊上,要么是那些在代码中成功模型的人写的。在这两种状况下,作者人造会对他们所写的模型持有成见。在一些极其状况下,这些文章实践上是该模型的宣传广告。
很少有文章比拟不同模型的功能体现。进一步参与凌乱的是,每当有人写关于像RetinaFace这样的模型时,他们探讨的是该模型的特定成功。模型自身实践上是神经网络架构,不同的成功或许会造成不同的结果。更复杂的是,这些模型的功能还取决于后解决参数,如置信度阈值、非极大值克服等。
每个作者都将自己的模型形容为“最好”,但我很快看法到“最好”取决于高低文。没有主观上最好的模型。选择哪个面部检测模型最适合的两个关键规范是准确性和速度。
没有一个模型能同时具有高准确性和高速度,这是一个掂量。咱们还必定检查原始准确性之外的目的,大少数基准测试基于原始准确性(正确猜想/总样本量),但原始准确性不是惟一须要关注的目的。假阳性与真阳性的比率以及假阴性与真阴性的比率也是关键的思考起因。用技术术语来说,这种掂量是精度(最小化假阳性)和召回率(最小化假阴性)之间的掂量。这篇文章深化探讨了这个疑问。
测试模型
有一些现有的用于基准测试的面部检测数据集,如WIDER FACE,但我总是青睐看看这些模型在我的数据上体现如何。所以我随机选取了1064帧电视节目样原本测试这些模型(±3%的误差范围)。在手动标注每张图像时,我尽量选用尽或许多的面部,包括局部或简直齐全遮挡的面部,以给模型带来真正的应战。由于我最终要对检测到的面部启动面部识别,所以我想测试每个模型的极限。
数据和标注可以从上方链接启动下载:
将各种模型分为两类是有协助的;那些运转在GPU上的模型和那些运转在CPU上的模型。普通来说,假设你有兼容CUDA的GPU,应该经常使用基于GPU的模型。我有一个NVIDIA 1080 TI显卡,具有11GB内存,这使我能够经常使用一些大规模的模型。但是,我的名目规模渺小(我指的是不可胜数的视频文件),所以对速度极快的基于CPU的模型很感兴味。基于CPU的面部检测模型不多,所以我选择只测试最受欢迎的一个:YuNet。由于其速度,YuNet造成了我的基线比拟。一个GPU模型必定比其CPU对应的模型准确得多,以证实其较慢的解决速度是正当的。
CPU模型
YuNet是为功能而开发的,其模型大小仅为较大模型的一小局部。例如,YuNet只要75,856个参数,而RetinaFace则有27,293,600个参数,这使得YuNet可以在“边缘”计算设施上运转,而这些设施无余以运转较大的模型。
作为一个CPU模型,YuNet的体现比我预期的要好得多。它能够毫无疑问地检测到大面部,但在检测较小面部时有些艰巨。
能够检测到即使在斜角度的大面部。边界框有些偏向,或许是由于图像须要调整为300x300能力输入到模型中。
YuNet简直找到了一切面部,但也包括了一些假阳性。
当限度为图像中的最大面部时,准确性大大提高。
假设功能是关键思考起因,YuNet是一个很好的选用。它甚至足够快,可以用于实时运行,而GPU选项则不能(至少在没有一些重大配件的状况下)。
YuNet经常使用固定的300x300输入尺寸,因此时期差异是由于将图像调整为这些尺寸造成的。GPU模型
Dlib是一个C++成功,带有Python包装器,坚持了准确性、功能和便利性之间的平衡。Dlib可以间接经过Python装置,也可以经过Face Recognition Python库访问。但是,Dlib的准确性和功能在upsampling参数上有很强的掂量。当上采样次数设置为0时,模型速度更快但准确性较低。
无上采样
上采样=1
Dlib模型的准确性随着进一步的上采样而参与,但任何高于上采样=1的值都会造成我的脚本解体,由于它超出了我的GPU内存(顺便说一下,我的内存是11GB)。
Dlib的准确性相关于其(缺乏)速度来说有些令人绝望。但是,它在最小化假阳性方面体现十分好,这是我的优先事项。面部检测是我面部识别流水线的第一局部,因此最小化假阳性数量将有助于缩小下游的失误。为了进一步缩小假阳性数量,咱们可以经常使用Dlib的置信度输入来过滤低置信度的样本。
假阳性和真阳性之间的置信度差异很大,咱们可以应用这一点来过滤前者。咱们可以检查置信度散布来选用一个更准确的阈值,而不是选用一个恣意的阈值。
95%的置信度值在0.78以上,因此扫除低于该值的一切内容可以将假阳性数量缩小一半。
虽然经过置信渡过滤缩小了假阳性数量,但并没有提高全体准确性。我会思考在最小化假阳性数量是关键关注点时经常使用Dlib。但除此之外,Dlib在准确性上并没有比YuNet大幅参与,不可证实其更高的解决时期是正当的;至少对我的用途来说是这样。
OpenCV面部检测模型的关键吸引力在于其速度。但是,其准确性令人绝望。虽然与其余GPU模型相比,它速度十分快,但即使是Top 1准确性也仅略好于YuNet的全体准确性。我不清楚在什么状况下我会选用OpenCV模型启动面部检测,尤其是由于它很难反常上班。
Pytorch-MCNN
MTCNN模型的体现也很差。虽然它的准确性略高于OpenCV模型,但速度要慢得多。由于其准确性低于YuNet,没有 compelling reason to select MTCNN。
RetinaFace
RetinaFace以其作为开源面部检测模型中最准确的声誉而知名。测试结果允许了这一声誉。
它不只是最准确的模型,而且许多“失误”实践上并不是实践失误。RetinaFace真的测试了“假阳性”这个类别,由于它检测到了一些我没有看到的面部,没有标注的由于我以为它们太难了,或许没有思考是“面部”。
它在这张《Seinfeld》片段中的镜子中检测到了局部面部。
它在《Modern Family》的背景图像中找到了面部。
它在识别人脸方面如此杰出,以致于找到了非人脸。
学习到RetinaFace并不算太慢是一个惊喜。虽然它不如YuNet或OpenCV快,但与MTCNN相当。虽然它在低分辨率下比MTCNN慢,但它裁减得相对较好,可以雷同极速地解决更高分辨率。RetinaFace击败了Dlib(至少在须要上采样时)。它比YuNet慢得多,但准确性清楚提高。
经过过滤掉较小的面部,可以扫除RetinaFace识别的许多“假阳性”。假设咱们删除最低四分位的面部,假阳性率会大幅降低。
最低四分位的边界是0.0035
虽然RetinaFace十分准确,但其失误确实有特定的偏向。虽然RetinaFace容易识别小面部,但它在检测较大、局部遮挡的面部时存在艰巨,这在检查面部尺寸相关于准确性时尤为清楚。
这对我的用途来说或许是个疑问,由于图像中面部的大小与其关键性亲密相关。因此,RetinaFace或许会错过最关键的状况,例如以下示例。
RetinaFace未能检测到这张图像中的面部,但YuNet做到了。
论断
依据我的测试(我想强调这些测试并不是环球上最严厉的测试;所以要保管一点疑心态度),我只会思考经常使用YuNet或RetinaFace,详细取决于我的关键关注点是速度还是准确性。或许在我相对想要最小化假阳性数量时会思考经常使用Dlib,但关于我的名目来说,只能选用YuNet或RetinaFace。
完整的名目代码在这里: