人脸检测高级:疲劳检测

article/2025/9/23 19:38:37

今天我们实现疲劳检测。 如果眼睛已经闭上了一段时间,我们会认为他们开始打瞌睡并发出警报来唤醒他们并引起他们的注意。我们测试一段视频来展示效果。同时代码中保留开启摄像头的的代码,取消注释即可使用。

image-20211208161834615

使用 OpenCV 构建犯困检测器

要开始我们的实现,打开一个新文件,将其命名为 detect_drowsiness.py ,并插入以下代码:

# import the necessary packages
from scipy.spatial import distance as dist
from imutils.video import VideoStream
from imutils import face_utils
from threading import Thread
import numpy as np
import playsound
import argparse
import imutils
import time
import dlib
import cv2

导入们所需的 Python 包。

我们还需要 imutils 包,我的一系列计算机视觉和图像处理功能,以便更轻松地使用 OpenCV。

如果您的系统上还没有安装 imutils,您可以通过以下方式安装/升级 imutils:

pip install --upgrade imutils

还将导入 Thread 类,以便我们可以在与主线程不同的线程中播放我们的警报,以确保我们的脚本不会在警报响起时暂停执行。

为了真正播放我们的 WAV/MP3 闹钟,我们需要 playsound 库,这是一个纯 Python 的跨平台实现,用于播放简单的声音。

playsound 库可以通过 pip 方便地安装:

pip install playsound

但是,如果您使用的是 macOS(就像我为这个项目所做的那样),您还需要安装 pyobjc,否则当您实际尝试播放声音时,您将收到与 AppKit 相关的错误:

pip install pyobjc

接下来,我们需要定义 sound_alarm 函数,该函数播放音频文件:

def sound_alarm(path):# play an alarm soundplaysound.playsound(path)

定义 eye_aspect_ratio 函数,该函数用于计算垂直眼睛界标之间的距离与水平眼睛界标之间的距离之比:

def eye_aspect_ratio(eye):# compute the euclidean distances between the two sets of# vertical eye landmarks (x, y)-coordinatesA = dist.euclidean(eye[1], eye[5])B = dist.euclidean(eye[2], eye[4])# compute the euclidean distance between the horizontal# eye landmark (x, y)-coordinatesC = dist.euclidean(eye[0], eye[3])# compute the eye aspect ratioear = (A + B) / (2.0 * C)# return the eye aspect ratioreturn ear

由于OpenCV不能直接绘制中文,我们还需定义绘制中文的方法:

def cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20):if (isinstance(img, np.ndarray)):  # 判断是否OpenCV图片类型img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))# 创建一个可以在给定图像上绘图的对象draw = ImageDraw.Draw(img)# 字体的格式fontStyle = ImageFont.truetype("font/simsun.ttc", textSize, encoding="utf-8")# 绘制文本draw.text((left, top), text, textColor, font=fontStyle,stroke_width=2)# 转换回OpenCV格式return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

接下来,定义命令行参数:

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,help="path to facial landmark predictor")
ap.add_argument("-v", "--video", type=str, default="",help="path to input video file")
ap.add_argument("-a", "--alarm", type=str, default="",help="path alarm .WAV file")
ap.add_argument("-w", "--webcam", type=int, default=0,help="index of webcam on system")
args = vars(ap.parse_args())

犯困检测器需要一个命令行参数,后跟两个可选参数,每个参数的详细信息如下:

–shape-predictor :这是 dlib 的预训练面部标志检测器的路径。 您可以使用本博文底部的“下载”部分将检测器和本教程的源代码一起下载。

–video:视频文件。本文用视频文件测试。

–alarm :您可以在此处选择指定要用作警报的输入音频文件的路径。

–webcam :此整数控制内置网络摄像头/USB 摄像头的索引。

定义了命令行参数,我们还需要定义几个重要的变量:

# define two constants, one for the eye aspect ratio to indicate
# blink and then a second constant for the number of consecutive
# frames the eye must be below the threshold for to set off the
# alarm
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 48
# initialize the frame counter as well as a boolean used to
# indicate if the alarm is going off
COUNTER = 0
ALARM_ON = False

定义了 EYE_AR_THRESH。如果眼睛纵横比低于此阈值,我们将开始计算人闭上眼睛的帧数。

如果该人闭上眼睛的帧数超过 EYE_AR_CONSEC_FRAMES,我们将发出警报。

在实验中,我发现 0.3 的 EYE_AR_THRESH 在各种情况下都能很好地工作(尽管您可能需要为自己的应用程序自己调整它)。

我还将 EYE_AR_CONSEC_FRAMES 设置为 48 ,这意味着如果一个人连续闭眼 48 帧,我们将播放警报声。

您可以通过降低 EYE_AR_CONSEC_FRAMES 来使疲劳检测器更敏感——同样,您可以通过增加它来降低疲劳检测器的敏感度。

定义了 COUNTER,即眼睛纵横比低于 EYE_AR_THRESH 的连续帧的总数。

如果 COUNTER 超过 EYE_AR_CONSEC_FRAMES ,那么我们将更新布尔值 ALARM_ON。

dlib 库附带了一个基于定向梯度的人脸检测器的直方图以及一个人脸地标预测器——我们在以下代码块中实例化了这两个:

# initialize dlib's face detector (HOG-based) and then create
# the facial landmark predictor
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])

dlib 产生的面部标志是一个可索引的列表,见下图:

image-20211208165348604

因此,要从一组面部标志中提取眼睛区域,我们只需要知道正确的数组切片索引:

# grab the indexes of the facial landmarks for the left and
# right eye, respectively
(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]

使用这些索引,我们将能够通过数组切片轻松提取眼睛区域。

我们现在准备启动我们的睡意检测器的核心:

# start the video stream thread
print("[INFO] starting video stream thread...")
vs = VideoStream(src=args["webcam"]).start()
time.sleep(1.0)
# loop over frames from the video stream
while True:# grab the frame from the threaded video file stream, resize# it, and convert it to grayscale# channels)frame = vs.read()frame = imutils.resize(frame, width=450)gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# detect faces in the grayscale framerects = detector(gray, 0)

实例化 VideoStream。

暂停一秒钟,让相机传感器预热。

开始遍历视频流中的帧。

读取下一帧,然后我们通过将其大小调整为 450 像素的宽度并将其转换为灰度进行预处理。

应用 dlib 的人脸检测器来查找和定位图像中的人脸。

下一步是应用面部标志检测来定位面部的每个重要区域:

	# loop over the face detectionsfor rect in rects:# determine the facial landmarks for the face region, then# convert the facial landmark (x, y)-coordinates to a NumPy# arrayshape = predictor(gray, rect)shape = face_utils.shape_to_np(shape)# extract the left and right eye coordinates, then use the# coordinates to compute the eye aspect ratio for both eyesleftEye = shape[lStart:lEnd]rightEye = shape[rStart:rEnd]leftEAR = eye_aspect_ratio(leftEye)rightEAR = eye_aspect_ratio(rightEye)# average the eye aspect ratio together for both eyesear = (leftEAR + rightEAR) / 2.0

循环遍历检测到的每个人脸——在我们的实现中(特别与司机睡意有关),我们假设只有一张脸——司机——但我把这个 for 循环留在这里以防万一你想应用多张脸视频的技术。

对于每个检测到的人脸,我们应用 dlib 的面部标志检测器并将结果转换为 NumPy 数组。

使用 NumPy 数组切片,我们可以分别提取左眼和右眼的 (x, y) 坐标。

给定双眼的 (x, y) 坐标,我们然后计算它们的眼睛纵横比。

Soukupová 和 Čech 建议将两个眼睛的纵横比平均在一起以获得更好的估计。

然后,我们可以使用下面的 cv2.drawContours 函数可视化框架上的每个眼睛区域——这在我们尝试调试脚本并希望确保正确检测和定位眼睛时通常很有帮助:

		# compute the convex hull for the left and right eye, then# visualize each of the eyesleftEyeHull = cv2.convexHull(leftEye)rightEyeHull = cv2.convexHull(rightEye)cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)

最后,我们现在准备检查视频流中的人是否出现犯困的症状:

		# check to see if the eye aspect ratio is below the blink# threshold, and if so, increment the blink frame counterif ear < EYE_AR_THRESH:COUNTER += 1# if the eyes were closed for a sufficient number of# then sound the alarmif COUNTER >= EYE_AR_CONSEC_FRAMES:# if the alarm is not on, turn it onif not ALARM_ON:ALARM_ON = True# check to see if an alarm file was supplied,# and if so, start a thread to have the alarm# sound played in the backgroundif args["alarm"] != "":t = Thread(target=sound_alarm,args=(args["alarm"],))t.deamon = Truet.start()# draw an alarm on the frameframe=cv2ImgAddText(frame,"醒醒,别睡!",10,30,(255, 0, 0),30)# otherwise, the eye aspect ratio is not below the blink# threshold, so reset the counter and alarmelse:COUNTER = 0ALARM_ON = False

检查眼睛纵横比是否低于“眨眼/闭合”眼睛阈值 EYE_AR_THRESH 。

如果是,我们增加 COUNTER ,即该人闭上眼睛的连续帧总数。

如果 COUNTER 超过 EYE_AR_CONSEC_FRAMES,那么我们假设此人开始打瞌睡。

进行了另一次检查,以查看警报是否已打开——如果没有,我们将其打开。

处理播放警报声音,前提是在执行脚本时提供了 --alarm 路径。我们特别注意创建一个单独的线程来负责调用 sound_alarm 以确保我们的主程序在声音播放完毕之前不会被阻塞。

绘制文本 DROWSINESS ALERT!在我们的框架上——同样,这通常有助于调试,尤其是当您不使用 playsound 库时。

最后,第 136-138 行处理眼睛纵横比大于 EYE_AR_THRESH 的情况,表示眼睛是睁开的。如果眼睛是睁开的,我们重置计数器并确保警报关闭。

我们的睡意检测器中的最后一个代码块处理将输出帧显示到我们的屏幕上:

		# draw the computed eye aspect ratio on the frame to help# with debugging and setting the correct eye aspect ratio# thresholds and frame counterscv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)# show the framecv2.imshow("Frame", frame)key = cv2.waitKey(1) & 0xFF# if the `q` key was pressed, break from the loopif key == ord("q"):break
# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()

到这里编码完成!!!

测试疲劳检测器

运行指令:

python detect_drowsiness.py --shape-predictor shape_predictor_68_face_landmarks.dat --video 12.mp4  --alarm alarm.mp3

运行结果:

image-20211208180257859

检测到打瞌睡就会发出提示,并将提醒打印在视频上面
完整代码如下:
https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/67343016


http://chatgpt.dhexx.cn/article/3CC5iOZp.shtml

相关文章

数字图像处理课程设计-疲劳检测系统

文章目录 数字图像处理课程设计-疲劳检测系统前言一、课程设计任务二、设计框图三、准备工作四、任务流程&#xff14;.&#xff11;视频预处理4.2图片分割 五、结果六、项目总结 数字图像处理课程设计-疲劳检测系统 前言 此系统基于MATLAB设计,核心思想是PERCLOS算法. 参考文…

MATLAB的疲劳检测系统

一、课题介绍 本设计针对现有逐帧眼睛定位方法计算量大&#xff0c;速度慢的缺点&#xff0c;提出一种用于疲劳驾驶实时监测的眼睛定位方法&#xff0c;该方法能够在保证眼睛定位准确性的同时&#xff0c;减少人脸定位的计算量&#xff0c;从而提高图像处理速度&#xff0c;实现…

毕业设计 机器视觉 opencv 深度学习 驾驶人脸疲劳检测系统 -python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业…

利用opencv 做一个疲劳检测系统(2)

文章目录 杂谈实现步骤核心算法交互界面界面代码检测效果源代码 杂谈 最近发现视力下降严重&#xff0c; 可能跟我的过度用眼有关&#xff0c;于是想着能不能做一个检测用眼疲劳的&#xff0c;灵感来自特斯拉的疲劳检测系统。 效果如下&#xff1a; 实现步骤 实现核心算法制…

基于Matlab深度学习的驾驶员疲劳检测系统

随着城市化进程不断加快,中国汽车的需求 量和保有量也急剧上升。 截至 2020 年 9 月,中国 汽车保有量达到了 2.75 亿辆,随着车辆保有量的 增加,交通事故的发生率也在逐年上升。2017 年交通事故共计 20.3 万起,因车祸死亡人数 6.3 万 人,2018 年交通事故较 2017 年上升 20.6%,20…

基于MATLAB的疲劳检测系统

基于MATLAB的疲劳检测系统 一、课题介绍 随着汽车工业的不断发展,随之而来的社会问题也愈加严重。交通事故给人们造成巨大伤害的同时,也给社会带来沉重的负担和影响。由于疲劳驾驶是引起交通事故的一个主要原因。因此,研究一种合理有效、实时准确检测驾驶员疲劳驾驶的非接触式车…

基于图像分割的疲劳检测方法研究

问题&#xff1a; 随着社会的不断进步,汽车已经成为了当今世界拥有主宰地位的交通工具。然而汽车数量的上升同时也导致交通事故数量猛增,由司机疲劳驾驶引起的交通事故的发生频率更是不断攀升。疲劳的复杂性引起了各个学科的研究者广泛关注&#xff0c;传统的疲劳评估方法不仅需…

疲劳检测实验报告

疲劳检测实验报告 邢益玮 201930101151 2021/1/13 &#xff08;重度拖延症了&#xff0c;内容又有点多&#xff0c;学长和老师不好意思了&#x1f64f;&#x1f64f;&#x1f64f;&#xff09; 文章目录 疲劳检测实验报告前言一、最初的尝试——dlib库1.1 信息收集1.2 为Anac…

基于MATLAB的疲劳检测

在疲劳检测算法中&#xff0c;个人感觉最好的算法是 Dlib 这个库可以实现人脸的关键点的检测&#xff0c;有了人眼睛的点位&#xff0c;便可以检测眨眼之类的频率来进行人眼识别&#xff1b; 但是在matlab中调用dlip需要比较复杂的操做&#xff0c;有兴趣的可以网上搜索做法&am…

MATLAB疲劳检测系统

目录 摘要 I Abstract II 1 绪论 1 1.1 研究背景及意义 1 1.2 国内外疲劳驾驶研究现状 2 1.3本文的主要研究内容及组织结构 3 2 人脸检测与定位技术 4 2.1人脸检测与定位技术概述 4 2.1.1基于图像的人脸检测方法 4 2.1.2基于特征的人脸检测方法 5 2.2 Adaboost算法介绍 6 2.2.1…

python疲劳检测

疲劳驾驶检测 结合眼睛的闭合状态和嘴巴闭合状态&#xff0c;综合判断驾驶人员的疲劳状况。python编写&#xff0c;tensorflow&#xff0c;opencv和dlib实现人脸的检测和特征点提取。 效果图&#xff1a; 效果视频: python opencv 疲劳驾驶检测 项目代码下载&#xff1a; pyt…

疲劳检测(一)Landmark + HeadPose

数据集 1&#xff09;Drazy 数据集&#xff1a;红外&#xff0c;包含多种用于疲劳检测的数据&#xff0c;(有电极) 14*3*10min get http://www.drozy.ulg.ac.be/ 2&#xff09;NTHU 驾驶员疲劳检测数据集 http://cv.cs.nthu.edu.tw/php/callforpaper/datasets/DDD/ 3&am…

26.疲劳检测

目录 1 项目介绍 2 代码实现 2.1 导入库 2.2 定义68个关键点 2.3 定义eye_aspect_ratio() 2.4 定义参数 2.5 定义阈值 2.6 定义次数 2.7 创建检测器 2.8 获取左眼与右眼的起始点与终止点 2.9 读取视频 2.10 定义shape_to_np() 2.11 遍历每一帧 2.11…

Dlib模型之驾驶员疲劳检测一(眨眼)

目录 序目的技术背景 正文&#xff08;1&#xff09;环境搭建&#xff08;2&#xff09;下载开源数据集&#xff08;3&#xff09;视觉疲劳检测原理&#xff08;4&#xff09;主要代码思路&#xff08;5&#xff09;运行效果 序 目的 经查阅相关文献&#xff0c;疲劳在人体面…

Python人脸检测实战之疲劳检测

本文主要介绍了实现疲劳检测&#xff1a;如果眼睛已经闭上了一段时间&#xff0c;我们会认为他们开始打瞌睡并发出警报来唤醒他们并引起他们的注意&#xff0c;感兴趣的朋友可以了解一下。 今天我们实现疲劳检测。 如果眼睛已经闭上了一段时间&#xff0c;我们会认为他们开始打…

计算机视觉项目实战-驾驶员疲劳检测

&#x1f60a;&#x1f60a;&#x1f60a;欢迎来到本博客&#x1f60a;&#x1f60a;&#x1f60a; 本次博客内容将继续讲解关于OpenCV的相关知识 &#x1f389;作者简介&#xff1a;⭐️⭐️⭐️目前计算机研究生在读。主要研究方向是人工智能和群智能算法方向。目前熟悉深度学…

【毕业设计】深度学习疲劳检测 驾驶行为检测 - python opencv cnn

文章目录 0 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目…

Pandas和Numpy:常见函数参数inplace的作用

1.inplace参数的作用 pandas中&#xff0c;包括numpy中很多方法都设置了inplace参数。该参数的主要作用是指示是否在本地数据上做更改&#xff0c;其只能接受bool型参数&#xff0c;即 True和False. 具体示例如下&#xff1a; data为原始数据。接下来用dataframe.drop()删除Ti…

编译inplace_abn

出现以上问题 1、检查pytorch版本&#xff0c;一般1.5以上 2、检查cuda版本&#xff0c;一般10.1以上 3、检查环境变量设置 linux&#xff1a;export -p 重点检查 PATH 、LD_LIBRARY_PATH 不能重复设置变量&#xff0c;将重复的删掉 unset LANG 是将LANG删掉 declare -x LANG是…

build_ext --inplace 是什么意思

如果是做目标检测类的任务&#xff0c;经常需要用到cocoapi python setup.py build_ext --inplacebuild_ext是指明python生成C/C的扩展模块(build C/C extensions (compile/link to build directory))--inplace指示 将编译后的扩展模块直接放在与test.py同级的目录中。 流程如…