[python]毕业设计基于python+opencv的疲劳驾驶检测项目源码和实现过程有详细代码注释

这段代码是一个疲劳驾驶检测系统,它使用计算机视觉和深度学习技术来监测驾驶员的眼睛和嘴巴状态,以判断是否出现闭眼或打哈欠等疲劳迹象。以下是代码的主要功能和组件的详细解释:

  1. 导入模块

    • scipy.spatial.distance 用于计算欧氏距离。
    • imutils 提供图像处理辅助函数。
    • dlib 用于人脸识别和特征点检测。
    • cv2 和 numpy 用于图像处理和数组操作。
    • PIL(Python Imaging Library)用于在图像上添加文字。
  2. 定义常量

    • EYE_AR_THRESH 是眼睛纵横比的阈值,低于这个值表示可能闭眼。
    • EYE_AR_CONS_FRAMES 连续闭眼帧数达到此值判定为疲劳。
    • MOU_AR_THRESH 嘴巴纵横比的阈值,高于此值表示可能在打哈欠。
    • EYE_CL_TIME 闭眼持续时间,超过这个时间认为是长时间闭眼。
  3. 函数定义

    • eye_aspect_ratio(eye) 计算眼睛的纵横比。
    • mouth_aspect_ratio(mou) 计算嘴巴的纵横比。
    • cv2_add_chinese_text(img, text, position, _text_color, _text_size) 在图像上添加中文文本。
  4. 眼睛和嘴巴检测

    • eyes_mouth_detection(ear, _mouth_ear, frame, _count, yawns, prev_yawn_status, EYE_STATUS, t1) 根据眼睛和嘴巴的纵横比判断疲劳状态,并在图像上显示提示信息。
  5. 疲劳驾驶检测主程序

    • driver_fatigue_detection()
      • 初始化变量,如眼睛状态、计数器、哈欠状态和计数。
      • 使用cv2.VideoCapture打开视频文件或摄像头。
      • 使用dlib的面部检测器和形状预测器找到人脸特征点。
      • 对每一帧图像进行处理,检测眼睛和嘴巴,计算纵横比,调用eyes_mouth_detection进行疲劳判断。
      • 在图像上绘制眼睛和嘴巴的轮廓,并显示相关信息。
      • 当检测到疲劳迹象时,显示警告信息。
      • 按 'q' 键退出。
  6. 主入口

    • if __name__ == '__main__': 确保当脚本作为主程序运行时,调用 driver_fatigue_detection()

这个系统可以用于实时监控驾驶员的疲劳状态,提醒驾驶员休息,提高行车安全。

核心代码:

# -*- coding:utf-8 -*-
"""
Author:Huang YuWei
Date:2022/10/15
"""
from scipy.spatial import distance as dist
from imutils import face_utils
import imutils
import dlib
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import time
# 定义眼睛的比的阈值
EYE_AR_THRESH = 0.25
# 定义眼睛闪烁阈值,连续闭眼次数
EYE_AR_CONS_FRAMES = 40
# 定义嘴巴的纵横比的阈值
MOU_AR_THRESH = 0.85
# 定义闭眼时间
EYE_CL_TIME=2000

# 计算垂直眼睛界标之间的距离与水平眼睛界标之间的距离之比
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])
    # 计算眼睛比例
    ear = (A + B) / (2.0 * C)
    return ear


# 计算上下嘴唇纵横比
def mouth_aspect_ratio(mou):
    # 计算水平面之间的欧氏距离
    X = dist.euclidean(mou[0], mou[6])
    # 计算垂直线之间的欧氏距离
    Y1 = dist.euclidean(mou[2], mou[10])
    Y2 = dist.euclidean(mou[4], mou[8])
    # 取平均值
    Y = (Y1 + Y2) / 2.0
    # 计算比例
    mar = Y / X
    return mar


# 定义中文输出
def cv2_add_chinese_text(img, text, position, _text_color=(0, 255, 0), _text_size=25):
    if isinstance(img, np.ndarray):  # 判断是否OpenCV图片类型
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    # 创建一个可以在给定图像上绘图的对象
    draw = ImageDraw.Draw(img)
    # 字体的格式
    _font_style = ImageFont.truetype(
        "simsun.ttc", _text_size, encoding="utf-8")
    # 绘制文本
    draw.text(position, text, _text_color, font=_font_style)
    # 转换回OpenCV格式
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)


# 判断眼睛,嘴巴
def eyes_mouth_detection(ear, _mouth_ear, frame, _count, yawns, prev_yawn_status,EYE_STATUS,t1):
    # 通过检查眼睛的纵横比,如果眼睛纵横比小于阈值,则为闭眼
    t2 = 0
    if ear < EYE_AR_THRESH:
        if  EYE_STATUS:
            t1=int(round(time.time() * 1000))
        EYE_STATUS = False
        if t1 != 0:
            t2 = int(round(time.time() * 1000))
            print("闭眼时长", int(t2 - t1))
        if (t2 - t1) > EYE_CL_TIME:
            frame = cv2_add_chinese_text(frame, "检测到长时间闭眼!", (120, 5), (255, 0, 0))
        _count += 1
        frame = cv2_add_chinese_text(frame, "闭眼!", (10, 5), (255, 0, 0))
        # 如果闭眼次数大于阈值
        if _count >= EYE_AR_CONS_FRAMES:
            frame = cv2_add_chinese_text(frame, "检测到有睡意,醒醒!", (120, 35), (255, 0, 0))
    # 否则为睁眼
    else:
        EYE_STATUS = True
        _count = 0
        frame = cv2_add_chinese_text(frame, "睁眼", (10, 5), (0, 255, 0))

    # 通过检查嘴唇的纵横比,如果嘴唇纵横比大于阈值,则为打哈欠
    if _mouth_ear > MOU_AR_THRESH:
        frame = cv2_add_chinese_text(frame, "打哈欠!", (10, 35), (255, 0, 0))
        _yawn_status = True
        output_text = "打哈欠次数: " + str(yawns + 1)
        frame = cv2_add_chinese_text(frame, output_text, (10, 70), (0, 0, 225))
    else:
        _yawn_status = False
    if prev_yawn_status == True and _yawn_status == False:
        yawns += 1
    return frame, _count, yawns, _yawn_status,EYE_STATUS,t1


# 检测入口
def driver_fatigue_detection():
    EYE_STATUS = True
    t1=0
    # 加载摄像头,0表示使用默认摄像头,直接写视频路径表示读取该视频
    camera = cv2.VideoCapture("vi.mp4")
    #camera = cv2.VideoCapture(0)
    # 这里直接使用dlib库训练好的人脸68点位特征模型
    predictor_path = "shape_predictor_68_face_landmarks.dat"

    # 初始化基于HOG的dlib人脸识别器
    detector = dlib.get_frontal_face_detector()
    # 加载模型
    predictor = dlib.shape_predictor(predictor_path)

    # 获取左眼特征
    (_lt_start, _lt_end) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
    # 获取右眼特征
    (_rt_start, _rt_end) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
    # 获取嘴巴特征
    (_mh_start, _mh_end) = face_utils.FACIAL_LANDMARKS_IDXS["mouth"]

    # 定义已闭眼次数
    COUNTER = 0
    # 定义打哈欠状态
    _yawn_status = False
    # 定义打哈欠次数
    yawns = 0
    # 循环视频
    while True:
        # 读取视频
        ret, frame = camera.read()
        # 定义视频尺寸
        frame = imutils.resize(frame, width=750)
        # 将图像转成灰度
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        prev_yawn_status = _yawn_status
        # 检测灰度框中的人脸
        rects = detector(gray, 0)
        # 循环人脸
        for rect in rects:
            # 确定面部区域的面部特征
            # 将面部坐标(x,y)坐标转换为NumPy
            shape = predictor(gray, rect)
            shape = face_utils.shape_to_np(shape)

            # 提取左眼和右眼坐标
            _left_eye = shape[_lt_start:_lt_end]
            _right_eye = shape[_rt_start:_rt_end]
            # 提取嘴唇坐标
            mouth = shape[_mh_start:_mh_end]
            # 然后计算双眼的眼睛纵横比的坐标
            _LEFT_EAR = eye_aspect_ratio(_left_eye)
            _RIGHT_EAR = eye_aspect_ratio(_right_eye)
            # 计算上下嘴唇纵横比的坐标
            _MOUTH_EAR = mouth_aspect_ratio(mouth)
            # 计算平均双眼的眼睛纵横比
            _EYE_EAR = (_LEFT_EAR + _RIGHT_EAR) / 2.0

            # 计算双眼和嘴唇的凸包
            _left_eye_hull = cv2.convexHull(_left_eye)
            _right_eye_hull = cv2.convexHull(_right_eye)
            _mouth_hull = cv2.convexHull(mouth)

            # 绘制轮廓
            cv2.drawContours(frame, [_left_eye_hull], -1, (0, 255, 255), 1)
            cv2.drawContours(frame, [_right_eye_hull], -1, (0, 255, 255), 1)
            cv2.drawContours(frame, [_mouth_hull], -1, (0, 255, 0), 1)

            # 实时输出眼睛和嘴巴纵横比
            frame = cv2_add_chinese_text(frame, "(眼睛)EAR: {:.2f}".format(_EYE_EAR), (550, 5), (255, 0, 0))
            frame = cv2_add_chinese_text(frame, "(嘴巴)MAR: {:.2f}".format(_MOUTH_EAR), (550, 45), (255, 0, 0))

            # 调用方法进行对比纵横比
            frame, COUNTER, yawns, _yawn_status,EYE_STATUS,t1 = eyes_mouth_detection(_EYE_EAR, _MOUTH_EAR, frame, COUNTER, yawns,
                                                                       prev_yawn_status,EYE_STATUS,t1)

        # 显示视频
        cv2.imshow("video", frame)
        key = cv2.waitKey(1) & 0xFF
        # 按q退出
        if key == ord("q"):
            break
    # 关闭窗口
    cv2.destroyAllWindows()
    # 释放相机流
    camera.release()

if __name__ == '__main__':
    driver_fatigue_detection()

完整源码下载地址:

https://download.csdn.net/download/FL1768317420/89191094

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
设计与实现Python基于OpenCV疲劳检测系统包括源码、数据库和说明文档。 首先,源码部分主要包括以下几个模块: 1. 数据采集模块:使用OpenCV库进行摄像头视频的采集和每帧图像的处理。 2. 眼睛检测模块:使用Haar Cascade分类器来检测人眼的位置和状态。 3. 眼睛状态检测模块:通过计算眼睛的高宽比例、瞳孔的颜色变化等指标来判断眼睛是否疲劳。 4. 疲劳检测模块:根据眼睛状态判断疲劳程度,并触发警报功能。 5. 用户界面模块:提供一个简单的图形用户界面,用于系统的操作、参数设置和实时显示结果。 其次,数据库部分用于存储疲劳检测系统的相关数据,包括用户的登陆信息、历史记录、警报记录等。 最后,说明文档应包含以下内容: 1. 系统的整体设计思路和流程:包括每个模块的功能和相互间的关系。 2. 源码文件的介绍:列出每个源码文件的作用和关系,以及如何编译和运行系统。 3. 采集和处理图像的方法和算法:详细说明如何使用OpenCV库来进行图像采集和处理,包括眼睛位置检测和状态判断的方法。 4. 数据库的设计和使用:介绍数据库的结构和表的设计,以及如何使用数据库来存储和查询相关数据。 5. 用户界面的设计和操作:说明系统的用户界面的设计思路和操作方式。 综上所述,Python基于OpenCV疲劳检测系统的设计与实现包括源码、数据库和说明文档,通过图像采集和处理、眼睛状态检测、疲劳判断和警报等模块实现疲劳检测功能,并使用数据库来存储相关数据,最后通过说明文档进行系统的介绍和操作说明。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FL1768317420

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值