博主介绍:✌全网粉丝50W+,前互联网大厂软件研发、集结硕博英豪成立软件开发工作室,专注于计算机相关专业项目实战6年之久,累计开发项目作品上万套。凭借丰富的经验与专业实力,已帮助成千上万的学生顺利毕业,选择我们,就是选择放心、选择安心毕业✌
> 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与我联系了。🍅

点击查看作者主页,了解更多项目!

🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。🍅

1、毕业设计:2025年计算机专业毕业设计选题汇总(建议收藏)✅

2、最全计算机专业毕业设计选题大全(建议收藏)✅

1、项目介绍

技术栈:
python语言、Django框架、hyperlpr、opencv、Dlib、疲劳驾驶检测、Echarts可视化

2、项目界面

(1)疲劳驾驶检测—摄像头检测
在这里插入图片描述

(2)疲劳驾驶检测—摄像头检测
在这里插入图片描述

(3)数据大屏

在这里插入图片描述

(4)数据可视化分析
在这里插入图片描述

(5)数据管理

在这里插入图片描述

(6)注册登录

在这里插入图片描述

3、项目说明

摘 要

精神疲劳是指在过渡体力劳动或者连续工作的情况下造成的生理和心理机能下降,精神疲劳严重影响人们的注意力、思维判断以及决策能力,在实际生活过程中精神疲劳容易造成交通事故、医疗事故以及影响工作和学习的效率。疲劳驾驶作为道路安全的重要隐患,为了避免疲劳驾驶行为的发生,我国要求驾驶员连续驾驶4小时后需要强制休息,同时还通过疲劳检测设备对于疲劳驾驶行为进行预警,然而检测设备的成本较高且便携性较低,因此借助系统平台开发设计一款针对疲劳检测的系统是非常有需求空间的。
本文提出了一种基于眼动信号及人脸判断的疲劳检测方法,借助OpenCV图像处理库检测测试者的眼睛闭合程度,同时通过面部表情呈现及眨眼频次来表征测试者的疲劳程度,借助人脸及人眼图像识别的结果参数实现疲劳测试的评判,同时在系统的呈现设计上利用了Python编程语言以及Mysql数据库,通过系统平台的图像识别、图片分析及照片管理等功能模块实现系统平台的管理和应用,进一步提升了疲劳检测应用的便捷性,通过疲劳检测系统的应用提升了人身财产的安全性。

关键词:OpenCV; Python语言;人脸识别;疲劳检测;

此次疲劳检测系统的开发设计主要基于国内外的研究成果以及当前的应用需求,通过人脸图像识别的方式来检测人员的眨眼频次及打哈欠次数,利用图片识别的内容判断被检测者的疲劳程度。本文在开发设计过程中主要应用了Python编程语言以及Opencv图像识别技术,借助WEB平台实现在线疲劳状态监测,同时利用Mysql数据库实现了图像识别内容的存储和管理。通过系统平台的开发设计可以帮助检测机构实现更加便捷的线上检测途径,同时也可以帮助很多高危企业用户检测员工的疲劳状态,利用线上系统应用的便捷性来帮助人们实现疲劳工作状态预警,从而避免不必要的人身财产损失。当然此次系统平台的开发设计在内容的实现及检测判断条件上还有待加强,在检测运算的快速性和稳定性上还存在可提升空间。

4、核心代码

# -*- coding:utf-8 -*-
import os.path

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


work_dir = os.path.dirname(os.path.abspath(__file__))
# 计算垂直眼睛界标之间的距离与水平眼睛界标之间的距离之比
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
    eye_status = '睁眼'
    yawn = False
    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))
        eye_status = '闭眼'
        # 如果闭眼次数大于阈值
        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:
        yawn = True
        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,eye_status,yawn


# 检测入口
def driver_fatigue_detection():
    EYE_STATUS = True
    t1=0
    # 加载摄像头,0表示使用默认摄像头,直接写视频路径表示读取该视频
    camera = cv2.VideoCapture(0)
    #camera = cv2.VideoCapture(0)
    # 这里直接使用dlib库训练好的人脸68点位特征模型
    predictor_path = os.path.join(work_dir,"shape_predictor.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)
        cv2.imwrite("./1.jpg",frame)
        # 将图像转成灰度
        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,eye_status,yawn = 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()
def image_detection(input_path,save_path):
    EYE_STATUS = True
    t1=0
    # 这里直接使用dlib库训练好的人脸68点位特征模型
    predictor_path = os.path.join(work_dir,"shape_predictor.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
    # 循环视频

    frame = cv2.imread(input_path)
    #cv2.imwrite("./1.jpg",frame)
    # 将图像转成灰度
    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,eye_status,yawn  = eyes_mouth_detection(_EYE_EAR, _MOUTH_EAR, frame, COUNTER, yawns,
                                                                   prev_yawn_status,EYE_STATUS,t1)
        print(eye_status,yawn)
        cv2.imwrite(save_path,frame)
        return eye_status,yawn
if __name__ == '__main__':
    driver_fatigue_detection()    
    image_detection()

🍅✌感兴趣的可以先收藏起来,点赞关注不迷路,想学习更多项目可以查看主页,大家在毕设选题,项目编程以及论文编写等相关问题都可以给我留言咨询,希望可以帮助同学们顺利毕业!🍅✌

5、源码获取方式

🍅由于篇幅限制,获取完整文章或源码、代做项目的,拉到文章底部即可看到个人联系方式。🍅

点赞、收藏、关注,不迷路,下方查看👇🏻获取联系方式👇🏻

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐