当前位置: 首页 > article >正文

《计算机视觉》—— 疲劳检测

文章目录

  • 一、疲劳检测实现的思想
  • 二、代码实现

一、疲劳检测实现的思想

  • 了解以下几篇文章有助于了解疲劳检测的方法
    • 基于dlib库的人脸检测
      • https://blog.csdn.net/weixin_73504499/article/details/142977202?spm=1001.2014.3001.5501
    • 基于dlib库的人脸关键点定位
      • https://blog.csdn.net/weixin_73504499/article/details/142990867?spm=1001.2014.3001.5501
    • 基于dlib库的人脸关键部位的轮廓检测
      • https://blog.csdn.net/weixin_73504499/article/details/143027371?spm=1001.2014.3001.5501
  • 实现疲劳检测的方法核心方法是通过眼睛的关键点定位来实现的,具体思想如下:
    • 通过68个人脸关键点定位后的效果如下:
      在这里插入图片描述

    • 通过[36-41]和[42~45]这分别两组6个关键点来确定左眼和右眼的位置,眼睛的闭合程度会改变这些点的位置, 因此可以通过这6个点来计算眼睛睁开时的宽高比

    • 设定一个阈值来判断眼睛的闭合程度,低于这个阈值则表示眼睛处于非正常睁开状态,若长时间都低于这个阈值,则会判定为是处于疲劳状态

    • 具体实现如下图
      在这里插入图片描述

      • 取眼睛的6个关键点的上下两组点,分别求出两个距离,并取平均值,作为眼睛镇开时的高度
      • 取左右两个点,计算距离,作为眼睛镇开时的宽度
      • 高度与宽度的比值与设定的阈值进行比较,并做出判断

二、代码实现

好未写完!!!!!!!!!!!!!!!!

  • 定义计算眼睛纵横比的函数

    def eye_aspect_ratio(eye):
        A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))
        B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))
        C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))
        ear = ((A + B) / 2.0) / C
        return ear
    
  • 定义向图片中添加中文的函数

    def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
        if (isinstance(img, np.ndarray)):  # 判断是否是OpenCV图片类型
            img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))  # 实现 array 到 image 的转换
        draw = ImageDraw.Draw(img)  # 在img图片上创建一个绘图的对象
        # 字体的格式                       C 盘中的 Windows/Fonts 中,复制到此文件夹下可看到文件名
        fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
        draw.text(position, text, textColor, font=fontStyle)  # 绘制文本
        return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)  # 转换回 OpenCV 格式
    
  • 完整代码:

    import numpy as np
    import dlib
    import cv2
    from sklearn.metrics.pairwise import euclidean_distances    # 计算欧氏距离
    from PIL import Image, ImageDraw, ImageFont
    
    """------计算眼睛纵横比------"""
    def eye_aspect_ratio(eye):
        A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))
        B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))
        C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))
        ear = ((A + B) / 2.0) / C
        return ear
    
    """ 向图片中添加中文 """
    def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
        if (isinstance(img, np.ndarray)):  # 判断是否是OpenCV图片类型
            img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))  # 实现 array 到 image 的转换
        draw = ImageDraw.Draw(img)  # 在img图片上创建一个绘图的对象
        # 字体的格式                       C 盘中的 Windows/Fonts 中,复制到此文件夹下可看到文件名
        fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
        draw.text(position, text, textColor, font=fontStyle)  # 绘制文本
        return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)  # 转换回 OpenCV 格式
    
    """ 绘制眼眶凸包 """
    def drawEye(eye):
        eyeHull = cv2.convexHull(eye)
        cv2.drawContours(frame, [eyeHull], -1, (0, 255, 0))
    
    
    COUNTER = 0     # 闭眼持续次数统计
    detector = dlib.get_frontal_face_detector()     # 构造脸部位置检测器
    # 读取人脸关键点定位模型
    predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
    
    # 打开摄像头或视频
    cap = cv2.VideoCapture(0)
    
    while True:
        ret, frame = cap.read()
        frame = cv2.flip(frame, 1)
    
        faces = detector(frame, 0)  # # 获取人脸
        for face in faces:  # 循环遍历每一个人脸
            shape = predictor(frame, face)     # 获取关键点
            # 将关键点转换为坐标(x, y)的形式
            shape = np.array([[p.x, p.y] for p in shape.parts()])
            rightEye = shape[36:42]     # 右眼,关键点索引从36到41(不包含42)
            leftEye = shape[42:48]      # 左眼,关键点索引从42到47(不包含48)
            rightEAR = eye_aspect_ratio(rightEye)   # 计算右眼纵横比
            leftEAR = eye_aspect_ratio(leftEye)     # 计算左眼纵横比
    
            ear = (rightEAR + leftEAR) / 2.0        # 均值处理
    
            if ear < 0.3:   # 小于0.3认为闭眼,也可能是眨眼(可根据实际调整)
                COUNTER += 1    # 每检测到一次,将+1
                if COUNTER >= 50:   # 持续50帧都闭眼,则警报
                    frame = cv2AddChineseText(frame, "!!!!危险!!!!", (250, 250))
            # 宽高比>0.3,则计数器清零、解除疲劳标志
            else:
                COUNTER = 0
    
            drawEye(leftEye)      # 绘制左跟凸包
            drawEye(rightEye)     # 绘制右眼凸包
            info = "EAR: {:.2f}".format(ear[0][0])
            frame = cv2AddChineseText(frame, info, (0, 30))     # 显示眼睛闭合程度值
    
        cv2.imshow("Frame", frame)
    
        # 检查是否按下ESC键(ASCII码27),如果按下则退出循环
        if cv2.waitKey(10) == 27:
            break
    
    # 释放摄像头资源
    cap.release()
    # 关闭所有OpenCV创建的窗口
    cv2.destroyAllWindows()
    

http://www.kler.cn/news/353661.html

相关文章:

  • Android Gralde 新版aar依赖问题解决
  • 滚雪球学Redis[4.2讲]:Redis Sentinel 深度解析:工作原理、配置与高可用架构下的故障转移
  • 如何打开荣耀手机的调试模式?
  • Vue 3 的不同版本总结
  • 自动化运维的研究与应用
  • Latex
  • 高一全栈开发;国产 Arc 浏览器;Tauri 2.0 发布 | 生活周刊 #3
  • python实现录屏功能
  • 甲方安全和乙方安全的区别
  • Git常用指令【精简版】
  • CodeActAgent :Executable Code Actions Elicit Better LLM Agents解读
  • Meta新模型Dualformer:融合快慢思维,推理能力媲美人脑
  • Mamba学习笔记(2)—序列数据处理基础
  • 顺序表删除相关的算法题|删除最小值|删除值为x的值|删除区间内的值|删除重复的元素(C)
  • Vue3 路由基础 02
  • 爬虫案例——网易新闻数据的爬取
  • 【数据结构】宜宾大学-计院-实验三
  • 【Linux 从基础到进阶】防止数据泄露的策略与工具
  • 前端开发攻略---取消已经发出但是还未响应的网络请求
  • 文心智能体 | AI大师工坊 | 【超省钱小助手】智能体开发经验分享