转:https://www.toutiao.com/i6899377526662038029/?is_new_connect=0&is_new_user=0
1 说明
=====
1.1 高速上开车容易疲劳,双眼就会闭合,几秒钟可能诱发意外,甚至造成严重事故!
1.2 既然python这么厉害,是不是可以实现报警呢?当然可以!!所以高速交警一旦发现驾驶员有双眼闭合代表疲劳,可能就会直接拨打司机的电话,告知提醒驾驶员已经疲劳,危险驾驶,建议下一个服务区强制休息,以免意外发生。
1.3 当然上述太麻烦了,可以生成一个成品,自己放在自己的汽车上,摄像头对准自己的面部,一旦自己闭眼就会报警,一个小小的新科技产品从此就诞生了!!汽车生产制造商们注意了,可以卖钱哟。取个名字叫开始防眯眼警报狗!!哈哈哈。
2 分析
====
2.1 资料来源:竟然有巨大bug(真不该),对代码进行增加,删除,注释,排版和运行调试。
https://github.com/raja434/driver-fatigue-detection-system
2.2 对于那个巨大bug,竟然有人去问stackoverflow,也没有解决。
https://stackoverflow.com/questions/53579289/run-a-certain-code-while-it-detects-something-python/53579720
2.3 被作者'易三一世'搞定了!!,分享出来,感谢头条,易三一世+原作者。
3 文件
=====
3.1 图
3.2 这个文件从计算机系统中搜索,安装软件复制过来:shape_predictor_68_face_landmarks.dat
3.3 drowsiness_detection.py代码名改为这样比较正规。
3.4 执行:终端输入:
python3.8 drowsiness_detection.py --alarm=alarm.wav
3.5 打开摄像头,睁眼识别,如果闭眼一会就会报警;如果继续睁眼,报警声就会停止;如果再闭眼,报警声还会响起......
4 drowsiness_detection.py代码讲解
============================
4.1 导入模块
#第1步:导入模块
from scipy.spatial import distance as dist
import imutils
from imutils.video import VideoStream
from imutils import face_utils
from threading import Thread
import argparse
import time
import dlib
import cv2
import numpy as np
import pyglet
没有的模块,这样安装,本机是这样安装
sudo pip3.8 install -i https://pypi.tuna.tsinghua.edu.cn/simple xxx
本机环境:python3.8+deepin-linux深度操作系统+微软编辑器vscode;
软件:opencv4.2.0+numpy1.19.4+dlib19.21.99
4.2
#第2步:终端参数构建
ap = argparse.ArgumentParser()
#默认为0,就是摄像头获取视频
ap.add_argument("-w", "--webcam", type=int, default=0,
help="index of webcam on system")
#巨大的bug,原来没有这个的,我自己增加的
ap.add_argument("-a", "--alarm",
help="index of alarm on system")
args = vars(ap.parse_args())
4.3 eye=眼睛,ear=耳朵,怕误解将ear改为EAR=eye aspect ratio
#第3步:函数定义
#报警声函数定义
def sound_alarm(path):
# play an alarm sound
music = pyglet.resource.media('alarm.wav')
#bug,原来未对齐,缩进去了
music.play()
pyglet.app.run()
#返回双眼睑比率函数测定
def eye_aspect_ratio(eye):
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
C = dist.euclidean(eye[0], eye[3])
# compute the eye aspect ratio=ear,not ear耳朵
#ear = (A + B) / (2.0 * C)
EAR = (A + B) / (2.0 * C)
#return ear
return EAR
4.4
#第4步:参数初始化
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 48
COUNTER = 0
ALARM_ON = False
#加载dlib的侦测器
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
#原来的dat名字都错了,该文件需要自己复制过来
#predictor = dlib.shape_predictor("68 face landmarks.dat")
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
#获取左右眼的坐标点信息
(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)
4.5
#第5步:循环
# loop over frames from the video stream
while True:
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)
# loop over the face detections
for rect in rects:
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
leftEye = 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 eyes
#修改为大写
#ear = (leftEAR + rightEAR) / 2.0
EAR = (leftEAR + rightEAR) / 2.0
leftEyeHull = 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)
#修改为大写
#if ear < EYE_AR_THRESH:
if EAR < EYE_AR_THRESH:
COUNTER += 1
if COUNTER >= EYE_AR_CONSEC_FRAMES:
# if the alarm is not on, turn it on
if not ALARM_ON:
ALARM_ON = True
if args["alarm"] != "": #报错,已经上面修改好了
t = Thread(target=sound_alarm,
args=(args["alarm"],))
t.deamon = True
t.start()
# draw an alarm on the frame
cv2.putText(frame, "DROWSINESS ALERT!", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
else:
COUNTER = 0
ALARM_ON = False
#修改为大写
#cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "EAR: {:.2f}".format(EAR), (300, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
# show the frame
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
#退出设置
if key == ord("q"):
break
#第6步:收尾和结束
# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()
5 易三一世已经亲测过,可行.
自己整理并分享出来,希望大家喜欢,也感谢原作者的github,别忘了给他点个星星。