使用OpenCV进行实时面部和眼睛检测
在进行人脸检测之前,我们需要知道Haar-like特征和级联分类器是什么。传统上使用图像强度(使用RGB)使得特征计算的任务计算成本昂贵。然后人们开始谈论基于Haar小波的特征计算,以降低计算成本。Paul Voila和Michel Jones在2001年使用了这个概念并开发了Haar-like features。Haar-like特征考虑在检测窗口中的特定位置处的相邻矩形区域,对每个区域中的像素强度求和并计算这些和之间的差异。该差异用于对图像的子部分进行分类。例如,在人脸图像中,眼睛的区域比脸颊更暗。
因此,当检测图像中的对象时,目标尺寸的窗口在输入图像上移动,并且对于图像的每个子部分,计算类Haar特征。然后将该差异与将对象与非对象分开的学习阈值进行比较。
Haar-liker特征是弱学习者或分类器,因此需要大量Haar-like的特征来以更高的准确度对图像进行分类。这是因为一个简单的图像可以包含超过180,000个Haar-liker的微小特征。这就是为什么在Haar-liker特征中被组织成一个叫做分类器级联的东西来形成一个强大的学习者或分类器。由于整体图像的使用,可以以比传统方法更快的速度计算出Haar-liker的特征。
现在让我们开始代码。我们需要的第一件事是在我们的计算机上安装OpenCV。如果取决于您的操作系统,安装可能非常具有挑战性,但让我们看一下更简单的方法。如果您已经安装了anaconda,只需执行以下命令即可安装OpenCV及其依赖项:
conda install -c menpo opencv3
测试是否正确安装:
$ python3
>> import cv2
如果python shell中的这个命令没有给出任何错误,那么祝贺一切都已设置好。OpenCV配有探测器和训练器。现在,为了检测眼睛和面部,我们需要两个具有预定义Haar特征或分类器的XML文件。当然,您也可以构建自己的分类器来检测对象。但是我们在这里检测面部和眼睛,openCV已经带有分类器,所以为什么要重新发明轮子。它将为我们节省大量开发系统的时间。我们可以从OpenCV的Github仓库下载以下两个文件:
- haarcascade_frontalface_default.xml(https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml)
- haarcascade_eye.xml(https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_eye.xml)
现在在与上述XML文件相同的目录中创建另一个名为facedetection.py的文件。然后在python文件中,我们首先导入OpenCV库并加载两个级联。
由于Haar-like特征分类器或级联仅适用于灰度图像,因此我们需要将图像转换为灰度。
import cv2
# Load the Haar cascades
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
现在我们需要一个能够进行检测的函数。我们首先得到检测面部和眼睛的坐标。然后我们将迭代视频中检测到的面部,并为每个面部绘制指示面部的矩形。在每个面孔内,我们都会发现眼睛。
import cv2
# Load the Haar cascades
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eyes_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
# Define function that will do detection
def detect(gray, frame):
""" Input = greyscale image or frame from video stream
Output = Image with rectangle box in the face
"""
# Now get the tuples that detect the faces using above cascade
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
# faces are the tuples of 4 numbers
# x,y => upperleft corner coordinates of face
# width(w) of rectangle in the face
# height(h) of rectangle in the face
# grey means the input image to the detector
# 1.3 is the kernel size or size of image reduced when applying the detection
# 5 is the number of neighbors after which we accept that is a face
# Now iterate over the faces and detect eyes
for (x,y,w,h) in faces:
cv2.rectangle(frame, (x,y), (x+w, y+h), (255,0,0), 2)
# Arguements => image, top-left coordinates, bottomright coordinates, color, rectangle border thickness
# we now need two region of interests(ROI) grey and color for eyes one to detect and another to draw rectangle
roi_gray = gray[y:y+h, x:x+w]
roi_color = frame[y:y+h, x:x+w]
# Detect eyes now
eyes = eyes_cascade.detectMultiScale(roi_gray, 1.1, 3)
# Now draw rectangle over the eyes
for (ex, ey, ew, eh) in eyes:
cv2.rectangle(roi_color, (ex,ey), (ex+ew, ey+eh), (0, 255, 0), 2)
return frame
现在,您需要从网络摄像头捕获视频,然后从这些视频中选择一个帧。获得帧后,需要转换为灰度,然后将彩色和灰度图像帧传递给上述函数。
# Capture video from webcam
video_capture = cv2.VideoCapture(0)
# Run the infinite loop
while True:
# Read each frame
_, frame = video_capture.read()
# Convert frame to grey because cascading only works with greyscale image
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Call the detect function with grey image and colored frame
canvas = detect(gray, frame)
# Show the image in the screen
cv2.imshow("Video", canvas)
# Put the condition which triggers the end of program
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()
现在,如果您运行上述代码,您将看到您的眼睛和脸部被检测到。