文章目录

  • 一、项目简介
  • 二、算法原理
  • 三、环境配置
    • 3.1、dlib人脸检测器:dlib.get_frontal_face_detector()
    • 3.2、dlib关键点定位工具:shape_predictor_68_face_landmarks.dat
  • 四、项目实战(加载视频)
  • 五、项目实战(摄像头获取帧图像)

一、项目简介

本项目基于dlib库提供的人脸检测器关键点定位工具以及眼睛纵横比算法完成。通过分析摄像头或视频流中的人脸,实时计算眼睛纵横比EAR(Eye Aspect Ratio),以判断眼睛是否闭合。通过统计眨眼次数,可以检测出眨眼的频率和时长,用于评估用户的注意力水平或疲劳状态。

二、算法原理

论文地址:https://vision.fe.uni-lj.si/cvww2016/proceedings/papers/05.pdf

  • 由于眨眼动作是一个过程,而不是一个帧图像就能瞬间完成。故设置连续帧数的阈值(=3),即连续三帧图像计算得到的EAR值都小于EAR的阈值(=3),则表示眨眼一次。
  • 眨眼检测与疲劳检测的区别就是连续帧数的阈值设置,原理相同!

三、环境配置

dlib库在计算机视觉和人工智能领域有广泛的应用,包括人脸识别、人脸表情分析、人脸关键点检测、物体检测和追踪等任务。它的简单易用性、高性能和丰富的功能使其成为研究人员和开发者的首选库之一。

  • dlib是一个开源的C++机器学习和计算机视觉库,提供了人脸检测、关键点定位、人脸识别等功能,以及支持向量机和其他机器学习算法的实现,具有高性能和跨平台支持。
  • dlib工具的python API下载地址:http://dlib.net/python/
  • dlib库包的介绍与使用:opencv+dlib人脸检测 + 人脸68关键点检测 + 人脸识别 + 人脸特征聚类 + 目标跟踪

3.1、dlib人脸检测器:dlib.get_frontal_face_detector()

dlib官方详细说明:dlib.get_frontal_face_detector()

3.2、dlib关键点定位工具:shape_predictor_68_face_landmarks.dat

dlib官方预训练工具的下载地址:http://dlib.net/files/
(1)5个关键点检测:shape_predictor_5_face_landmarks.dat。五个点分别为:左右眼 + 鼻子 + 左右嘴角
(2)68个关键点检测:shape_predictor_68_face_landmarks.dat

脸部关键点注释详细请看:https://ibug.doc.ic.ac.uk/resources/facial-point-annotations/

四、项目实战(加载视频)

  • 【参数配置】方式一:Pycharm + Terminal + 输入指令自动检测:python detect_blinks.py --shape-predictor shape_predictor_68_face_landmarks.dat --video test.mp4
  • 【参数配置】方式二:Pycharm + 点击Edit Configuration,输入配置参数--shape-predictor shape_predictor_68_face_landmarks.dat --video test.mp4,点击Run开始检测。

# 导入所需库
from scipy.spatial import distance as dist
from collections import OrderedDict
import numpy as np
import argparse
import time
import dlib
import cv2# 定义脸部关键点索引
FACIAL_LANDMARKS_68_IDXS = OrderedDict([("mouth", (48, 68)),("right_eyebrow", (17, 22)),("left_eyebrow", (22, 27)),("right_eye", (36, 42)),("left_eye", (42, 48)),("nose", (27, 36)),("jaw", (0, 17))
])# 计算眼睛纵横比函数
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])# 计算眼睛纵横比EARear = (A + B) / (2.0 * C)return ear# 解析命令行参数
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True, help="面部地标预测器路径")
ap.add_argument("-v", "--video", type=str, default="", help="输入视频文件路径")
args = vars(ap.parse_args())# 设置EAR阈值和连续帧数
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 3# 初始化计数器
COUNTER = 0        # 计算连续帧数3
TOTAL = 0      # 若连续帧数==3,则总眨眼次数+1# 加载面部地标预测器
print("[INFO] 正在加载面部地标预测器...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])# 分别获取左眼和右眼坐标索引
(lStart, lEnd) = FACIAL_LANDMARKS_68_IDXS["left_eye"]
(rStart, rEnd) = FACIAL_LANDMARKS_68_IDXS["right_eye"]# 读取视频
print("[INFO] 开始视频流...")
vs = cv2.VideoCapture(args["video"])
time.sleep(1.0)# 将shape对象转换为numpy数组
def shape_to_np(shape, dtype="int"):# 创建一个dtype类型的空ndarray用于存储68个关键点的坐标coords = np.zeros((shape.num_parts, 2), dtype=dtype)# 遍历每个关键点,提取坐标并存储到ndarray中for i in range(0, shape.num_parts):coords[i] = (shape.part(i).x, shape.part(i).y)return coords# 不断循环处理每一帧图像
while True:# 预处理frame = vs.read()[1]if frame is None:break# 调整图像大小(h, w) = frame.shape[:2]width = 1200       # 脸部大小会影响检测器的识别,太小可能会识别不到r = width / float(w)dim = (width, int(h * r))frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 人脸检测rects = detector(gray, 0)# 遍历检测到的每个人脸for rect in rects:# 获取关键点坐标shape = predictor(gray, rect)shape = shape_to_np(shape)# 提取左眼和右眼区域坐标leftEye = shape[lStart:lEnd]rightEye = shape[rStart:rEnd]# 计算左右眼纵横比EARleftEAR = eye_aspect_ratio(leftEye)rightEAR = eye_aspect_ratio(rightEye)# 计算平均纵横比ear = (leftEAR + rightEAR) / 2.0# 绘制眼睛区域轮廓(凸包)leftEyeHull = cv2.convexHull(leftEye)rightEyeHull = cv2.convexHull(rightEye)cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)# 检查是否满足EAR阈值if ear < EYE_AR_THRESH:COUNTER += 1else:# 如果连续几帧都是闭眼的,增加总数if COUNTER >= EYE_AR_CONSEC_FRAMES:TOTAL += 1# 重置计数器COUNTER = 0# 在图像中,显示眨眼次数和纵横比cv2.putText(frame, "Blinks: {}".format(TOTAL), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)# 显示当前帧图像cv2.imshow("Frame", frame)key = cv2.waitKey(10) & 0xFF# 按下Esc键退出循环if key == 27:breakvs.release()              # 释放视频流
cv2.destroyAllWindows()     # 关闭所有窗口

五、项目实战(摄像头获取帧图像)

  • 【参数配置】方式一:Pycharm + Terminal + 输入指令自动检测:python detect_blinks.py --shape-predictor shape_predictor_68_face_landmarks.dat
  • 【参数配置】方式二:Pycharm + 点击Edit Configuration,输入配置参数--shape-predictor shape_predictor_68_face_landmarks.dat,点击Run开始检测。
# 导入所需库
from scipy.spatial import distance as dist
from collections import OrderedDict
import numpy as np
import argparse
import time
import dlib
import cv2# 定义脸部关键点索引
FACIAL_LANDMARKS_68_IDXS = OrderedDict([("mouth", (48, 68)),("right_eyebrow", (17, 22)),("left_eyebrow", (22, 27)),("right_eye", (36, 42)),("left_eye", (42, 48)),("nose", (27, 36)),("jaw", (0, 17))
])# 计算眼睛纵横比函数
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])# 计算眼睛纵横比EARear = (A + B) / (2.0 * C)return ear# 解析命令行参数
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True, help="面部地标预测器路径")
args = vars(ap.parse_args())# 设置EAR阈值和连续帧数
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 3# 初始化计数器
COUNTER = 0    # 计算连续帧数3
TOTAL = 0    # 若连续帧数==3,则总眨眼次数+1# 加载面部地标预测器
print("[INFO] 正在加载面部地标预测器...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])# 分别获取左眼和右眼坐标索引
(lStart, lEnd) = FACIAL_LANDMARKS_68_IDXS["left_eye"]
(rStart, rEnd) = FACIAL_LANDMARKS_68_IDXS["right_eye"]# 读取视频
print("[INFO] 开始视频流...")
vs = cv2.VideoCapture(0)
time.sleep(1.0)# 将shape对象转换为numpy数组
def shape_to_np(shape, dtype="int"):# 创建一个dtype类型的空ndarray用于存储68个关键点的坐标coords = np.zeros((shape.num_parts, 2), dtype=dtype)# 遍历每个关键点,提取坐标并存储到ndarray中for i in range(0, shape.num_parts):coords[i] = (shape.part(i).x, shape.part(i).y)return coords# 不断循环处理每一帧图像
while True:# 预处理ret, frame = vs.read()if not ret:break# 调整图像大小(h, w) = frame.shape[:2]width = 1200    # 脸部大小会影响检测器的识别,太小可能会识别不到r = width / float(w)dim = (width, int(h * r))frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 人脸检测rects = detector(gray, 0)# 遍历检测到的每个人脸for rect in rects:# 获取关键点坐标shape = predictor(gray, rect)shape = shape_to_np(shape)# 提取左眼和右眼区域坐标leftEye = shape[lStart:lEnd]rightEye = shape[rStart:rEnd]# 计算左右眼纵横比EARleftEAR = eye_aspect_ratio(leftEye)rightEAR = eye_aspect_ratio(rightEye)# 计算平均纵横比ear = (leftEAR + rightEAR) / 2.0# 绘制眼睛区域轮廓(凸包)leftEyeHull = cv2.convexHull(leftEye)rightEyeHull = cv2.convexHull(rightEye)cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)# 检查是否满足EAR阈值if ear < EYE_AR_THRESH:COUNTER += 1else:# 如果连续几帧都是闭眼的,增加总数if COUNTER >= EYE_AR_CONSEC_FRAMES:TOTAL += 1# 重置计数器COUNTER = 0# 在图像中,显示眨眼次数和纵横比cv2.putText(frame, "Blinks: {}".format(TOTAL), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)# 显示当前帧图像cv2.imshow("Frame", frame)key = cv2.waitKey(1) & 0xFF# 按下Esc键退出循环if key == 27:breakvs.release()             # 释放视频流
cv2.destroyAllWindows()     # 关闭所有窗口

Opencv项目实战:基于dlib的疲劳检测相关推荐

  1. 基于Dlib的疲劳检测系统

    需要源码的朋友可以私信我 基于Dlib的疲劳检测系统 1.设计背景及要求 2.系统分析 3.系统设计 3.1功能结构图 3.2基于EAR.MAR和HPE算法的疲劳检测 3.2.1基于EAR算法的眨眼检 ...

  2. 12月28日 OpenCV 实战基础学习笔记——疲劳检测

    文章目录 前言 一.眨眼疲劳检测 前言 本文为12月28日 OpenCV 实战基础学习笔记--疲劳检测. 一.眨眼疲劳检测 from scipy.spatial import distance as ...

  3. 基于C++的OpenCV项目实战——文档照片转换成扫描文件

    基于C++的OpenCV项目实战--文档照片转换成扫描文件 一.背景 前段时间都是基于Python的OpecCV进行一些学习和实践,但小的知识点并没有应用到实际的项目中:并且基于Python的版本的移 ...

  4. 【Opencv项目实战】背景替换:动态背景移除与替换(cvzone+MediaPipe)

    文章目录 一.项目思路 二.环境布置 2.1.cvzone安装 2.2.MediaPipe安装 2.3.常见问题 2.4.注意事项 三.算法详解 3.1.segmentor.removeBG():去除 ...

  5. 项目实战——基于计算机视觉的物体位姿定位及机械臂抓取(单目标定)

    项目实战--基于计算机视觉的物体位姿定位及机械臂抓取(单目标定) 请各位读者朋友注意,这里面很多东西涉及到我的毕设,写作辛苦,请勿滥用,转载请务必注明出处!         单目标定主要分为两个部分, ...

  6. Opencv项目实战-信用卡数字识别

    Opencv项目实战:信用卡数字识别 导入库,定义展示函数 import cv2 import numpy as np from imutils import contours import myut ...

  7. Arduino项目实战——基于Arduino【智能垃圾桶】设计

       Arduino项目实战        -基于Arduino[智能垃圾桶]设计 第一次接触Arduino是在大一的时候,距离现在已经五年,当时一个简单的"电子琴"项目就让我抓耳 ...

  8. 项目:基于yolov5的舰船检测+pycharm+机器学习+图像检测

    项目:基于yolov5的舰船检测+pycharm+机器学习+图像检测 项目将深度学习的方法引入海洋目标的检测,利用深度神经网络模型强大的学习能力和模型通用性,来实现准确.可靠和快速的目标自动检测和识别 ...

  9. 自动化运维-----项目实战: 基于Ansible的云平台自动化运维系统

    文章目录 项目实战: 基于Ansible的云平台自动化运维系统 一.项目介绍 1.项目介绍 2.项目背景 二.项目环境搭建 1.项目目录的配置 2.远程服务器虚拟环境的配置 3.MySQL数据库配置 ...

最新文章

  1. Pycharm 和 vscode 多光标、折叠代码和代码格式化快捷键
  2. elasticSearch6源码分析(4)indices模块
  3. 哆啦A梦消除连连看游戏源码项目完整版
  4. idea yml文件不变成树叶_springboot获取配置文件的三种方式
  5. 1078 字符串压缩与解压 (20 分)
  6. HDU4911 Inversion 解题报告
  7. dubbo-admin管理平台搭建
  8. MaxCompute规格详解 让您花更低的成本获得更高的业务价值
  9. Linux下安装flash player插件
  10. Adobe软件注册机
  11. Spring Environment全解析
  12. [爬虫]一个关于课堂派课件的爬虫
  13. 裸眼3d项目,数字平原是这样制作的
  14. 论文阅读笔记《REDE: End-to-End Object 6D Pose Robust Estimation Using Differentiable Outliers Elimination》
  15. 利用CSS让dl dt dd呈现多行多列效果
  16. es备份之snapshot SLM策略cron详解
  17. 外汇投资策略——超短线策略
  18. 带plx芯片的服务器主板,主板上面都有啥?常见板载芯片功能介绍(三)
  19. springcloud在 repository层通过sql语句实现查询功能
  20. 【技术贴】火狐QQ空间音乐插件下载+火狐进空间没背景音乐崩溃解决+火狐浏览器插件推荐...

热门文章

  1. 网络安全 kali Web安全之CSRF攻击
  2. 数据仓库分层的原因多维数据模型元数据技术
  3. 对数据隐私性的担忧,谁来解决?
  4. NOJ 练习题5,6季
  5. python基础实验报告-Python语言接收信息的内置函数是________________。
  6. 2019年中国游戏市场
  7. 破解xftp和xshell
  8. 蓝牙血压计的android实现思路,基于蓝牙4.0的示波法电子血压计的设计与实现
  9. MSP430F5529 (六)定时器Timer_A
  10. CentOS 查看主机地址