0%

基于dlib,OpenCV,YOLOv5的疲劳驾驶与分心驾驶检测系统(附带效果展示)-CSDN博客

Excerpt

文章浏览阅读1.9k次,点赞2次,收藏33次。基于dlib,OpenCV,YOLOv5的疲劳驾驶与分心驾驶检测系统。数字信号处理课程设计非常简单的数字信号处理课程设计,先开个坑,考完试再填,大概七月初会上传完整的版本,预览图在下面,如果实在需要可以邮箱联系,Toss_3@std.uestc.edu.cn


非常简单的数字信号处理课程设计,详细内容邮箱联系,Toss_3@163.com

项目地址:Captain-Rhino/Fatigue_Detecting: (Course Design)Fatigue-driving-detecting system based on yolov8, dlib and opencv (github.com)

已编辑… 2024.6.30

数字信号处理课程设计——基于dlib,OpenCV,YOLOv5的疲劳驾驶与分心驾驶检测系统(附带效果展示)

1.疲劳驾驶检测部分

这里采用的是dlib库的68点人脸检测模型,标记人脸关键点

使用的shape_predictor_68_face_landmarks.dat

68点人脸检测模型的下载链接:http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2

通过openCV调用本地摄像头实现人脸检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def _learning_face(self):

"""dlib的初始化调用"""

self.detector = dlib.get_frontal_face_detector()

self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

data = {

'type':'msg',

'value':u"加载模型成功!!!\n"

}

self.thread_signal.emit(data)

(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]

(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]

(mStart, mEnd) = face_utils.FACIAL_LANDMARKS_IDXS["mouth"]

self.cap = cv2.VideoCapture(self.VIDEO_STREAM)

data = {

'type': 'msg',

}

if self.cap.isOpened() == True:

self.CAMERA_STYLE = True

data['value'] = u"打开摄像头成功!!!"

else:

data['value'] = u"摄像头打开失败!!!"

self.thread_signal.emit(data)

res = []

t_time = datetime.datetime.now()

e_time = datetime.datetime.now()

h_time = datetime.datetime.now()

while (self.cap.isOpened()):

start_time = datetime.datetime.now()

res = [' ' for i in range(9)]

flag, im_rd = self.cap.read()

label = myframe.frametest(im_rd)

print(label)

img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY)

faces = self.detector(img_gray, 0)

if (len(faces) != 0):

res[0] = '识别到人脸'

for k, d in enumerate(faces):

cv2.rectangle(im_rd, (d.left(), d.top()), (d.right(), d.bottom()), (0, 0, 255), 1)

shape = self.predictor(im_rd, d)

for i in range(68):

cv2.circle(im_rd, (shape.part(i).x, shape.part(i).y), 2, (0, 255, 0), -1, 8)

shape = face_utils.shape_to_np(shape)

1.1眨眼检测

        通过定位眼睛和眼睑的轮廓得出眼睛的长宽比(Eye Aspect Ratio,EAR),用于估计睁眼状态。EAR详细内容参见基于人眼纵横比计算的人眼闭合检测算法_闭眼算法-CSDN博客

        通过EAR值的改变来判断眨眼与否,并统计一个时间周期内(这里设置的时间周期为10s)的眨眼次数,并设定一个阈值。如果在这个时间周期内眨眼次数超过阈值,则会触发提醒警告,进入下一个时间周期。

        下面是判断眨眼的相关代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
if self.fun[0]:

leftEye = shape[lStart:lEnd]

rightEye = shape[rStart:rEnd]

leftEAR = self.eye_aspect_ratio(leftEye)

rightEAR = self.eye_aspect_ratio(rightEye)

ear = (leftEAR + rightEAR) / 2.0

leftEyeHull = cv2.convexHull(leftEye)

rightEyeHull = cv2.convexHull(rightEye)

cv2.drawContours(im_rd, [leftEyeHull], -1, (0, 255, 0), 1)

cv2.drawContours(im_rd, [rightEyeHull], -1, (0, 255, 0), 1)

if ear < self.EYE_AR_THRESH:

self.COUNTER += 1

res[5] = '闭眼'

else:

if self.COUNTER >= self.EYE_AR_CONSEC_FRAMES:

self.TOTAL += 1

self.thread_signal.emit({'type':'msg','value':time.strftime('%Y-%m-%d %H:%M:%S ', time.localtime()) + u"眨眼"})

self.COUNTER = 0

res[5] = '睁眼'

1.2闭眼检测

         同样是通过EAR值进行检测,如果EAR值一直小于阈值,当累积一定时间就记为

1.3哈欠检测

        嘴部长宽比MAR>0.5时,视为张嘴。连续四帧以上处于张嘴状态之后睁闭嘴,则视为打哈欠一次。

1.4瞌睡(前/后)点头检测与左/右歪头检测

        估计头部姿态需要一个标准的头部姿态坐标(世界坐标)作为参考系,将检测到的实时头部姿态坐标(像素坐标)与其进行比较,凭借对比结果得出当前头部姿态的偏移程度。选取通用三维人脸模型作为标准的头部坐标参数。

通用三维人脸模型中人脸关键点的部分坐标

        实时头部姿态坐标则采用dilib库中的dlib.get_frontal_face_detector()函数提取到的对应人脸帧图像的68个特征坐标点。

        由于标准的头部姿态坐标为三位坐标,实时头部姿态坐标为二位坐标,两者并不匹配,所以需要将两个坐标相统一。

转换示意图

        相机坐标系与像素坐标系转换关系:

        相机坐标系与世界坐标系转换关系:

        根据以上两个关系式可以得出世界坐标系与像素坐标系转换关系:

        式中s为比例因子;K为相机内参矩阵;R 为代表相机坐标系到世界坐标系姿态变化的旋转矩阵;T为相对空间位置变化的平移向量。

        根据得到的变换关系式,在我们输入对应的标准的头部姿态坐标和实时头部姿态坐标参数后,即可求解出旋转矩阵R。

        进而根据求解得到的旋转矩阵,我们可以求解出头部偏移的三个角度:Pitch(俯仰角)、Roll(翻滚角)、Yaw(偏航角)。

        角度求解公式:

式中:ψ为俯仰角;ϕ为偏航角;γ为翻滚角。

2.分心驾驶检测部分

2.1接口文件

        在分心驾驶检测中,我们可以利用预训练的YOLO模型来实现目标检测的功能。首先,我们需要将每一帧图像传递给YOLO模型进行处理,以识别图像中出现的物体,并获取它们的标签信息。通过这一步骤,我们可以获得图像中出现的可能分心驾驶行为相关的物体信息。

        接下来,我们将检测到的物体标签与预定义的分心驾驶行为标签进行比较。这些分心驾驶行为标签可以包括使用手机、看向侧面镜、与乘客交谈等。通过比较检测到的物体标签与分心行为标签,我们可以判断当前是否存在分心驾驶的行为。如果检测到分心行为,我们可以触发相应的警报或采取适当的措施,以提醒驾驶员注意道路安全。

        为了实现这一功能,我们需要创建一个YOLO接口文件,其目的是将视频流捕捉到的每一帧图像传递给YOLO模型进行处理,并执行相应的操作。这个接口文件可以通过简单的软件编程来实现,例如使用Python编程语言和相关的深度学习框架,如TensorFlow或PyTorch。

        接口文件的编程过程中,我们需要设置YOLO模型的参数和配置,加载预训练的权重文件,以及定义图像处理和物体检测的流程。一旦接口文件完成,我们就可以将视频流的每一帧图像传递给接口文件,它将使用YOLO模型进行目标检测,并与分心驾驶行为进行比较。根据比较结果,我们可以采取相应的措施进行提醒以确保驾驶员的安全。

2.2调用YOLO实现实时检测

        通过将摄像头捕捉到的帧画面实时传入YOLO模型中并返回输出结果,我们可以实现实时的基于行为特征的分心驾驶检测。在这个过程中,使用训练好的轻量化YOLOv5模型能够在基于RTX3060算力的平台上提供优秀的性能。

        YOLOv5是YOLO系列的最新版本,相较于之前的版本,它采用了一系列的优化措施,包括网络架构设计和训练策略的改进。这使得YOLOv5模型具有更高的精度和更快的推理速度,非常适合在实时应用中使用。

        在基于RTX3060算力的平台上,我们可以充分利用其强大的计算能力来加速YOLOv5模型的推理过程。这样,我们就能够在较短的时间内处理摄像头捕捉到的帧画面,并获得相应的检测结果。这种结合在整合的检测系统中,可以实现每秒达到24-27帧的处理速度,从而实现了良好的实时性能。

        通过这样的实时检测系统,我们可以及时发现驾驶员的分心行为,如使用手机、低头看东西或者分散注意力等,进而采取适当的措施来提醒驾驶员,确保道路安全。系统的实时性能对于分心驾驶检测至关重要,因为它需要在短时间内对每一帧图像进行处理和判断。

2.3通过检测所得标签触发提示警报

        在这一部分我们设定,触发警报的标签为手机和水杯,对应分心驾驶中的接打电话和开车喝水,当YOLO模型检测到这两类标签时便会触发提示音,提醒驾驶员不要分心驾驶以确保行车安全。

3.效果图

 歪头——超过时间阈值会提醒

 使用手机——提醒