人脸68关键点与K210疲劳检测

目录

人脸68关键点检测

检测闭眼睁眼

双眼关键点检测

计算眼睛的闭合程度:

原理:

设置阈值进行判断

实时监测和更新

拓展:通过判断上下眼皮重合程度去判断是否闭眼

检测嘴巴是否闭合

提取嘴唇上下轮廓的关键点

计算嘴唇上下轮廓关键点之间的距离

计算嘴角到上嘴唇中心的距离

计算嘴角到下嘴唇中心的距离

将两个距离相加作为嘴唇的闭合程度指标

判断嘴巴是否闭合

K210疲劳检测


前两天在做项目的时候,想通过偷懒的方式去试试,不用目标检测去检测疲劳,而是通过人脸检测的68关键点去通过检测睁眼闭眼和张嘴闭嘴去检测闭眼和打瞌睡。那让我们来试试吧。

人脸68关键点检测

人脸68关键点检测是一种计算机视觉技术,旨在识别和定位人脸图像中的关键点。这些关键点通常包括眼睛、鼻子、嘴巴等面部特征的位置。通过检测这些关键点,可以实现人脸识别、表情识别、姿势估计等

主要的步骤:

  1. 检测人脸:首先需要使用人脸检测算法确定图像中人脸的位置。
  2. 提取关键点:在检测到的人脸区域内,使用特定的算法来识别和标记关键点的位置。
  3. 分类关键点:将检测到的关键点分为不同的类别,如眼睛、鼻子、嘴巴等。

检测闭眼睁眼

双眼关键点检测

在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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/775064.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

喜讯!聚铭网络荣获《日志分类方法及系统》发明专利

近日&#xff0c;聚铭网络又喜获一项殊荣&#xff0c;其申报的《日志分类方法及系统》发明专利成功获得国家知识产权局的授权&#xff0c;正式荣获国家发明专利证书。 在信息化时代&#xff0c;网络安全问题日益凸显&#xff0c;日志分析作为保障网络安全的重要手段&#xff…

SpringBoot多线程查询实战-查询库中所有数据多线程实现

文章目录 案例说明测试结论Controller层核心代码测试数据生成测试报告源码获取 案例说明 本案例我们希望使用三种方式查询数据库某张表下所有数据&#xff1a; 单线程分页查询获取所有数据单线程直接查询获取所有数据多线程分页查询获取所有数据 测试结论 ​ ​ ​在比较…

3D数据格式导出工具HOOPS Publish如何生成高质量3D PDF?

在当今数字化时代&#xff0c;从建筑设计到制造业&#xff0c;从医学领域到电子游戏开发&#xff0c;3D技术已经成为了不可或缺的一部分。在这个进程中&#xff0c;将3D模型导出为3D PDF格式具有重要的意义。同时&#xff0c;HOOPS Publish作为一个领先的解决方案&#xff0c;为…

通过Jmeter准备压测数据-mysql示例

1、新建线程组 总共30万条数据 2、创建jdbc链接 创建jdbc连接配置 配置mysql连接 需要在jmeter安装的路径\apache-jmeter-5.6.3\lib\ext 目录下添加mysql 驱动 3、创建jdbc请求 jdbc链接名称需要与上一步中的保持一致&#xff0c;同时添加insert语句 例如 INSERT INTO test…

iOS - Runtime-消息机制-objc_msgSend()

iOS - Runtime-消息机制-objc_msgSend() 前言 本章主要介绍消息机制-objc_msgSend的执行流程&#xff0c;分为消息发送、动态方法解析、消息转发三个阶段&#xff0c;每个阶段可以做什么。还介绍了super的本质是什么&#xff0c;如何调用的 1. objc_msgSend执行流程 OC中的…

阿里云实时计算Flink的产品化思考与实践【上】

摘要&#xff1a;本文整理自阿里云高级产品专家黄鹏程和阿里云技术专家陈婧敏在 FFA 2023 平台建设专场中的分享。内容主要为以下五部分&#xff1a; 阿里云实时计算 Flink 简介产品化思考产品化实践SQL 产品化思考及实践展望 该主题由黄鹏程和陈婧敏共同完成&#xff0c;前半程…

java调用jacob进行文件转换ppt转pdf或者png

java调用jacob进行文件转换ppt转pdf或者png 前情提要 最近项目上&#xff0c;遇到一个复杂的ppt&#xff0c;最终要求是要将ppt每一页转成图片原本这个是不难&#xff0c;网上一搜一大堆案例&#xff0c;外加我本身也比较精通aspose&#xff0c;那还不是分分钟搞定。结果就是…

Django 中间件

【一】Django框架之生命周期流程图 【二】介绍 【1】概述 Django 中的中间件&#xff08;Middleware&#xff09;是一个轻量级、底层的“插件”系统&#xff0c;用来全局地改变 Django 的输入或输出。每个中间件组件负责处理特定的全局任务&#xff0c;例如处理会话、处理跨站…

【有限状态机】- FSM详细讲解 【附Autoware有限状态机模型代码讲解】

参考博客&#xff1a; &#xff08;1&#xff09;FSM&#xff08;有限状态机&#xff09; &#xff08;2&#xff09;关于有限状态机(FSM)的一些思考 &#xff08;3&#xff09;状态设计模式 1 状态机简介 有限状态机FSM&#xff1a;有限个状态以及在这些状态之间的转移和动作…

2024年最新最全Vue3开源后台管理系统复盘总结

在现代前端开发中&#xff0c;搭建一个高效、灵活、易用的后台管理系统并不容易。然而&#xff0c;Vue3 的出现为我们提供了一个备受瞩目的选择。作为一个现代化的前端框架&#xff0c;Vue3 具有众多优点&#xff0c;能够帮助开发者快速搭建企业级中后台产品原型。 今天&#…

iphoneX系统的参数

1. 2. 3. 4. 5.相关的网址信息 Apple iPhone X 規格、价格和评论 | Kalvo Apple iPhone X 規格、价格和评论 | Kalvo

UOS、Linux下的redis的详细部署流程(适用于内网)

提示&#xff1a;适用于Linux以及UOS等内外网系统服务器部署。 文章目录 一.上传离线包二.部署基本环境三.解压并安装redis四.后台运行redis五.uos系统可能遇到的问题六.总结 一.上传离线包 1.自己去Redis官网下载适配自己部署系统的redis安装包。 2.通过文件传输工具&#xf…

Rust使用原始字符串字面量实现Regex双引号嵌套双引号正则匹配

rust使用Regex实现正则匹配的时候&#xff0c;如果想实现匹配双引号&#xff0c;就需要使用原始字符串字面量&#xff0c;不然无法使用双引号嵌套的。r#"..."# 就表示原始字符串字面量。 比如使用双引号匹配&#xff1a; use regex::Regex;fn main() {println!(&qu…

快速幂算法在Java中的应用

引言&#xff1a; 在计算机科学和算法领域中&#xff0c;快速幂算法是一种用于高效计算幂运算的技术。在实际编程中&#xff0c;特别是在处理大数幂运算时&#xff0c;快速幂算法能够显著提高计算效率。本文将介绍如何在Java中实现快速幂算法&#xff0c;并给出一些示例代码和应…

151 shell编程,正则表达式,在C语言中如何使用正则表达式

零&#xff0c;坑点记录&#xff1a;bash 和 dash 的区别&#xff0c;导致的坑点 查看当前用的shell 是啥&#xff0c;用的是/bin/bash hunandedehunandede-virtual-machine:~$ echo $SHELL /bin/bash 当shell 脚本运行的时候&#xff08;后面会学到方法&#xff0c;这里是最…

全局UI方法-弹窗一警告弹窗(AlertDialog)

1、描述 显示警告弹窗组件&#xff0c;可设置文本内容与响应回调。 2、属性 名称参数类型参数描述showAlertDialogParamWithConfirm | AlertDialogParamWithButtons定义并显示AlertDialog组件。 2.1、AlertDialogParamWithConfirm对象说明&#xff1a; 参数名称参数类型必填…

『Apisix安全篇』探索Apache APISIX身份认证插件:从基础到实战

&#x1f680;『Apisix系列文章』探索新一代微服务体系下的API管理新范式与最佳实践 【点击此跳转】 &#x1f4e3;读完这篇文章里你能收获到 &#x1f6e0;️ 了解APISIX身份认证的重要性和基本概念&#xff0c;以及如何在微服务架构中实施API安全。&#x1f511; 学习如何使…

FreeRTOS(三)

第二部分 事件组 一、事件组的简介 1、事件 事件是一种实现任务间通信的机制&#xff0c;主要用于实现多任务间的同步&#xff0c;但事件通信只能是事件类型的通信&#xff0c;无数据传输。其实事件组的本质就是一个整数(16/32位)。可以是一个事件发生唤醒一个任务&#xff…

ClickHouse初体验

1.clickHouse是啥&#xff1f; ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的列式存储数据库(DBMS)&#xff0c;使用 C语言编写&#xff0c;主要用于在线分析处理查询(OLAP)&#xff0c;能够使用SQL查询实时生成分析数据报告 2.clickHouse的特点 2.1列式存储 对于列的聚合&…

城市内涝排水新模式:慧天[HTWATER]

慧天[HTWATER]软件&#xff1a;慧天排水数字化分析平台针对城市排水系统基础设施数据管理的需求&#xff0c;以及水文、水力及水质模拟对数据的需求&#xff0c;实现了以数据库方式对相应数据的存储。可以对分流制排水系统及合流制排水系统进行地表水文、管网水力、水质过程的模…