开始前,您将了解如何使用称为haar cascades的特征映射器检测人眼的眨眼。在项目中,我们将使用 Python 语言和 OpenCV 库分别进行算法执行和图像处理。我们将在项目中使用的 haar 级联经过预训练并与 OpenCV 库一起存储为 haarcascade_frontalface_default.xml 和 haarcascade_eye_tree_eyeglasses.xml 文件。该项目开发了对系统的基本了解,例如驾驶员睡意检测、眨眼锁定、眼睛检测、面部检测以及使用 OpenCV 库的 haar 级联使用。
关于 Haar Cascades:
Haar 基于特征的级联分类器是 Paul Viola 和 Michael Jones 在其 2001 年的论文“Rapid Object Detection using a Boosted Cascade of Simple Features”中提出的一种有效的对象检测方法。它是一种基于机器学习的方法,其中级联函数是从很多正面和负面的图像中训练出来的。这里正图像是包含目标对象的样本,负图像是不包含目标对象的样本。训练分类器需要大量的正样本和负样本。
现在,我们使用上图所示的 haar 特征从给定的输入图像中提取特征。它们就像卷积核。每个特征都是通过从黑色矩形下的像素总和中减去白色矩形下的像素总和而获得的单个值。
过度计算:
使用所有可能的分类器大小来计算特征,但是计算特征所需的计算量,一个24×24的窗口会产生超过 160000 个特征。同样对于每个特征计算,还需要像素的总和。为了降低计算成本,haar 级联的创建者引入了积分图像,这意味着无论您的图像多么大,它将给定像素的计算减少为仅涉及四个像素的操作。
虚假的特征
现在计算出来的特征中,大部分特征都是假的和不相关的。现在,应用于图像区域的窗口可能会看到一个不同的区域,该区域看起来与窗口具有相同的特征,但实际上并非如此。因此,需要删除由AdaBoost完成的错误特征,这有助于从 160000 多个特征中选择最佳特征。自适应提升的 Adaboost 缩写形式是一种机器学习算法,用于此唯一任务。
算法 :
1、帧被捕获并转换为灰度。
2、双边过滤用于去除杂质。
3、使用 haarcascade 检测人脸。
4、人脸的 ROI(图像区域)被馈送到算法的眼睛检测部分。
5、检测到眼睛并将结果列表传递给 if-else 构造。
6、如果列表的长度超过两个,则表示眼睛在那里。
7、否则程序被标记为眨眼并重新启动。
代码:
haarcascade_frontalface_default.xml和haarcascade_eye_tree_eyeglasses.xml是与python脚本同目录下的xml文件。
xml脚本获取: https://github.com/opencv/opencv/tree/4.x/data/haarcascades
# 所有的导入都在这里
import numpy as np
import cv2
# 从xml文件初始化人脸和眼睛级联分类器
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye_tree_eyeglasses.xml')
# 可变存储执行状态
first_read = True
# 开始视频捕捉
cap = cv2.VideoCapture(0)
ret,img = cap.read()
while(ret):
ret,img = cap.read()
# 将记录的图像转换为灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用过滤器去除杂质
gray = cv2.bilateralFilter(gray,5,1,1)
# 对输入人眼分类器的图像区域进行人脸检测
faces = face_cascade.detectMultiScale(gray, 1.3, 5,minSize=(200,200))
if(len(faces)>0):
for (x,y,w,h) in faces:
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
# Roi_face即人眼分类器输入的人脸
roi_face = gray[y:y+h,x:x+w]
roi_face_clr = img[y:y+h,x:x+w]
eyes = eye_cascade.detectMultiScale(roi_face,1.3,5,minSize=(50,50))
# 检查眼睛的长度对象为眼睛
if(len(eyes)>=2):
# 检查程序是否正在运行检测
if(first_read):
cv2.putText(img,
"Eye detected press s to begin",
(70,70),
cv2.FONT_HERSHEY_PLAIN, 3,
(0,255,0),2)
else:
cv2.putText(img,
"Eyes open!", (70,70),
cv2.FONT_HERSHEY_PLAIN, 2,
(255,255,255),2)
else:
if(first_read):
# 在开始前确保眼睛是否在
cv2.putText(img,
"No eyes detected", (70,70),
cv2.FONT_HERSHEY_PLAIN, 3,
(0,0,255),2)
else:
# 这将在控制台上打印并重新启动算法
print("Blink detected--------------")
cv2.waitKey(3000)
first_read=True
else:
cv2.putText(img,
"No face detected",(100,100),
cv2.FONT_HERSHEY_PLAIN, 3,
(0,255,0),2)
# 用密钥控制算法
cv2.imshow('img',img)
a = cv2.waitKey(1)
if(a==ord('q')):
break
elif(a==ord('s') and first_read):
#This will start the detection
first_read = False
cap.release()
cv2.destroyAllWindows()
样本输出:
左边为: 检测到眼孔
右边为: 没有检测到眼睛