通过这个中级 Python 项目,我们将制作一个睡意检测设备。无数人日夜在高速公路上行驶。出租车司机、公共汽车司机、卡车司机和长途旅行的人都缺乏睡眠。因此,在感到困倦时开车变得非常危险。
大多数事故的发生是由于驾驶员昏昏欲睡。因此,为了防止这些事故,我们将使用 Python、OpenCV 和 Keras 构建一个系统,当驾驶员感到困倦时会提醒他。
睡意检测是一种安全技术,可以防止驾驶员在驾驶时睡着引起的事故。
这个中级 Python 项目的目标是构建一个睡意检测系统,该系统将检测一个人的眼睛闭上几秒钟。该系统会在检测到困倦时提醒驾驶员。
在这个 Python 项目中,我们将使用 OpenCV 从网络摄像头收集图像并将它们输入深度学习模型,该模型将分类人的眼睛是“睁开”还是“闭上”。我们将用于此 Python 项目的方法如下:
- 步骤 1 – 将图像作为来自相机的输入。
- 步骤 2 –检测图像中的人脸并创建感兴趣区域 (ROI)。
- 步骤 3 –从 ROI 中检测眼睛并将其提供给分类器。
- 第 4 步 –分类器将分类眼睛是睁着还是闭着。
- 步骤 5 –计算分数以检查该人是否昏昏欲睡。
数据集
用于该模型的数据集由我们创建。为了创建数据集,我们编写了一个脚本,从相机捕捉眼睛并存储在我们的本地磁盘中。我们将它们分成各自的标签“打开”或“关闭”。通过删除构建模型不需要的不需要的图像来手动清理数据。该数据包括大约 7000 张不同光照条件下人眼的图像。在我们的数据集上训练模型后,我们附上了最终的权重和模型架构文件“models/cnnCat2.h5”。
现在,您可以使用这个模型来分类一个人的眼睛是睁着还是闭着。
模型架构
我们使用的模型是使用卷积神经网络 (CNN)使用Keras构建的。卷积神经网络是一种特殊类型的深度神经网络,在图像分类方面表现非常出色。CNN 基本上由一个输入层、一个输出层和一个可以有多个层的隐藏层组成。使用过滤器对这些层执行卷积运算,该过滤器对层和过滤器执行 2D 矩阵乘法。
CNN 模型架构由以下几层组成:
- 卷积层;32 个节点,内核大小 3
- 卷积层;32 个节点,内核大小 3
- 卷积层;64 个节点,内核大小 3
- 全连接层;128个节点
最后一层也是一个全连接层,有 2 个节点。在所有层中,除了我们使用 Softmax 的输出层之外,都使用了 Relu 激活函数。
先决条件
这个 Python 项目的要求是一个网络摄像头,我们将通过它捕获图像。您需要在您的系统上安装 Python(推荐 3.6 版本),然后使用 pip,您可以安装必要的包。
- OpenCV – pip install opencv-python(人脸和眼睛检测)。
- TensorFlow – pip install tensorflow(keras 使用 TensorFlow 作为后端)。
- Keras – pip install keras(构建我们的分类模型)。
- Pygame – pip install pygame(播放警报声)。
现在让我们逐步了解我们的算法是如何工作的。
- 步骤 1 – 将图像作为来自相机的输入
使用网络摄像头,我们将图像作为输入。所以为了访问网络摄像头,我们做了一个无限循环来捕捉每一帧。我们使用 OpenCV 提供的方法cv2.VideoCapture(0)来访问摄像头并设置捕获对象(cap)。cap.read()将读取每一帧并将图像存储在帧变量中。
- 步骤 2 – 检测图像中的人脸并创建感兴趣区域 (ROI)
为了检测图像中的人脸,我们需要首先将图像转换为灰度,因为用于对象检测的 OpenCV 算法在输入中采用灰度图像。我们不需要颜色信息来检测对象。我们将使用 haar 级联分类器来检测人脸。这一行用于设置我们的分类器face = cv2.CascadeClassifier(’ path to our haar cascade xml file’)。然后我们使用faces = face.detectMultiScale(gray)进行检测。它返回一个包含 x、y 坐标和高度(对象边界框的宽度)的检测数组。现在我们可以遍历面并为每个面绘制边界框。
for (x,y,w,h) in faces:
cv2.rectangle(frame, (x,y), (x+w, y+h), (100,100,100), 1 )
- 步骤 3 – 从 ROI 中检测眼睛并将其提供给分类器
检测人脸的相同程序用于检测眼睛。首先,我们分别为leye和reye 中的眼睛设置级联分类器,然后使用left_eye = leye.detectMultiScale(gray)检测眼睛。现在我们只需要从完整图像中提取眼睛数据。这可以通过提取眼睛的边界框来实现,然后我们可以使用此代码从帧中提取眼睛图像。
l_eye = frame[ y : y+h, x : x+w ]
- 第 4 步 – 分类器将分类眼睛是睁着还是闭着
我们使用CNN分类器来预测眼睛状态。要将我们的图像输入模型,我们需要执行某些操作,因为模型需要正确的尺寸才能开始。首先,我们使用r_eye = cv2.cvtColor(r_eye, cv2.COLOR_BGR2GRAY)将彩色图像转换为灰度。然后,我们将图像调整为 2424 像素,因为我们的模型是在 2424 像素图像上训练的 cv2.resize(r_eye, (24,24))。我们标准化我们的数据以获得更好的收敛r_eye = r_eye/255 (所有值都在 0-1 之间)。扩展维度以输入我们的分类器。我们使用model = load_model(‘models/cnnCat2.h5’)加载我们的模型。现在我们用我们的模型lpred = model.predict_classes(l_eye)预测每只眼睛
. 如果 lpred[0] 的值 = 1,则表示眼睛是睁开的,如果 lpred[0] 的值 = 0,则表示眼睛是闭着的。
- 步骤 5 – 计算分数以检查人是否昏昏欲睡
分数基本上是一个我们将用来确定人闭上眼睛的时间的值。所以如果两只眼睛都闭上,我们会继续增加分数,当眼睛睁开时,我们会减少分数。我们正在使用 cv2.putText() 函数在屏幕上绘制结果,该函数将显示人员的实时状态。
cv2.putText(frame, “Open”, (10, height-20), font, 1, (255,255,255), 1, cv2.LINE_AA )
例如,如果分数变得大于 15,则定义阈值,这意味着人的眼睛长时间闭上。这是我们使用sound.play()发出警报的时候
我们主文件的源代码如下所示:
import cv2
import os
from keras.models import load_model
import numpy as np
from pygame import mixer
import time
mixer.init()
sound = mixer.Sound('alarm.wav')
face = cv2.CascadeClassifier('haar cascade files\haarcascade_frontalface_alt.xml')
leye = cv2.CascadeClassifier('haar cascade files\haarcascade_lefteye_2splits.xml')
reye = cv2.CascadeClassifier('haar cascade files\haarcascade_righteye_2splits.xml')
lbl=['Close','Open']
model = load_model('models/cnncat2.h5')
path = os.getcwd()
cap = cv2.VideoCapture(0)
font = cv2.FONT_HERSHEY_COMPLEX_SMALL
count=0
score=0
thicc=2
rpred=[99]
lpred=[99]
while(True):
ret, frame = cap.read()
height,width = frame.shape[:2]
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face.detectMultiScale(gray,minNeighbors=5,scaleFactor=1.1,minSize=(25,25))
left_eye = leye.detectMultiScale(gray)
right_eye = reye.detectMultiScale(gray)
cv2.rectangle(frame, (0,height-50) , (200,height) , (0,0,0) , thickness=cv2.FILLED )
for (x,y,w,h) in faces:
cv2.rectangle(frame, (x,y) , (x+w,y+h) , (100,100,100) , 1 )
for (x,y,w,h) in right_eye:
r_eye=frame[y:y+h,x:x+w]
count=count+1
r_eye = cv2.cvtColor(r_eye,cv2.COLOR_BGR2GRAY)
r_eye = cv2.resize(r_eye,(24,24))
r_eye= r_eye/255
r_eye= r_eye.reshape(24,24,-1)
r_eye = np.expand_dims(r_eye,axis=0)
rpred = model.predict_classes(r_eye)
if(rpred[0]==1):
lbl='Open'
if(rpred[0]==0):
lbl='Closed'
break
for (x,y,w,h) in left_eye:
l_eye=frame[y:y+h,x:x+w]
count=count+1
l_eye = cv2.cvtColor(l_eye,cv2.COLOR_BGR2GRAY)
l_eye = cv2.resize(l_eye,(24,24))
l_eye= l_eye/255
l_eye=l_eye.reshape(24,24,-1)
l_eye = np.expand_dims(l_eye,axis=0)
lpred = model.predict_classes(l_eye)
if(lpred[0]==1):
lbl='Open'
if(lpred[0]==0):
lbl='Closed'
break
if(rpred[0]==0 and lpred[0]==0):
score=score+1
cv2.putText(frame,"Closed",(10,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
# if(rpred[0]==1 or lpred[0]==1):
else:
score=score-1
cv2.putText(frame,"Open",(10,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
if(score<0):
score=0
cv2.putText(frame,'Score:'+str(score),(100,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
if(score>15):
#person is feeling sleepy so we beep the alarm
cv2.imwrite(os.path.join(path,'image.jpg'),frame)
try:
sound.play()
except: # isplaying = False
pass
if(thicc<16):
thicc= thicc+2
else:
thicc=thicc-2
if(thicc<2):
thicc=2
cv2.rectangle(frame,(0,0),(width,height),(0,0,255),thicc)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
打开网络摄像头并开始检测可能需要几秒钟的时间。
示例截图:
概括
在这个 Python 项目中,我们构建了一个 昏昏欲睡的驾驶员警报系统,您可以通过多种方式实现该系统 。我们使用 OpenCV 使用 haar 级联分类器检测人脸和眼睛,然后使用 CNN 模型来预测状态。