OpenCV从入门到精通实战(九)——基于dlib的疲劳监测 ear计算

2024-04-18 06:04

本文主要是介绍OpenCV从入门到精通实战(九)——基于dlib的疲劳监测 ear计算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文实现Python库d和OpenCV来实现眼部闭合检测,主要用于评估用户是否眨眼。

步骤一:导入必要的库和设置参数

首先,代码导入了必要的Python库,如dlib、OpenCV和scipy。通过argparse设置了输入视频和面部标记预测器的参数。

from scipy.spatial import distance as dist
from collections import OrderedDict
import numpy as np
import argparse
import time
import dlib
import cv2

步骤二:定义面部关键点索引

使用OrderedDict定义了包含68个点的面部关键点,用于眼部分析。

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))
])

步骤三:定义眼部闭合比率(EAR)函数

此函数计算眼部的纵横比,用于判断眼睛是否闭合。

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

步骤四:读取视频并初始化检测器

加载面部检测器和预测器,读取视频流。

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])
vs = cv2.VideoCapture(args["video"])

步骤五:遍历视频帧,检测和分析

对视频的每一帧进行处理,检测人脸,提取眼部关键点,并计算EAR。

while True:frame = vs.read()[1]gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)rects = detector(gray, 0)

步骤六:闭眼检测逻辑

分析EAR值,累计闭眼帧数,并计算总的眨眼次数。

if ear < EYE_AR_THRESH:COUNTER += 1
else:if COUNTER >= EYE_AR_CONSEC_FRAMES:TOTAL += 1COUNTER = 0

步骤七:显示结果

在视频帧上显示眨眼次数和当前EAR值,同时绘制眼部区域。

cv2.putText(frame, "Blinks: {}".format(TOTAL), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)

完整代码

#导入工具包
from scipy.spatial import distance as dist
from collections import OrderedDict
import numpy as np
import argparse
import time
import dlib
import cv2FACIAL_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))
])# http://vision.fe.uni-lj.si/cvww2016/proceedings/papers/05.pdf
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值ear = (A + B) / (2.0 * C)return ear# 输入参数
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor",default="shape_predictor_68_face_landmarks.dat",help="path to facial landmark predictor")
ap.add_argument("-v", "--video", type=str, default="test.mp4",help="path to input video file")
args = vars(ap.parse_args())# 设置判断参数
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 3# 初始化计数器
COUNTER = 0
TOTAL = 0# 检测与定位工具
print("[INFO] loading facial landmark predictor...")
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] starting video stream thread...")
vs = cv2.VideoCapture(args["video"])
#vs = FileVideoStream(args["video"]).start()
time.sleep(1.0)def shape_to_np(shape, dtype="int"):# 创建68*2coords = np.zeros((shape.num_parts, 2), dtype=dtype)# 遍历每一个关键点# 得到坐标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=1200r = 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)# 分别计算ear值leftEye = shape[lStart:lEnd]rightEye = shape[rStart:rEnd]leftEAR = 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)# 检查是否满足阈值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) & 0xFFif key == 27:breakvs.release()
cv2.destroyAllWindows()

在这里插入图片描述

这篇关于OpenCV从入门到精通实战(九)——基于dlib的疲劳监测 ear计算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/913946

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

电力系统中的A类在线监测装置—APView400

随着电力系统的日益复杂和人们对电能质量要求的提高,电能质量在线监测装置在电力系统中得到广泛应用。目前,市场上的在线监测装置主要分为A类和B类两种类型,A类和B类在线监测装置主要区别在于应用场景、技术参数、通讯协议和扩展性。选择时应根据实际需求和应用场景综合考虑,并定期维护和校准。电能质量在线监测装置是用于实时监测电力系统中的电能质量参数的设备。 APView400电能质量A类在线监测装置以其多核

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc