Opencv项目实战:基于dlib的疲劳检测
文章目录
- 一、项目简介
- 二、算法原理
- 三、环境配置
- 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的疲劳检测相关推荐
- 基于Dlib的疲劳检测系统
需要源码的朋友可以私信我 基于Dlib的疲劳检测系统 1.设计背景及要求 2.系统分析 3.系统设计 3.1功能结构图 3.2基于EAR.MAR和HPE算法的疲劳检测 3.2.1基于EAR算法的眨眼检 ...
- 12月28日 OpenCV 实战基础学习笔记——疲劳检测
文章目录 前言 一.眨眼疲劳检测 前言 本文为12月28日 OpenCV 实战基础学习笔记--疲劳检测. 一.眨眼疲劳检测 from scipy.spatial import distance as ...
- 基于C++的OpenCV项目实战——文档照片转换成扫描文件
基于C++的OpenCV项目实战--文档照片转换成扫描文件 一.背景 前段时间都是基于Python的OpecCV进行一些学习和实践,但小的知识点并没有应用到实际的项目中:并且基于Python的版本的移 ...
- 【Opencv项目实战】背景替换:动态背景移除与替换(cvzone+MediaPipe)
文章目录 一.项目思路 二.环境布置 2.1.cvzone安装 2.2.MediaPipe安装 2.3.常见问题 2.4.注意事项 三.算法详解 3.1.segmentor.removeBG():去除 ...
- 项目实战——基于计算机视觉的物体位姿定位及机械臂抓取(单目标定)
项目实战--基于计算机视觉的物体位姿定位及机械臂抓取(单目标定) 请各位读者朋友注意,这里面很多东西涉及到我的毕设,写作辛苦,请勿滥用,转载请务必注明出处! 单目标定主要分为两个部分, ...
- Opencv项目实战-信用卡数字识别
Opencv项目实战:信用卡数字识别 导入库,定义展示函数 import cv2 import numpy as np from imutils import contours import myut ...
- Arduino项目实战——基于Arduino【智能垃圾桶】设计
Arduino项目实战 -基于Arduino[智能垃圾桶]设计 第一次接触Arduino是在大一的时候,距离现在已经五年,当时一个简单的"电子琴"项目就让我抓耳 ...
- 项目:基于yolov5的舰船检测+pycharm+机器学习+图像检测
项目:基于yolov5的舰船检测+pycharm+机器学习+图像检测 项目将深度学习的方法引入海洋目标的检测,利用深度神经网络模型强大的学习能力和模型通用性,来实现准确.可靠和快速的目标自动检测和识别 ...
- 自动化运维-----项目实战: 基于Ansible的云平台自动化运维系统
文章目录 项目实战: 基于Ansible的云平台自动化运维系统 一.项目介绍 1.项目介绍 2.项目背景 二.项目环境搭建 1.项目目录的配置 2.远程服务器虚拟环境的配置 3.MySQL数据库配置 ...
最新文章
- Pycharm 和 vscode 多光标、折叠代码和代码格式化快捷键
- elasticSearch6源码分析(4)indices模块
- 哆啦A梦消除连连看游戏源码项目完整版
- idea yml文件不变成树叶_springboot获取配置文件的三种方式
- 1078 字符串压缩与解压 (20 分)
- HDU4911 Inversion 解题报告
- dubbo-admin管理平台搭建
- MaxCompute规格详解 让您花更低的成本获得更高的业务价值
- Linux下安装flash player插件
- Adobe软件注册机
- Spring Environment全解析
- [爬虫]一个关于课堂派课件的爬虫
- 裸眼3d项目,数字平原是这样制作的
- 论文阅读笔记《REDE: End-to-End Object 6D Pose Robust Estimation Using Differentiable Outliers Elimination》
- 利用CSS让dl dt dd呈现多行多列效果
- es备份之snapshot SLM策略cron详解
- 外汇投资策略——超短线策略
- 带plx芯片的服务器主板,主板上面都有啥?常见板载芯片功能介绍(三)
- springcloud在 repository层通过sql语句实现查询功能
- 【技术贴】火狐QQ空间音乐插件下载+火狐进空间没背景音乐崩溃解决+火狐浏览器插件推荐...
热门文章
- 网络安全 kali Web安全之CSRF攻击
- 数据仓库分层的原因多维数据模型元数据技术
- 对数据隐私性的担忧,谁来解决?
- NOJ 练习题5,6季
- python基础实验报告-Python语言接收信息的内置函数是________________。
- 2019年中国游戏市场
- 破解xftp和xshell
- 蓝牙血压计的android实现思路,基于蓝牙4.0的示波法电子血压计的设计与实现
- MSP430F5529 (六)定时器Timer_A
- CentOS 查看主机地址