人脸68关键点与K210疲劳检测
目录
人脸68关键点检测
检测闭眼睁眼
双眼关键点检测
计算眼睛的闭合程度:
原理:
设置阈值进行判断
实时监测和更新
拓展:通过判断上下眼皮重合程度去判断是否闭眼
检测嘴巴是否闭合
提取嘴唇上下轮廓的关键点
计算嘴唇上下轮廓关键点之间的距离
计算嘴角到上嘴唇中心的距离
计算嘴角到下嘴唇中心的距离
将两个距离相加作为嘴唇的闭合程度指标
判断嘴巴是否闭合
K210疲劳检测
前两天在做项目的时候,想通过偷懒的方式去试试,不用目标检测去检测疲劳,而是通过人脸检测的68关键点去通过检测睁眼闭眼和张嘴闭嘴去检测闭眼和打瞌睡。那让我们来试试吧。
人脸68关键点检测
人脸68关键点检测是一种计算机视觉技术,旨在识别和定位人脸图像中的关键点。这些关键点通常包括眼睛、鼻子、嘴巴等面部特征的位置。通过检测这些关键点,可以实现人脸识别、表情识别、姿势估计等
主要的步骤:
- 检测人脸:首先需要使用人脸检测算法确定图像中人脸的位置。
- 提取关键点:在检测到的人脸区域内,使用特定的算法来识别和标记关键点的位置。
- 分类关键点:将检测到的关键点分为不同的类别,如眼睛、鼻子、嘴巴等。

检测闭眼睁眼
双眼关键点检测
在68个关键点中,一般左眼和右眼的位置会分别由多个关键点表示。这些关键点的坐标通常以 (x, y) 形式给出,其中 x 表示水平方向的位置,y 表示垂直方向的位置。
import cv2
# 加载人脸关键点检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
# 读取图像
img = cv2.imread('face_image.jpg')
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 检测人脸
faces = detector(gray)
for face in faces:# 获取关键点landmarks = predictor(gray, face)for n in range(37, 48): # 提取左眼和右眼的关键点x = landmarks.part(n).xy = landmarks.part(n).ycv2.circle(img, (x, y), 2, (0, 255, 0), -1) # 在关键点处画圆
计算眼睛的闭合程度:
原理:
通过计算眼睛关键点的纵向位置(Y 坐标)的差值,并加权求和来反映眼睛的状态。
对于每只眼睛,首先计算关键点的纵向位置(Y 坐标)的差值。可以选择一些具有代表性的关键点来进行计算,比如眼睛的上下眼睑或者眼角等位置点。 对这些差值进行加权求和,可以根据不同的应用场景进行加权,比如可以将靠近眼睛中心的关键点的差值赋予更高的权重,因为这些部位更能反映眼睛的状态。
眼睛闭合程度计算公式:
- 首先,选择上眼睑和下眼睑的关键点,分别计算它们的平均纵向位置(Y 坐标)。
- 然后,通过上眼睑平均位置减去下眼睑平均位置,得到一个值表示眼睛的闭合程度。这个值越小,表示眼睛越闭合\
[ \text{闭合程度} = \text{上眼睑平均位置} - \text{下眼睑平均位置} ]
其中,上眼睑平均位置和下眼睑平均位置分别表示对应关键点的纵向位置的平均值。
# 计算眼睛的闭合程度
def eye_closure_ratio(eye_landmarks):# 假设我们选取了上眼睑关键点的索引为[1, 2, 3],下眼睑关键点的索引为[4, 5, 6]upper_lid_points = eye_landmarks[1:4]lower_lid_points = eye_landmarks[4:7]# 计算上下眼睑的平均纵向位置upper_lid_y_mean = sum([point[1] for point in upper_lid_points]) / len(upper_lid_points)lower_lid_y_mean = sum([point[1] for point in lower_lid_points]) / len(lower_lid_points)# 计算纵向位置的差值,这里可以根据具体情况加权求和diff = upper_lid_y_mean - lower_lid_y_meanreturn diff
设置阈值进行判断
根据实际情况,可以设置一个阈值来判断眼睛是否闭合。当加权求和的结果小于阈值时,可以认为眼睛是闭合的;反之则是睁开的。
# 判断眼睛是否闭合
def is_eye_closed(eye_landmarks, threshold):closure_ratio = eye_closure_ratio(eye_landmarks)if closure_ratio < threshold:return True # 眼睛闭合else:return False # 眼睛睁开
实时监测和更新
在实时监测过程中,不断更新眼睛关键点的位置信息,并重新计算眼睛的闭合程度,以实现对眼睛状态的准确监测。
# 循环实时监测
while True:ret, frame = cap.read() # 从摄像头读取画面gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = detector(gray)for face in faces:landmarks = predictor(gray, face)left_eye_landmarks = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(36, 42)] # 左眼关键点right_eye_landmarks = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(42, 48)] # 右眼关键点# 计算左眼闭合程度并判断left_eye_closed = is_eye_closed(left_eye_landmarks, 5) # 假设阈值设为5# 计算右眼闭合程度并判断right_eye_closed = is_eye_closed(right_eye_landmarks, 5) # 假设阈值设为5# 综合判断眼睛状态if left_eye_closed and right_eye_closed:print("Both eyes closed")elif left_eye_closed:print("Left eye closed")elif right_eye_closed:print("Right eye closed")else:print("Eyes open")
拓展:通过判断上下眼皮重合程度去判断是否闭眼
通过判断上下眼皮的重合程度来间接判断眼睛是否闭合。当眼睛闭合时,上下眼皮会有一定程度的重合,而睁开时则不会存在明显的重合。
具体实现方法可以是计算上下眼睑之间的垂直距离,并将其与总眼睛高度的比值作为闭合程度的度量指标。当这个比值超过一定阈值时,可以判断为闭眼状态
# 计算上下眼皮重合程度
def eyelid_overlap_ratio(eye_landmarks):# 假设我们选取了上眼睑关键点的索引为[1, 2, 3],下眼睑关键点的索引为[4, 5, 6]upper_lid_points = eye_landmarks[1:4]lower_lid_points = eye_landmarks[4:7]# 计算上下眼睑之间的垂直距离vertical_distance = lower_lid_points[0][1] - upper_lid_points[-1][1]# 计算垂直距离与总眼睛高度的比值eye_height = max(eye_landmarks, key=lambda x: x[1])[1] - min(eye_landmarks, key=lambda x: x[1])[1]overlap_ratio = vertical_distance / eye_heightreturn overlap_ratio
检测嘴巴是否闭合
提取嘴唇上下轮廓的关键点
根据人脸关键点的位置信息,提取出嘴唇上下轮廓的关键点。一般而言,嘴唇上下轮廓的关键点包括嘴角、上嘴唇中心、下嘴唇中心等关键点。
计算嘴唇上下轮廓关键点之间的距离
选择合适的距离度量方法(如欧氏距离)计算嘴唇上下轮廓关键点之间的距离。具体来说,可以计算嘴角到上嘴唇中心和嘴角到下嘴唇中心的距离,并将这两个距离相加作为嘴唇的闭合程度指标。
计算嘴角到上嘴唇中心的距离
使用欧氏距离公式计算嘴角到上嘴唇中心的距离: [ distance_top = \sqrt{(x_{top} - x_{corner})^2 + (y_{top} - y_{corner})^2} ] 其中 (x_{top}) 和 (y_{top}) 分别是上嘴唇中心的 x、y 坐标,(x_{corner}) 和 (y_{corner}) 分别是嘴角的 x、y 坐标。
计算嘴角到下嘴唇中心的距离
同样使用欧氏距离公式计算嘴角到下嘴唇中心的距离: [ distance_bottom = \sqrt{(x_{bottom} - x_{corner})^2 + (y_{bottom} - y_{corner})^2} ] 其中 (x_{bottom}) 和 (y_{bottom}) 分别是下嘴唇中心的 x、y 坐标。
将两个距离相加作为嘴唇的闭合程度指标
将嘴角到上嘴唇中心的距离 (distance_top) 和嘴角到下嘴唇中心的距离 (distance_bottom) 相加,得到嘴唇的闭合程度指标: [ distance_total = distance_top + distance_bottom ]
判断嘴巴是否闭合
设定一个阈值,根据嘴唇上下轮廓关键点之间的距禀与该阈值的比较结果来判断嘴巴是否闭合。通常情况下,当嘴唇闭合时,嘴唇上下轮廓的关键点之间的距离会比较小;而当嘴巴张开时,这个距离会增大。
import math
# 计算欧氏距离
def euclidean_distance(point1, point2):return math.sqrt((point2[0] - point1[0])**2 + (point2[1] - point1[1])**2)
# 提取嘴唇上下轮廓的关键点索引(假设为索引0到11)
mouth_landmarks = face_landmarks[0:12] # 假设face_landmarks包含了所有68个关键点的坐标
# 计算嘴唇上下轮廓关键点之间的距离
lip_distances = []
for i in range(len(mouth_landmarks)//2):distance = euclidean_distance(mouth_landmarks[i], mouth_landmarks[i + len(mouth_landmarks)//2])lip_distances.append(distance)
# 计算平均距离
avg_distance = sum(lip_distances) / len(lip_distances)
# 设定阈值
threshold = 5.0
# 判断嘴巴是否闭合
if avg_distance < threshold:print("嘴巴闭合")
else:print("嘴巴张开")
K210疲劳检测
项目的来源:对K210人脸检测68关键点的一种拓展
如何通过人脸检测68关键点去检测疲劳情况
代码是根据K210的例程改的,也只是使用上下眼皮的距离和上下嘴唇的距离来检测疲劳状态
import sensor, image, time, lcd
from maix import KPU
import gclcd.init()
sensor.reset()sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(True) # 摄像头后置sensor.skip_frames(time=500)
clock = time.clock()od_img = image.Image(size=(320, 256), copy_to_fb=False)# 构建KPU对象
# 需要导入2个模型,分别是人脸检测模型和68关键点检测模型
anchor = (0.893, 1.463, 0.245, 0.389, 1.55, 2.58, 0.375, 0.594, 3.099, 5.038, 0.057, 0.090, 0.567, 0.904, 0.101, 0.160, 0.159, 0.255)
kpu_face_detect = KPU()
print("Loading face detection model")
kpu_face_detect.load_kmodel("/sd/face_detect.kmodel")
kpu_face_detect.init_yolo2(anchor, anchor_num=9, img_w=320, img_h=240, net_w=320, net_h=256, layer_w=10, layer_h=8, threshold=0.7, nms_value=0.2, classes=1)kpu_lm68 = KPU()
print("Loading landmark 68 model")
kpu_lm68.load_kmodel("/sd/landmark68.kmodel")RATIO = 0.08while True:gc.collect()clock.tick() # Update the FPS clock.img = sensor.snapshot()od_img.draw_image(img, 0, 0)od_img.pix_to_ai()kpu_face_detect.run_with_output(od_img)detections = kpu_face_detect.regionlayer_yolo2()fps = clock.fps()if len(detections) > 0:for det in detections:x1_t = max(int(det[0] - RATIO * det[2]), 0)x2_t = min(int(det[0] + det[2] + RATIO * det[2]), 319)y1_t = max(int(det[1] - RATIO * det[3]), 0)y2_t = min(int(det[1] + det[3] + RATIO * det[3]), 255)cut_img_w = x2_t - x1_t + 1cut_img_h = y2_t - y1_t + 1face_cut = img.cut(x1_t, y1_t, cut_img_w, cut_img_h)face_cut_128 = face_cut.resize(128, 128)face_cut_128.pix_to_ai()out = kpu_lm68.run_with_output(face_cut_128, getlist=True)if out is not None:left_eye_height = out[41][1] - out[37][1]right_eye_height = out[47][1] - out[43][1]eye_height_avg = (left_eye_height + right_eye_height) / 2mouth_height = out[66][1] - out[62][1]if eye_height_avg < 10 and mouth_height > 15:print("Tired: Eyes closed, Mouth open")elif eye_height_avg < 10:print("Tired: Eyes closed")elif mouth_height > 15:print("Tired: Mouth open")del face_cut_128del face_cutimg.draw_string(0, 0, "%2.1f fps" % fps, color=(0, 60, 255), scale=2.0)lcd.display(img)gc.collect()kpu_face_detect.deinit()
kpu_lm68.deinit()
相关文章:
人脸68关键点与K210疲劳检测
目录 人脸68关键点检测 检测闭眼睁眼 双眼关键点检测 计算眼睛的闭合程度: 原理: 设置阈值进行判断 实时监测和更新 拓展:通过判断上下眼皮重合程度去判断是否闭眼 检测嘴巴是否闭合 提取嘴唇上下轮廓的关键点 计算嘴唇上下轮廓关键点之间的距…...
【跟着GPT4学JAVA】异常篇
JAVA异常中的知识点 问: 介绍下JAVA中的异常有哪些知识点吧 答: Java中的异常处理是一个重要的知识点,主要包括以下内容: 异常体系:Java的异常类是Throwable类派生出来的,Throwable下有两个重要的子类:Err…...
Ubuntu上安装d4rl数据集
Ubuntu上安装d4rl数据集 D4RL的官方 github: https://github.com/Farama-Foundation/D4RL 一、安装Mujoco 1.1 官网下载mujoco210文件 如果装过可以跳过这步 链接:https://github.com/deepmind/mujoco/releases/tag/2.1.0 下载第一个文件即可。我这里是在windo…...
C++之STL整理(4)之set 用法(创建、赋值、增删查改)详解
C之STL整理(4)之set 用法(创建、赋值、增删查改)详解 注:整理一些突然学到的C知识,随时mark一下 例如:忘记的关键字用法,新关键字,新数据结构 C 的map用法整理 C之STL整理…...
IDEA MyBatisCodeHelper Pro最新版(持续更新)
目录 0. 你想要的0.1 包下载0.2 使用jh 1. 功能介绍2. 下载安装2.1 在idea中插件市场安装2.2 在jetbrains插件市场下载安装 3. 简单使用3.1 创建一个SpringBoot项目3.2 配置数据库3.3 一键生成实体类、mapper 0. 你想要的 0.1 包下载 测试系统:Windows(…...
sheng的学习笔记-AI-YOLO算法,目标检测
AI目录:sheng的学习笔记-AI目录-CSDN博客 目录 目标定位(Object localization) 定义 原理图 具体做法: 输出向量 图片中没有检测对象的样例 损失函数 编辑 特征点检测(Landmark detection) 定义&a…...
C# wpf 嵌入wpf控件
WPF Hwnd窗口互操作系列 第一章 嵌入Hwnd窗口 第二章 嵌入WinForm控件 第三章 嵌入WPF控件(本章) 第四章 底部嵌入HwndHost 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现?1、继承HwndHost2、添加Content属性3、创建wpf窗口并设置Conten…...
云原生(六)、CICD - Jenkins快速入门
Jenkuns快速入门 一、CICD概述 CICD是持续集成(Continuous Integration)和持续部署(Continuous Deployment)的缩写。它是软件开发中的一种流程和方法论,旨在通过自动化的方式频繁地将代码集成到共享存储库中…...
基于java+springboot+vue实现的付费自习室管理系统(文末源码+Lw+ppt)23-400
摘 要 付费自习室管理系统采用B/S架构,数据库是MySQL。网站的搭建与开发采用了先进的java进行编写,使用了springboot框架。该系统从两个对象:由管理员和用户来对系统进行设计构建。主要功能包括:个人信息修改,对用户…...
【JavaParser笔记02】JavaParser解析Java源代码中的类字段信息(javadoc注释、字段名称)
这篇文章,主要介绍如何使用JavaParser解析Java源代码中的类字段信息(javadoc注释、字段名称)。 目录 一、JavaParser依赖库 1.1、引入依赖 1.2、获取类成员信息 (1)案例代码 <...
Spring IoCDI(3)
DI详解 接下来学习一下依赖注入DI的细节. 依赖注入是一个过程, 是指IoC容器在创建Bean时, 去提供运行时所依赖的资源, 而资源指的就是对象. 在之前的案例中, 使用了Autowired这个注解, 完成了依赖注入这个操作. 简单来说, 就是把对象取出来放到某个类的属性中. 在一些文章中…...
保研线性代数机器学习基础复习1
1.什么是代数(algebra)? 为了形式化一个概念,构建出有关这个概念的符号以及操作符号的公式。 2.什么是线性代数(linear algebra)? 一项关于向量以及操作向量的公式的研究。 3.举一些向量的例子&#x…...
js绑定事件的方法
在JavaScript中,绑定事件的方法主要有以下几种: HTML属性方式:直接在HTML元素中使用事件属性来绑定事件。 html<button onclick"alert(Hello World!)">Click Me</button> DOM属性方式:通过JavaScript代码…...
是德科技keysight N9000B 信号分析仪
181/2461/8938产品概述: 工程的内涵就是将各种创意有机地联系起来,并解决遇到的问题。 CXA 信号分析仪具有出色的实际性能,它是一款出类拔萃、经济高效的基本信号表征工具。 它的功能十分强大,为一般用途和教育行业的用户执行测试…...
软考 - 系统架构设计师 - 架构风格
软件架构风格是指描述特定软件系统组织方式的惯用模式。组织方式描述了系统的组成构件,以及这些构件的组织方式,惯用模式指众多系统所共有的结构和语义。 目录 架构风格 数据流风格 批处理架构风格 管道 - 过滤器架构风格 调用 / 返回风格 主程序…...
CleanMyMac X2024专业免费的国产Mac笔记本清理软件
非常高兴有机会向大家介绍CleanMyMac X 2024这款专业的Mac清理软件。它以其强大的清理能力、系统优化效果、出色的用户体验以及高度的安全性,在Mac清理软件市场中独树一帜。 CleanMyMac X2024全新版下载如下: https://wm.makeding.com/iclk/?zoneid49983 一、主要…...
ES6 模块化操作
ES6模块化主要有两个操作:import 和 export 如果在html文件的script中引用模块的话,要设置<script type"module"> 一种导入导出方法: a.js//分别暴露 export let num 1 export function compute(a, b){return a b }//统…...
统计XML文件内标签的种类和其数量及将xml格式转换为yolov5所需的txt格式
1、统计XML文件内标签的种类和其数量 对于自己标注的数据集,需在标注完成后需要对标注好的XML文件校验,下面是代码,只需将SrcDir换成需要统计的xml的文件夹即可。 import os from tqdm import tqdm import xml.dom.minidomdef ReadXml(File…...
《操作系统导论》第14章读书笔记:插叙:内存操作API
《操作系统导论》第14章读书笔记:插叙:内存操作API —— 杭州 2024-03-30 夜 文章目录 《操作系统导论》第14章读书笔记:插叙:内存操作API1.内存类型1.1.栈内存:它的申请和释放操作是编译器来隐式管理的,所…...
HAProxy + Vitess负载均衡
一、环境搭建 Vitess环境搭建: 具体vitess安装不再赘述,主要是需要启动3个vtgate(官方推荐vtgate和vtablet数量一致) 操作: 在vitess/examples/common/scripts目录中,修改vtgate-up.sh文件,…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...
