基于Python下的OpenCv人脸识别模拟
- 1.Pycharm下OpenCv的安装
- 2.人脸识别的原理
- 目标实现
- 基本原理
- 3.代码实现:
- 实现步骤
- 参考示意图:
目标实现
目标:
在本Blog中
- 我们将会用基于Haar Fearture-based Cascade Classifiers来进行人脸检测
- 我们会对眼睛等其它部位进行扩展
基本原理
原理
- Haar Fearture-based Cascade Classifiers是一种十分有效的物体检测方法。它是由Paul Viola and Michael Jones于2001年在他们的论文中提出的。(论文我还未看,看之后会给大家补充)他们利用了一种名为“Boosted Cascade”的级联方式,仅用一些简单的特征参考,就能实现快速的物体检测。
“Rapid Object Detection using a Boosted Cascade of Simple Features”
- 这是一种机器学习的方法。其中的级联函数是通过利用许多包含人脸的positive的图片,与不包含人脸的一些negative的图片来进行训练得到的。经过训练后,可以用来在其它图片中进行物体的检测。
- 这里,我们将用人脸检测作为例子进行讲解。最初,该算法需要很多包含人脸的positive的图片,与不包含人脸的一些negative的图片进行分类训练。之后,我们需要利用如下图所示的haar features从中提取出一些额外的特征。就像我们的卷积核( convolutional kernel) 一样,每个特征都是一个单一的数值,利用黑色矩形区域内像素之和减去白色矩形内像素之和而获得。图片如下所示:
Kernel可以把数据集从低维映射到高维,使得原来线性不可分的数据集变得线性可分。
- 但在这些所有的我们需要计算的特征中,考虑到所有Kernel函数的位置和大小尺寸.我们需要做出很多次的计算,例如一个24x24的窗口都会有超过160000个特征进行计算,而每一个特征的计算都要参考上面的haar features的计算方法,因此计算量十分的大。为了解决这个问题,他们创造出一种
integral images(该方式理论也在论文中,还未细看,之后会讲解)
对图像进行积分的方式来解决该问题。它简化了像素之和的计算,使操作仅用四个像素来解决问题,从而使得运算超级快。 - 但是在这些所有的特征中,大多数是没有什么关联的。例如下图,上面两个图显示了很好的两个特征,第一个特征似乎可以被用来辨别眼睛的区域,因为我们知道,眼睛区域是比脸颊部分更黑一点。第二部分可以用来辨别鼻子区域,鼻翼两侧的阴影会更黑。
- 但是,这些相同的窗口特征若放到如脸颊或耳朵附近则无法体现出特征值之间的关联性,因此如何从160000+的特征值中选取有用的特征值也是一门学问。
接下来我们将见到
Adaboost,它被很好的用于解决了上述的问题 - 对于上述问题,我们将在训练图像上分析每一个特征。而对于这其中的每一个特征,会找到一个最佳阈值来区分 the faces to positive and negative。当然,在进行图片分类时肯定会出现错误的分类,因此我们要选取一个最小的出错比例,意味着这些特征值可以最好的对图片进行分类(有人脸和无人脸)。而这个过程的处理是繁杂的,处理过程如下:起初每张图片都是等权重的,在每次分类后,那些被错误分类的图片的权重值将会上升。之后重复相同的过程,可以计算出新的出错比例和权重值。知道达到目标的准确率和出错比例时,该循环过程终止。此时可以得到需要的特征数。
- 最终的分类器可以用这些若分类器的加权和来表示。之所以称其为弱分类器,是因为它本身不能对图像进行分类,而是要与其他一起相结合来形成一个强分类器。论文中提到,哪怕有两百个特征都能提供到95%的正确率。而他们最终大概有设置了6000个特征,比之前的160000少了很多,可以说是一个大的收获。
- 当然,在实际的处理图片中还是有很多图片的大多数区域都是非脸部区域。因此,最好能有一个方法来使其识别一个窗口内的区域是否是一个有脸部图像,如果没有的话,可以将其一次性丢弃,不再对该区域进行处理。从而将注意力集中到有脸部区域的地方来。因此我们能有更多的时间来对面部区域进行分析。
- 对于此,论文中介绍了一种
Cascade of Classifiers的概念。及级联分类器的概念。它不是一次利用了6000种特征进行分析,而是对这些特征进行了分组。之后将其一组又一组的进行应用分析。例如,首先第一组有少量的特征,如果第一组验证该窗口为一个非脸部的区域,则对该窗口直接抛弃,不再考虑之后其余几组的特征。如果第一组验证通过,则接着进行之后的几组验证,直到所有的都验证完毕之后,我们可认定其是一个脸部。 - 作者的人脸检测大概有6000多个特征,并将这些特征分成了38组,在最初的5组中分别有 1,5,10,25,25,50个特征。(上面的那个眼睛和鼻子的那两个用来衡量的特征实际上就是利用Adaboost得到的最佳的特征)。根据作者所说,每个子窗口平均评价6000多个特征中的10个特征。
3.代码实现:
该方法不仅能够进行人脸检测,也能对汽车,房子等各种物体进行检测。OpenCv提供了训练和检测的方式,如果你想要训练一种单独的物体检测方式,你可以详细的学习一下级联分类器。
这里我们将对人脸进行识别检测,因为OpenCv里已经有许多预先分类好的人脸分析,例如眼睛,嘴巴等等。那些XML文件都在Github上可以找到,因为Github在国内下载较慢,故大家可以在CSDN上进行下载,也可私聊我单独给发送。
实现步骤
- 首先需要加载所需的XML分类器,之后用灰度模式(可以简便运算)导入我们的图片或者视频即可。
- 如果找到人脸的情况下,则记录下人脸的所在区域,之后可以创造一个
ROI region of interest,来着重分析脸部区域,方便找到眼睛所在位置。
下面展示一些 OpenCv代码
。
import cv2
filepath = "img/zhouxingchi.jpg"
img = cv2.imread(filepath)
# 转换灰色
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 显示图像
# OpenCV人脸识别分类器
face_cascade = cv2.CascadeClassifier(
"opencv-master/data/haarcascades/haarcascade_frontalface_default.xml"
)
eye_cascade = cv2.CascadeClassifier('opencv-master/data/haarcascades/haarcascade_eye.xml')
color = (0, 255, 0) # 定义绘制颜色
# 调用识别人脸
faces = face_cascade.detectMultiScale(
gray, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))
for (x,y,w,h) in faces: # 单独框出每一张人脸
#w,h分别代表脸部区域的宽和高
# 框出人脸
img = cv2.rectangle(img, (x, y), (x + h, y + w), color, 2)
# # 左眼
# cv2.circle(img, (x + w // 4, y + h // 4 + 30), min(w // 8, h // 8),
# color)
# #右眼
# cv2.circle(img, (x + 3 * w // 4, y + h // 4 + 30), min(w // 8, h // 8),
# color)
#嘴巴
# cv2.rectangle(img, (x + 3 * w // 8, y + 3 * h // 4),
# (x + 5 * w // 8, y + 7 * h // 8), color)
roi_gray=gray[y:y+h,x:x+w]
roi_color=img[y:y+h,x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(255,0,0),2)
cv2.imshow("image", img) # 显示图像
c = cv2.waitKey(100000)
cv2.destroyAllWindows()
参考示意图:
结果貌似不是那么理想,可以后续看看哪里能更改,着重在detectMultiScale上更改。这是我选了几组图片进行测试的结果。
看来蒙娜丽莎还是非常完美的了。
而卡卡罗特则完全没有被识别出来……