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 sound
playsound.playsound(path)
定义 eye_aspect_ratio 函数,该函数用于计算垂直眼睛界标之间的距离与水平眼睛界标之间的距离之比:
def eye_aspect_ratio(eye):
compute the euclidean distances between the two sets of
vertical eye landmarks (x, y)-coordinates
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
compute the euclidean distance between the horizontal
eye landmark (x, y)-coordinates
C = dist.euclidean(eye[0], eye[3])
compute the eye aspect ratio
ear = (A + B) / (2.0 * C)
return the eye aspect ratio
return 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 产生的面部标志是一个可索引的列表,见下图:
因此,要从一组面部标志中提取眼睛区域,我们只需要知道正确的数组切片索引:
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 frame
rects = detector(gray, 0)
实例化 VideoStream。
暂停一秒钟,让相机传感器预热。
开始遍历视频流中的帧。
读取下一帧,然后我们通过将其大小调整为 450 像素的宽度并将其转换为灰度进行预处理。
应用 dlib 的人脸检测器来查找和定位图像中的人脸。
下一步是应用面部标志检测来定位面部的每个重要区域:
loop over the face detections
for rect in rects:
determine the facial landmarks for the face region, then
convert the facial landmark (x, y)-coordinates to a NumPy
array
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
做了那么多年开发,自学了很多门编程语言,我很明白学习资源对于学一门新语言的重要性,这些年也收藏了不少的Python干货,对我来说这些东西确实已经用不到了,但对于准备自学Python的人来说,或许它就是一个宝藏,可以给你省去很多的时间和精力。
别在网上瞎学了,我最近也做了一些资源的更新,只要你是我的粉丝,这期福利你都可拿走。
我先来介绍一下这些东西怎么用,文末抱走。
(1)Python所有方向的学习路线(新版)
这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
最近我才对这些路线做了一下新的更新,知识体系更全面了。
(2)Python学习视频
包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。
(3)100多个练手项目
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。
(4)200多本电子书
这些年我也收藏了很多电子书,大概200多本,有时候带实体书不方便的话,我就会去打开电子书看看,书籍可不一定比视频教程差,尤其是权威的技术书籍。
基本上主流的和经典的都有,这里我就不放图了,版权问题,个人看看是没有问题的。
(5)Python知识点汇总
知识点汇总有点像学习路线,但与学习路线不同的点就在于,知识点汇总更为细致,里面包含了对具体知识点的简单说明,而我们的学习路线则更为抽象和简单,只是为了方便大家只是某个领域你应该学习哪些技术栈。
(6)其他资料
还有其他的一些东西,比如说我自己出的Python入门图文类教程,没有电脑的时候用手机也可以学习知识,学会了理论之后再去敲代码实践验证,还有Python中文版的库资料、MySQL和HTML标签大全等等,这些都是可以送给粉丝们的东西。
这些都不是什么非常值钱的东西,但对于没有资源或者资源不是很好的学习者来说确实很不错,你要是用得到的话都可以直接抱走,关注过我的人都知道,这些都是可以拿到的。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!