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

非常简单的数字信号处理课程设计,详细内容邮箱联系,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调用本地摄像头实现人脸检测

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.效果图

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

 使用手机——提醒

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值