人脸检测方法有许多,好比opencv自带的人脸Haar特征分类器和dlib人脸检测方法等。python
对于opencv的人脸检测方法,优势是简单,快速;存在的问题是人脸检测效果很差。正面/垂直/光线较好的人脸,该方法能够检测出来,而侧面/歪斜/光线很差的人脸,没法检测。所以,该方法不适合现场应用。而对于dlib人脸检测方法采用64个特征点检测,效果会好于opencv的方法识别率会更高,本文会分别采用这几种方法来实现人脸识别。那个算法更好,跑跑代码就知道。git
首先在进行人脸识别以前须要先来学点OpenCV的基础,起码知道如何从摄像头获取当前拍到的图像吧。OpenCV其实很简单,接下来的代码就是最基本的起步点。算法
第一步:打开本机上的摄像头,实例化VideoCapture
类api
camera = cv2.VideoCapture(0)
开始第一帧图像的捕获,这个方法用来测试当前的摄像头是否可用数组
success, frame = camera.read()
当success
返回真时表示开始捕捉图像,反则表示摄像头打开失败,接下来就用最少的代码来打开摄像头并将当前的图像直接显示到一个窗口上,具体代码结构以下:网络
# coding=utf-8 # ~/learn_face/cv_base.py from __future__ import print_function import cv2 cameraCapture = cv2.VideoCapture(0) success, frame = cameraCapture.read() while success and cv2.waitKey(1) == -1: success, frame = cameraCapture.read() #TODO:在此处可放置各类对当前每一帧图像的处理 cv2.imshow("Camera", frame) cameraCapture.release() cv2.destroyAllWindows()
将上述代码存为opencv_base.py
而后在命令行直接运行查看效果:app
python opencv_base.py
效果以下:机器学习
基于Haar特征的cascade分类器(classifiers) 是Paul Viola和 Michael Jone在2001年,论文”Rapid Object Detection using a Boosted Cascade of Simple Features”中提出的一种有效的物品检测(object detect)方法。它是一种机器学习方法,经过许多正负样例中训练获得cascade方程,而后将其应用于其余图片。ide
在OpenCV3的源码的data
目录中就能够找到已训练好的HAAR算法模型,至HAAR算法的各类细节与理论有兴趣的直接去Google或者百度吧,一搜一大堆。花时间看一堆理论不如直接上代码,由代码直接理解这些复杂理论的应用更适合开发人员,毕竟咱们不是数学家。工具
使用HAAR模型识别图像中的人脸其实只要三步走,即便你对深度网络一点不懂也不要紧,再复杂的理论到最终不过是一个方法调用罢了,了解清楚其中的原理就好。
第一步:初始化分类器并载入已训练好的HARR模型:
face_cascade = cv2.CascadeClassifier(r'haarcascade_frontalface_default.xml')
第二步: 经过cv2.cvtColor
方法将当前的图像进行灰度化处理,简化图像的信息:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
第三步:而后将灰度化后的图像输入到分类器进行预判:
faces = face_cascade.detectMultiScale(gray, 1.3, 5) #识别人脸
只要faces
数组的长度大于一就表示检测到当前画面中检测到人脸,反之亦然。简单来讲其实人脸检测已经完成,
最后,为了咱们能够知道识别出来的结果,咱们能够将脸用方框给圈出来,这里写个方法来圈脸:
def mark_face(img,x,y,w,h): return cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
如下为本例的所有代码:
# coding=utf-8 # ~/learn_face/cv_haar.py from __future__ import print_function import cv2 def mark_face(img, x, y, w, h): return cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) cameraCapture = cv2.VideoCapture(0) success, frame = cameraCapture.read() face_cascade = cv2.CascadeClassifier(r'haarcascade_frontalface_default.xml') # 1.载入模型 while success and cv2.waitKey(1) == -1: success, frame = cameraCapture.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 2.生成灰度图 faces = face_cascade.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5 ) # 3.进行识别 [mark_face(frame, *args) for args in faces] #画出识别的结果 cv2.imshow("Camera", frame) cameraCapture.release() cv2.destroyAllWindows()
如下是运行效果:
运行起来就会以为HAAR的识别效果不怎么样,稍微动一下就很会识别不了。
接下来咱们试试用DLib这个老牌的专作人脸识别起家的C++库来试试,Dlib是一个跨平台的C++公共库,除了线程支持,网络支持,提供测试以及大量工具等等优势,Dlib仍是一个强大的机器学习的C++库,包含了许多机器学习经常使用的算法。同时支持大量的数值算法如矩阵、大整数、随机数运算等等。Dlib同时还包含了大量的图形模型算法。最重要的是Dlib的文档和例子都很是详细。
与HAAR分类器的检测方法相比dLib就简单得多了,只须要用dlib自带的人脸检测器detector
就够了,连模型都省了!以前的代码两步就能完成
第一步:实例化 detector
:
detector = dlib.get_frontal_face_detector()
第二步:进行人脸检测
faces = detector(frame, 1)
That's all! 是否是很简单?
如下是本例的所有代码:
# coding=utf-8 # ~/learn_face/cv_dlib.py from __future__ import print_function import cv2 import dlib cameraCapture = cv2.VideoCapture(0) success, frame = cameraCapture.read() detector = dlib.get_frontal_face_detector() while success and cv2.waitKey(1) == -1: success, frame = cameraCapture.read() faces = detector(frame, 1) for k, d in enumerate(faces): frame = cv2.rectangle(frame, (d.left(), d.top()), (d.right(), d.bottom()), (255, 0, 0), 2) cv2.imshow("Camera", frame) cameraCapture.release() cv2.destroyAllWindows()
运行上述代码后会发现dlib的效果然的比HAAR的检测效果要好不少!无论头怎么转都能瞬间识别到,画出来的矩形框都不带闪的!
接下来咱们用DLib的特征点提取器detector
所识别出来的人脸轮廓点给标记出来。关键点(landmarks)提取须要一个特征提取器predictor
,为了构建特征提取器,预训练模型必不可少。除了自行进行训练外,可使用官方提供的一个模型。该模型可从dlib sourceforge 库下载,此模型是从人脸中提出64个特征点进行检测,其准确度至关高。
具体实现思路以下:
如下为所有代码
# coding=utf-8 # ~/learn_face/landmark.py import cv2 import dlib cameraCapture = cv2.VideoCapture(0) success, frame = cameraCapture.read() detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor( "shape_predictor_68_face_landmarks.dat") while success and cv2.waitKey(1) == -1: success, frame = cameraCapture.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #生成灰度图 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) #生成直方图 clahe_image = clahe.apply(gray) detections = detector(clahe_image, 1) for k, d in enumerate(detections): shape = predictor(clahe_image, d) # 获取坐标 for i in range(1, 68): # 每张脸都有68个识别点 cv2.circle(frame, (shape.part(i).x, shape.part(i).y), 1, (0, 0, 255), thickness=2) cv2.imshow("Camera", frame) cameraCapture.release() cv2.destroyAllWindows()
运行效果:
我在macBookPro上跑以上的代码在速度是上没有什么很大区别的,至少不会产生卡顿。但若是换将代码植到树莓3和树莓Zero上区别就明显了,HAAR分类器在树梅Zero上的运行时间平均在1.2s左右,而dlib则须要8s。至于准确率Dlib又明显会优于HAAR。