Viola-jones人脸检测算法是一种基于滑动窗口的目标检测算法,但它却克服了滑动窗口检测带来的低效问题,可以用于实时人脸检测,主要归功于以下三点:
我参考论文[1]实现了Viola Jones中提到的attention cascade检测框架,此处是 github传送门 。
下面进一步详细介绍整个检测原理。
基于滑窗的目标检测基本原理很简单,首先构建一个classifier(分类器),以人脸检测为例,分类器的工作是判断给定大小的图像的是否为人脸,用该分类器从左至右从上到下扫描整幅图像,扫描获取的部分图像称为子窗(文章中子窗大小为24x24像素),当分类器判断子窗是人脸时,即完成了人脸检测。
这样处理有个问题,如果图像中包含的人脸变大了,此时采用固定大小的子窗就无法进行检测。通常有两种解决方法,1. 采用image-pyramid(图像金字塔),也就是通过resize获得多种不同大小图像并堆叠在一起,用固定大小分类器同时对所有图像进行扫描;2. 采用不同大小的分类器进行扫描。文章中用到的是第二种方法,尽管如此,虽然避免了调整图像大小带来的计算开销,但不同大小的分类器意味着有更多子窗需要进行处理。
如何构建一个足够快的分类器来对每个子窗进行快速判断。
分类器的构建有两种方式,一种是pixel-based(基于像素),另一种是feature-based(基于特征)。当把神经网络作为图像分类器时,输入是图像的像素值,即基于像素的分类器。用图像像素作为输入不包含任何和待分类目标有关的特定信息,往往训练这种分类器需要大量数据,并且分类过程较慢。基于特征的分类器就是先针对图像进行特征提取(HOG特征,SIFT特征等),再利用获取的特征进行分类。这种分类器不需要大量训练数据,且计算量一般会在特征计算部分,相对较小。
文章采用的是基于特征的分类器,选取了一种较为简单的特征即haar-like特征。利用矩形个数对可以将haar-like特征分为三类,分别由两个,三个,和四个 大小相同 的矩形组成。全部列举出来可以分为以下(a)(b)(c)(d)(e)五类(注意是五类不是五个,具体有多少个haar-like特征是由子窗大小决定的)。如下图所示(文章[1]中的图)。
当子窗大小给定后,我们可以用五个参数唯一确定 一个 haar-like特征,即特征种类(a/b/c/d/e),左上角x轴坐标,左上角y轴坐标,矩形的长,矩形的宽。对应的特征值等于位于白色矩形框中像素值总和减去位于黑色矩形框中的像素值总和。文章中用到的子窗大小为24x24像素,可以计算出来总共有162336个特征(把在子窗中所有可能位置和可能大小的特征全部列举出来)。利用haar-like特征进行分类只需两步:
haar-like特征有两个优点,第一是它是scale-invariant(不随图片大小而改变)的,第二是可以通过积分图像快速计算。简单的说下第一点的含义,例如我们用24x24像素的训练样本训练获取一组haar-like特征和对应的门限值,当对图像进行扫描时,子窗大小调整为SxS像素,此时只需将特征中的矩形大小按同样比例进行缩放(门限值同样需要缩放),计算所得的特征值依然是有效的。 积分图像是受卷积的微分性质启发而定义一种数据结构。积分图像定义: 其中 为积分图像, 为原图像。积分图像中 位置处的像素值等于原图中位于 的左侧和上方的所有像素值之和。有了积分图像我们就可以快速计算haar-like特征,以特征(a)为例,如下图所示。
S1到S6是积分图像在这六个顶点上的值。该特征值等于位于A中的像素总和减去位于B中的像素总和,而A中像素总和等于S5+S1-S2-S4,B中像素总和等于S6+S2-S3-S5,并且无论矩形多大,我们总能在固定时间内计算出特征值(6次索引操作和少量的加法乘法计算)。积分图像只需计算一次后续可以一直使用,事实上在算法实现时,我们只需保存样本的积分图像,原图像反而不用保存。
现在找到了一类特征用于构建分类器,和快速计算该类特征的方法。分类器是由一组特征构成的,而不是一个,如何找到一组有效的特征。
文章列举了前人的一些特征选取方法(此处就不列举了),它们虽然取得了一定的效果,但最终选出来的特征数量还是太多。文章将adaBoost算法用于特征选取(创新点),即每次训练的弱分类器的过程看做特征选取的过程,一次从162336个特征中选取一个特征(同时还包括了对应的门限值,极性,加权误差)。
adaboost算法就不详细介绍了,它的基本思想是训练一系列“弱”分类器,组成一个committee(即每个弱分类器都有投票权,但是权重不同,加权误差越小的弱分类器权重越大)。adaboost采用迭代训练方式,给定一个t阶committee,如何寻找第t+1个弱分类器和对应的权重,以最小化在一定分布下的训练样本的加权指数损失。这个优化过程可以转换为对训练样本的分布进行调整(即增大上一轮错误判断的样本的权重,减小正确判断的样本权重),在调整后的样本分布下寻找最小化加权0-1损失的弱分类器并计算对应的加权0-1损失。
可以利用adaboost找到一组特征构成分类器,使得该分类器有极高的准确率和召回率(这种分类器势必会有较大的计算量),这样会导致图像中的每一个子窗都享有同等的计算量,扫描一整幅图会有几十万甚至上百万子窗,总体计算量依然很大。实际上一幅图像中只有极少可能包含人脸的位置是我们感兴趣的,其他不包含人脸的子窗我们希望能够快速筛除,将更精细的计算用于包含人脸的子窗。
文章引入了attention-cascade的机制(注意力级联),即训练多个分类器进行级联,替代单一的分类器。结构如下图所示(文章[3]中的图)。
上图所示的分类器有三级,上一级的输出是下一级的输入,只有预测为正的样本才能传递给下一级,预测为负的样本直接舍弃。大部分非人脸子窗往往在前几级分类器就被舍弃,这样使得扫描每个子窗所需的平均计算量大大减小。
分类器是一级一级训练之后级联起来的,训练分类器时,整个级联分类器的假负率(fpr_overall)有一个训练目标(文章[1]中设置为10e-7),同时每一级有一对训练目标,即假正率和假负率。每级分类器训练的思想是在假负率极低的情况下(文章[1]中设置为0.005)尽量得到一个较低的假正率(文章中[1]中设置为0.5),即我们保证在正样本尽可能多的通过该级分类器的情况下尽量筛除更多的负样本。文章[3]通过一个松弛量来调节假正率和假负率。
下一级用到的训练数据是由所有的正样本和上一级输出的假正样本组成的,这样训练的好处是可以让处于级联后半部分的分类器“看到”更多负样本数据,缺点是训练后期假正样本很难获取,训练时间会比较长。
尽管我们获取了一个级联分类器,但依然不能保证对同一幅图中的一张人脸只会检测到一次(子窗相对人脸有所便宜或者缩放子窗大小都可能导致重复检测),如何消除重复检测,获得更好的检测效果。
文章[3]中说的较为简略,主要是针对检测框构建并查集,并对并查集中的候选框求平均得出最终的检测框。
文章[1]中是采用连通分量算法,计算每种大小检测框的置信度,根据置信度选取最终结果,但前提是检测器在图像中扫描的步进必须是1个像素,处理时间可能会比较长。
只能用于正脸检测,如果人脸朝屏幕内外或者在屏幕平面上旋转均有可能失效 在背景较亮,人脸较暗的情况下可能失效。 在有遮挡的情况下大概率失效。
Viola-Jones方法,人脸识别研究组。《智能环保垃圾处理设备》发布的公告得知人脸识别参考文献为Viola-Jones方法,人脸识别研究组。包括人脸检测,人脸预处理和人脸等方向。
python使用dlib进行人脸检测与人脸关键点标记
Dlib简介:
首先给大家介绍一下Dlib
Dlib是一个跨平台的C++公共库,除了线程支持,网络支持,提供测试以及大量工具等等优点,Dlib还是一个强大的机器学习的C++库,包含了许多机器学习常用的算法。同时支持大量的数值算法如矩阵、大整数、随机数运算等等。
Dlib同时还包含了大量的图形模型算法。
最重要的是Dlib的文档和例子都非常详细。
Dlib主页:
这篇博客所述的人脸标记的算法也是来自Dlib库,Dlib实现了One Millisecond Face Alignment with an Ensemble of Regression Trees中的算法
这篇论文非常出名,在谷歌上打上One Millisecond就会自动补全,是CVPR 2014(国际计算机视觉与模式识别会议)上的一篇国际顶级水平的论文。毫秒级别就可以实现相当准确的人脸标记,包括一些半侧脸,脸很不清楚的情况,论文本身的算法十分复杂,感兴趣的同学可以下载看看。
Dlib实现了这篇最新论文的算法,所以Dlib的人脸标记算法是十分先进的,而且Dlib自带的人脸检测库也很准确,我们项目受到硬件所限,摄像头拍摄到的画面比较模糊,而在这种情况下之前尝试了几个人脸库,识别率都非常的低,而Dlib的效果简直出乎意料。
相对于C++我还是比较喜欢使用python,同时Dlib也是支持python的,只是在配置的时候碰了不少钉子,网上大部分的Dlib资料都是针对于C++的,我好不容易才配置好了python的dlib,这里分享给大家:
Dlib for python 配置:
因为是用python去开发计算机视觉方面的东西,python的这些科学计算库是必不可少的,这里我把常用的科学计算库的安装也涵盖在内了,已经安装过这些库的同学就可以忽略了。
我的环境是Ubuntu14.04:
大家都知道Ubuntu是自带python2.7的,而且很多Ubuntu系统软件都是基于python2.7的,有一次我系统的python版本乱了,我脑残的想把python2.7卸载了重装,然后……好像是提醒我要卸载几千个软件来着,没看好直接回车了,等我反应过来Ctrl + C 的时候系统已经没了一半了…
所以我发现想要搞崩系统,这句话比rm -rf 还给力…
sudo apt-get remove python2.71
首先安装两个python第三方库的下载安装工具,ubuntu14.04好像是预装了easy_install
以下过程都是在终端中进行:
1.安装pip
sudo apt-get install python-pip1
2.安装easy-install
sudo apt-get install python-setuptools1
3.测试一下easy_install
有时候系统环境复杂了,安装的时候会安装到别的python版本上,这就麻烦了,所以还是谨慎一点测试一下,这里安装一个我之前在博客中提到的可以模拟浏览器的第三方python库测试一下。
sudo easy_install Mechanize1
4.测试安装是否成功
在终端输入python进入python shell
python1
进入python shell后import一下刚安装的mechanize
>>>import mechanize1
没有报错,就是安装成功了,如果说没有找到,那可能就是安装到别的python版本的路径了。
同时也测试一下PIL这个基础库
>>>import PIL1
没有报错的话,说明PIL已经被预装过了
5.安装numpy
接下来安装numpy
首先需要安装python-dev才可以编译之后的扩展库
sudo apt-get install python-dev1
之后就可以用easy-install 安装numpy了
sudo easy_install numpy1
这里有时候用easy-install 安装numpy下载的时候会卡住,那就只能用 apt-get 来安装了:
sudo apt-get install numpy1
不推荐这样安装的原因就是系统环境或者说python版本多了之后,直接apt-get安装numpy很有可能不知道装到哪个版本去了,然后就很麻烦了,我有好几次遇到这个问题,不知道是运气问题还是什么,所以风险还是很大的,所以还是尽量用easy-install来安装。
同样import numpy 进行测试
python>>>import numpy1234
没有报错的话就是成功了
下面的安装过程同理,我就从简写了,大家自己每步别忘了测试一下
6.安装scipy
sudo apt-get install python-scipy1
7.安装matplotlib
sudo apt-get install python-matplotlib1
8.安装dlib
我当时安装dlib的过程简直太艰辛,网上各种说不知道怎么配,配不好,我基本把stackoverflow上的方法试了个遍,才最终成功编译出来并且导入,不过听说18.18更新之后有了setup.py,那真是极好的,18.18我没有亲自配过也不能乱说,这里给大家分享我配置18.17的过程吧:
1.首先必须安装libboost,不然是不能使用.so库的
sudo apt-get install libboost-python-dev cmake1
2.到Dlib的官网上下载dlib,会下载下来一个压缩包,里面有C++版的dlib库以及例子文档,Python dlib库的代码例子等等
我使用的版本是dlib-18.17,大家也可以在我这里下载:
之后进入python_examples下使用bat文件进行编译,编译需要先安装libboost-python-dev和cmake
cd to dlib-18.17/python_examples./compile_dlib_python_module.bat 123
之后会得到一个dlib.so,复制到dist-packages目录下即可使用
这里大家也可以直接用我编译好的.so库,但是也必须安装libboost才可以,不然python是不能调用so库的,下载地址:
将.so复制到dist-packages目录下
sudo cp dlib.so /usr/local/lib/python2.7/dist-packages/1
最新的dlib18.18好像就没有这个bat文件了,取而代之的是一个setup文件,那么安装起来应该就没有这么麻烦了,大家可以去直接安装18.18,也可以直接下载复制我的.so库,这两种方法应该都不麻烦~
有时候还会需要下面这两个库,建议大家一并安装一下
9.安装skimage
sudo apt-get install python-skimage1
10.安装imtools
sudo easy_install imtools1
Dlib face landmarks Demo
环境配置结束之后,我们首先看一下dlib提供的示例程序
1.人脸检测
dlib-18.17/python_examples/face_detector.py 源程序:
#!/usr/bin/python# The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt## This example program shows how to find frontal human faces in an image. In# particular, it shows how you can take a list of images from the command# line and display each on the screen with red boxes overlaid on each human# face.## The examples/faces folder contains some jpg images of people. You can run# this program on them and see the detections by executing the# following command:# ./face_detector.py ../examples/faces/*.jpg## This face detector is made using the now classic Histogram of Oriented# Gradients (HOG) feature combined with a linear classifier, an image# pyramid, and sliding window detection scheme. This type of object detector# is fairly general and capable of detecting many types of semi-rigid objects# in addition to human faces. Therefore, if you are interested in making# your own object detectors then read the train_object_detector.py example# program. ### COMPILING THE DLIB PYTHON INTERFACE# Dlib comes with a compiled python interface for python 2.7 on MS Windows. If# you are using another python version or operating system then you need to# compile the dlib python interface before you can use this file. To do this,# run compile_dlib_python_module.bat. This should work on any operating# system so long as you have CMake and boost-python installed.# On Ubuntu, this can be done easily by running the command:# sudo apt-get install libboost-python-dev cmake## Also note that this example requires scikit-image which can be installed# via the command:# pip install -U scikit-image# Or downloaded from . import sysimport dlibfrom skimage import iodetector = dlib.get_frontal_face_detector()win = dlib.image_window()print("a");for f in sys.argv[1:]:print("a");print("Processing file: {}".format(f))img = io.imread(f)# The 1 in the second argument indicates that we should upsample the image# 1 time. This will make everything bigger and allow us to detect more# faces.dets = detector(img, 1)print("Number of faces detected: {}".format(len(dets))) for i, d in enumerate(dets):print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(i, d.left(), d.top(), d.right(), d.bottom()))win.clear_overlay()win.set_image(img)win.add_overlay(dets)dlib.hit_enter_to_continue()# Finally, if you really want to you can ask the detector to tell you the score# for each detection. The score is bigger for more confident detections.# Also, the idx tells you which of the face sub-detectors matched. This can be# used to broadly identify faces in different orientations.if (len(sys.argv[1:]) > 0):img = io.imread(sys.argv[1])dets, scores, idx = detector.run(img, 1) for i, d in enumerate(dets):print("Detection {}, score: {}, face_type:{}".format(d, scores[i], idx[i]))123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
我把源代码精简了一下,加了一下注释: face_detector0.1.py
# -*- coding: utf-8 -*-import sysimport dlibfrom skimage import io#使用dlib自带的frontal_face_detector作为我们的特征提取器detector = dlib.get_frontal_face_detector()#使用dlib提供的图片窗口win = dlib.image_window()#sys.argv[]是用来获取命令行参数的,sys.argv[0]表示代码本身文件路径,所以参数从1开始向后依次获取图片路径for f in sys.argv[1:]: #输出目前处理的图片地址print("Processing file: {}".format(f)) #使用skimage的io读取图片img = io.imread(f) #使用detector进行人脸检测 dets为返回的结果dets = detector(img, 1) #dets的元素个数即为脸的个数print("Number of faces detected: {}".format(len(dets))) #使用enumerate 函数遍历序列中的元素以及它们的下标#下标i即为人脸序号#left:人脸左边距离图片左边界的距离 ;right:人脸右边距离图片左边界的距离#top:人脸上边距离图片上边界的距离 ;bottom:人脸下边距离图片上边界的距离for i, d in enumerate(dets):print("dets{}".format(d))print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format( i, d.left(), d.top(), d.right(), d.bottom())) #也可以获取比较全面的信息,如获取人脸与detector的匹配程度dets, scores, idx = detector.run(img, 1)for i, d in enumerate(dets):print("Detection {}, dets{},score: {}, face_type:{}".format( i, d, scores[i], idx[i])) #绘制图片(dlib的ui库可以直接绘制dets)win.set_image(img)win.add_overlay(dets) #等待点击dlib.hit_enter_to_continue()1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
分别测试了一个人脸的和多个人脸的,以下是运行结果:
运行的时候把图片文件路径加到后面就好了
python face_detector0.1.py ./data/3.jpg12
一张脸的:
两张脸的:
这里可以看出侧脸与detector的匹配度要比正脸小的很多
2.人脸关键点提取
人脸检测我们使用了dlib自带的人脸检测器(detector),关键点提取需要一个特征提取器(predictor),为了构建特征提取器,预训练模型必不可少。
除了自行进行训练外,还可以使用官方提供的一个模型。该模型可从dlib sourceforge库下载:
arks.dat.bz2
也可以从我的连接下载:
这个库支持68个关键点的提取,一般来说也够用了,如果需要更多的特征点就要自己去训练了。
dlib-18.17/python_examples/face_landmark_detection.py 源程序:
#!/usr/bin/python# The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt## This example program shows how to find frontal human faces in an image and# estimate their pose. The pose takes the form of 68 landmarks. These are# points on the face such as the corners of the mouth, along the eyebrows, on# the eyes, and so forth.## This face detector is made using the classic Histogram of Oriented# Gradients (HOG) feature combined with a linear
《刷脸背后》(张重生 著)电子书网盘下载免费在线阅读
资源链接:
链接:
书名:刷脸背后
作者:张重生 著
豆瓣评分:6.3
出版社:电子工业出版社
出版年份:2017-8-1
页数:234
内容简介:
人脸识别是当今热门的研发方向,在安防、金融、旅游等领域具有十分广泛的应用。本书全面、系统地介绍“刷脸”背后的技术,包括人脸检测、人脸识别、人脸检索相关的算法原理和实现技术。本书中讲解的算法具有高度的可操作性和实用性。通过学习本书,研究人员、工程师能够在3~5个月内,系统了解、掌握人脸检测、人脸识别、人脸检索相关的原理和技术。本书内容新颖、层次清晰,适合高校教师、研究人员、研究生、高年级本科生、人脸识别爱好者使用。
作者简介:
张重生,男,博士,教授,硕士生导师,河南大学大数据研究中心、大数据团队带头人。研究领域为大数据分析、深度学习、数据挖掘、数据库、数据流(实时数据分析)。
博士毕业于 INRIA,France(法国国家信息与自动化研究所),获得优秀博士论文荣誉。2010年08月至2011年3月,在美国加州大学洛杉矶分校(UCLA),计算机系,师从著名的数据库专家Carlo Zaniolo教授,从事数据挖掘领域的合作研究。 2012-2013,挪威科技大学,ERCIM/Marie-Curie Fellow。