非常简单的数字信号处理课程设计,详细内容邮箱联系,Toss_3@163.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调用本地摄像头实现人脸检测
def _learning_face(self):
"""dlib的初始化调用"""
# 使用人脸检测器get_frontal_face_detector
self.detector = dlib.get_frontal_face_detector()
# dlib的68点模型,使用作者训练好的特征预测器
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"]
# 建cv2摄像头对象
self.cap = cv2.VideoCapture(self.VIDEO_STREAM)
data = {
'type': 'msg',
}
if self.cap.isOpened() == True: # 返回true/false 检查初始化是否成功
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()
#将摄像头读取的im_rd返回到myframe函数
label = myframe.frametest(im_rd)
print(label)
# 取灰度
img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY)
# 使用人脸检测器检测每一帧图像中的人脸。并返回人脸数faces
faces = self.detector(img_gray, 0)
# 如果检测到人脸
if (len(faces) != 0):
res[0] = '识别到人脸'
# enumerate方法同时返回数据对象的索引和数据,k为索引,d为faces中的对象
for k, d in enumerate(faces):
# 用红色矩形框出人脸
cv2.rectangle(im_rd, (d.left(), d.top()), (d.right(), d.bottom()), (0, 0, 255), 1)
# 使用预测器得到68点数据的坐标
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)
# 将脸部特征信息转换为数组array的格式
shape = face_utils.shape_to_np(shape)
1.1眨眼检测
通过定位眼睛和眼睑的轮廓得出眼睛的长宽比(Eye Aspect Ratio,EAR),用于估计睁眼状态。EAR详细内容参见基于人眼纵横比计算的人眼闭合检测算法_闭眼算法-CSDN博客
通过EAR值的改变来判断眨眼与否,并统计一个时间周期内(这里设置的时间周期为10s)的眨眼次数,并设定一个阈值。如果在这个时间周期内眨眼次数超过阈值,则会触发提醒警告,进入下一个时间周期。
下面是判断眨眼的相关代码
if self.fun[0]:
# 提取左眼和右眼坐标
leftEye = shape[lStart:lEnd]
rightEye = shape[rStart:rEnd]
# 构造函数计算左右眼的EAR值,使用平均值作为最终的EAR
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.convexHull获得凸包位置,使用drawContours画出轮廓位置进行画图操作
cv2.drawContours(im_rd, [leftEyeHull], -1, (0, 255, 0), 1)
cv2.drawContours(im_rd, [rightEyeHull], -1, (0, 255, 0), 1)
# 循环,满足条件的,眨眼次数+1
if ear < self.EYE_AR_THRESH: # 眼睛长宽比:0.2
self.COUNTER += 1
res[5] = '闭眼'
else:
# 如果连续3次都小于阈值,则表示进行了一次眨眼活动
if self.COUNTER >= self.EYE_AR_CONSEC_FRAMES: # 阈值:3
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.效果图
歪头——超过时间阈值会提醒
使用手机——提醒