困倦检测系统

在此 Python 项目中,我们将使用 OpenCV 从网络摄像头收集图像并将其输入深度学习模型,该模型将分类人的眼睛是“睁开”还是“闭着”,来决定是否困倦,如果判断困倦则调用警铃进行报警行为。我们将在这个 Python 项目中使用的方法如下:

步骤 1 –将图像作为来自相机的输入。

步骤 2 –检测图像中的人脸并创建感兴趣区域 (ROI)。

步骤 3 –从 ROI 中检测眼睛并将其输入分类器。

第 4 步 –分类器将对眼睛是睁着还是闭着进行分类。

步骤 5 –计算分数以检查该人是否困倦。

项目效果的展示如下:

困倦检测数据集

该数据包含约 7000 张不同光照条件下人眼的图像。您可以使用此模型来对人的眼睛是睁着还是闭着进行分类。

下载数据集:https://www.kaggle.com/datasets/serenaraju/yawn-eye-dataset-new

模型架构

我们使用的模型是使用卷积神经网络 (CNN)通过 Keras 构建的。卷积神经网络是一种特殊类型的深度神经网络,在图像分类方面表现非常出色。

CNN 模型架构由以下层组成:

  • 卷积层;32 个节点,卷积核大小 3
  • 卷积层;32 个节点,卷积核大小 3
  • 卷积层;64 个节点,卷积核大小 3
  • 全连接层;128个节点

最后一层也是一个有 2 个节点的全连接层。除了我们使用 Softmax 的输出层之外,所有层都使用 Relu 激活函数。

项目先决条件

这个 Python 项目的要求是一个网络摄像头,我们将通过它捕获图像。您需要在系统上安装Python(推荐3.6版本),然后使用pip,您可以安装必要的软件包。

  1. OpenCV – pip install opencv-python(面部和眼睛检测)。
  2. TensorFlow – pip install tensorflow(keras 使用 TensorFlow 作为后端)。
  3. Keras – pip install keras(构建我们的分类模型)。
  4. Pygame – pip install pygame(播放闹钟声音)。

执行困倦检测的步骤

项目压缩包中的zip 的内容是:

  • “haar Cascade files”文件夹包含从图像中检测对象所需的 xml 文件。在我们的例子中,我们正在检测人的面部和眼睛。
  • models 文件夹包含我们的模型文件“cnnCat2.h5”,该文件是在卷积神经网络上进行训练的。
  • 我们有一个音频剪辑“alarm.wav”,当人们感到昏昏欲睡时会播放该音频剪辑。
  • “Model.py”文件包含我们通过对数据集进行训练来构建分类模型的程序。您可以在该文件中看到卷积神经网络的实现。
  • “睡意检测.py”是我们项目的主文件。要开始检测过程,我们必须运行该文件。

现在让我们逐步了解我们的算法是如何工作的。

步骤 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 坐标和高度(对象边界框的宽度)。现在我们可以迭代这些面并为每个面绘制边界框。

第 3 步 – 从 ROI 中检测眼睛并将其输入分类器

检测眼睛的过程与检测面部的过程相同。首先,我们分别为leyereye中的眼睛设置级联分类器,然后使用left_eye = leye.detectMultiScale(gray)检测眼睛。现在我们只需要从完整图像中提取眼睛数据。这可以通过提取眼睛的边界框来实现,然后我们可以使用此代码从帧中提取眼睛图像。

l_eye仅包含眼睛的图像数据。这将被输入到我们的 CNN 分类器中,该分类器将预测眼睛是睁着还是闭着。同样,我们将把右眼提取到r_eye中。

步骤 4 – 分类器将对眼睛是睁着还是闭着进行分类

我们使用卷积模型分类器来预测眼睛状态。为了将图像输入模型,我们需要执行某些操作,因为模型需要正确的尺寸来开始。

首先,我们使用r_eye = cv2.cvtColor(r_eye, cv2.COLOR_BGR2GRAY)将彩色图像转换为灰度图像。

然后,我们将图像大小调整为 24*24 像素,因为我们的模型是在 24*24 像素图像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() 函数在屏幕上绘制结果,该函数将显示人员的实时状态。

完整的代码如下:

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 = np.argmax(model.predict(r_eye), axis=-1)
        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 = np.argmax(model.predict(l_eye), axis=-1)
        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()

执行困倦检测项目

让我们执行项目并查看我们的机器学习项目的工作情况。要启动项目,可以直接在IDE平台运行drowsiness detector.py,也可以打开命令提示符,进入主文件“drowsiness detector.py”所在的目录。使用此命令运行脚本。

python drowsiness detector.py

打开网络摄像头并开始检测可能需要几秒钟的时间。

截图示例:

项目代码链接:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

作者

arwin.yu.98@gmail.com

相关文章

心律失常的数据分析与模型分类项目

项目背景 心脏疾病一直是全球健康的主要挑战之...

读出全部

基于图神经网络进行分子活性预测

该项目通过利用图神经网络来解析和预测化学分子...

读出全部