OpenCV和Mediapipe实现摸嘴或鼻检测

目录

引言

1.过程简介

2. 代码结构

2.1 导入库

2.2 初始化模型

2.3 读取视频流或摄像头

2.4 初始化FPS计算

2.5 主循环

2.6 转换BGR图像为RGB图像

2.7 运行姿势检测模型和手部检测模型

2.8 绘制姿势关键点及连接线

2.9 检测手部关键点

2.10 判断手部与鼻子、嘴的相对位置

2.11 计算并显示FPS

2.12 显示结果

2.13 退出程序

2.14 释放资源

3. 实现思路

4. 注意事项

5. 总结

行业应用

代码实现

效果展示


引言

        这份代码使用了 MediaPipe 库中的 Pose 模型和 Hands 模型,以及 OpenCV 库,用于实时监测摄像头捕捉到的视频中的姿势和手部动作。主要功能包括标记关键点、绘制姿势连接线以及通过手部与鼻子、嘴的相对位置判定实现了简单的动作监测。

1.过程简介

        这段代码实现了使用MediaPipe库进行人体姿势和手部动作检测,并在摄像头视频流上展示检测结果和实时FPS。

        首先,导入了需要的库,包括cv2和mediapipe。然后,通过mp_pose.Pose()和mp_hands.Hands()初始化了MediaPipe的Pose和Hands模型。

        接下来,通过cap = cv2.VideoCapture(0)打开了摄像头,获取视频流。然后,通过循环读取每一帧的图像,直到视频结束。

        在循环中,首先将BGR图像转换为RGB图像,然后分别使用pose.process()和hands.process()运行姿势和手部检测模型,获得检测结果。

        接着,通过mp.solutions.drawing_utils.draw_landmarks()方法绘制姿势关键点和连接线。如果检测到手部关键点,遍历每个手部关键点,将关键点绘制为圆点。

        在手部检测的过程中,同样检测了鼻尖和嘴巴的位置,判断手部和鼻尖、嘴巴的距离是否小于一定阈值,如果满足条件,则认为在摸鼻子或摸嘴巴。

        在最后,计算FPS并显示在图像上,然后通过cv2.imshow()显示图像。同时,通过cv2.waitKey(1)判断是否按下ESC键,如果是则退出循环。

        最后,释放摄像头资源并关闭所有窗口。

2. 代码结构

2.1 导入库

import cv2 import mediapipe as mp import time

导入 OpenCV 和 MediaPipe 库。

2.2 初始化模型

mp_pose = mp.solutions.pose mp_hands = mp.solutions.hands pose = mp_pose.Pose() hands = mp_hands.Hands() 

初始化姿势检测模型和手部检测模型。

2.3 读取视频流或摄像头

cap = cv2.VideoCapture(0)

打开默认摄像头,获取视频流。

2.4 初始化FPS计算

fps_start_time = time.time() fps_frame_count = 0 fps = 0

记录开始时间和帧数,计算每秒帧数(FPS)。

2.5 主循环

while cap.isOpened(): ret, frame = cap.read() if not ret: break

主循环用于读取视频流的每一帧。

2.6 转换BGR图像为RGB图像

rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

将每一帧从 BGR 转换为 RGB,以适应 MediaPipe 模型。

2.7 运行姿势检测模型和手部检测模型

pose_results = pose.process(rgb_frame) hand_results = hands.process(rgb_frame)

运行姿势检测模型和手部检测模型,获取检测结果。

2.8 绘制姿势关键点及连接线

if pose_results.pose_landmarks: mp.solutions.drawing_utils.draw_landmarks(frame, pose_results.pose_landmarks, mp_pose.POSE_CONNECTIONS)

通过 mp.solutions.drawing_utils.draw_landmarks 绘制姿势关键点及连接线。

2.9 检测手部关键点

if hand_results.multi_hand_landmarks: for landmarks in hand_results.multi_hand_landmarks: # 处理手部关键点

对检测到的手部关键点进行处理。

2.10 判断手部与鼻子、嘴的相对位置

# 判断手是否接近鼻子
distance_to_nose = cv2.norm((nose_x, nose_y), (hand_x, hand_y))
if distance_to_nose < 10:  # 调整阈值以适应你的实际情况
cv2.putText(frame, "Touching Nose", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 155, 155), 2,cv2.LINE_AA)# 判断手是否接近嘴巴
distance_to_mouth = cv2.norm((mouth_x, mouth_y), (hand_x, hand_y))
if distance_to_mouth < 20:  # 调整阈值以适应你的实际情况
cv2.putText(frame, "Touching Mouth", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 155, 155), 2,cv2.LINE_AA)
# 判断手部和鼻尖位置关系 # 判断手部和嘴巴位置关系 

通过相对位置判定手部与鼻子、嘴的关系。

2.11 计算并显示FPS

    # 计算FPSfps_frame_count += 1if fps_frame_count >= 15:fps_end_time = time.time()fps = round(fps_frame_count / (fps_end_time - fps_start_time), 2)fps_frame_count = 0fps_start_time = time.time()# 显示FPScv2.putText(frame, f"FPS: {fps}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)

# 计算并显示FPS

计算帧率,并在视频窗口上方显示。

2.12 显示结果

cv2.imshow('Pose and Hand Detection', frame)

使用 cv2.imshow 显示最终结果。

2.13 退出程序

if cv2.waitKey(1) & 0xFF == 27: # 按ESC键退出 break 

通过按下 ESC 键退出程序。

2.14 释放资源

cap.release() cv2.destroyAllWindows()

释放摄像头资源,关闭所有窗口。

3. 实现思路

        该代码首先通过 MediaPipe 库提供的 Pose 和 Hands 模型,获取姿势和手部的关键点。然后,通过 OpenCV 绘制姿势关键点和连接线,并在每一帧中检测手部的相对位置,判断是否进行了摸鼻子和摸嘴的动作。

4. 注意事项

  • 使用 MediaPipe 提供的模型进行姿势和手部检测。
  • 通过 OpenCV 绘制姿势关键点和连接线,提高可视化效果。
  • 通过相对位置判定手部与鼻子、嘴的关系,实现了动作监测。

5. 总结

        这份代码展示了如何结合 MediaPipe 和 OpenCV 库,实现实时的姿势和手部检测,并通过相对位置的判定,实现了简单的动作监测。代码结构清晰,易于理解和扩展。


行业应用

        此模块可以用作汽车内部摄像头的部署,来实时检测驾驶员的驾驶专注度以达到警示驾驶员的目的。


 

代码实现

import cv2
import mediapipe as mp
import time# 初始化MediaPipe Pose模型和Hand模型
mp_pose = mp.solutions.pose
mp_hands = mp.solutions.hands
pose = mp_pose.Pose()
hands = mp_hands.Hands()# 读取视频流或摄像头
cap = cv2.VideoCapture(0)  # 0表示默认摄像头# 初始化FPS计算
fps_start_time = time.time()
fps_frame_count = 0
fps = 0while cap.isOpened():ret, frame = cap.read()if not ret:break# 转换BGR图像为RGB图像rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 运行姿势估计模型pose_results = pose.process(rgb_frame)# 运行手部估计模型hand_results = hands.process(rgb_frame)# 绘制姿势关键点及连接线if pose_results.pose_landmarks:mp.solutions.drawing_utils.draw_landmarks(frame, pose_results.pose_landmarks, mp_pose.POSE_CONNECTIONS)# 检测手部关键点if hand_results.multi_hand_landmarks:for landmarks in hand_results.multi_hand_landmarks:for point in landmarks.landmark:x, y, _ = int(point.x * frame.shape[1]), int(point.y * frame.shape[0]), int(point.z * frame.shape[1] * 5)cv2.circle(frame, (x, y), 5, (155, 155, 0), -1)# 获取鼻尖位置if pose_results.pose_landmarks:nose_landmark = pose_results.pose_landmarks.landmark[mp_pose.PoseLandmark.NOSE]nose_x, nose_y = int(nose_landmark.x * frame.shape[1]), int(nose_landmark.y * frame.shape[0])# 获取嘴巴位置mouth_landmark = pose_results.pose_landmarks.landmark[int((mp_pose.PoseLandmark.MOUTH_LEFT + mp_pose.PoseLandmark.MOUTH_RIGHT) / 2)]mouth_x, mouth_y = int(mouth_landmark.x * frame.shape[1]), int(mouth_landmark.y * frame.shape[0])# 判断手部和鼻尖位置关系,如果距离小于一定阈值,则判定为摸鼻子for landmarks in hand_results.multi_hand_landmarks:for point in landmarks.landmark:hand_x, hand_y, _ = int(point.x * frame.shape[1]), int(point.y * frame.shape[0]), int(point.z * frame.shape[1] * 5)# 判断手是否接近鼻子distance_to_nose = cv2.norm((nose_x, nose_y), (hand_x, hand_y))if distance_to_nose < 10:  # 调整阈值以适应你的实际情况cv2.putText(frame, "Touching Nose", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 155, 155), 2,cv2.LINE_AA)# 判断手是否接近嘴巴distance_to_mouth = cv2.norm((mouth_x, mouth_y), (hand_x, hand_y))if distance_to_mouth < 20:  # 调整阈值以适应你的实际情况cv2.putText(frame, "Touching Mouth", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 155, 155), 2,cv2.LINE_AA)# 计算FPSfps_frame_count += 1if fps_frame_count >= 15:fps_end_time = time.time()fps = round(fps_frame_count / (fps_end_time - fps_start_time), 2)fps_frame_count = 0fps_start_time = time.time()# 显示FPScv2.putText(frame, f"FPS: {fps}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)# 显示结果cv2.imshow('Pose and Hand Detection', frame)# 退出程序if cv2.waitKey(1) & 0xFF == 27:  # 按ESC键退出break# 释放资源
cap.release()
cv2.destroyAllWindows()

        其实我还想要加入眼睛的部分,但是我写的眼睛部分检测的代码有BUG,所以我就暂时没有加上去,等我研究研究啦~~~~


效果展示

ヾ( ̄▽ ̄)Bye~Bye~

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

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

相关文章

使用Flask快速搭建轻量级Web应用【第127篇—Flask】

使用Flask快速搭建轻量级Web应用 在Web开发领域&#xff0c;选择适合项目需求的框架至关重要。Flask&#xff0c;一个轻量级的Python Web框架&#xff0c;以其简洁、灵活和易扩展的特性而备受开发者青睐。本文将介绍如何使用Flask迅速搭建一个轻量级的Web应用&#xff0c;并通过…

数学建模——蒙特卡洛法

目录 1.介绍2.可以做的题型3.实战3.1求pi的值3.2求定积分x^2 的值 参加了大大小小很多场比赛了&#xff0c;但是都是混子&#xff0c;但还是打算记录一下吧&#xff0c;系统认真过一遍。后续功力深厚&#xff0c;会拓展写的文章&#xff0c;目前是干货&#xff0c;一些背景啥的…

C#多线程(5)——异步方法async与await

在上一章节中&#xff0c;为大家介绍了C#多线程&#xff08;4&#xff09;——任务并行库TPL&#xff0c;TPL是从.NetFramwork4.0后引入的基于异步操作的一组API&#xff0c;核心关注于任务【 T a s k 和 T a s k < T > \textcolor{red}{Task 和 Task<T>} Task和Ta…

轴向磁通电机(轴向电机)属于高效节能型电机 本土企业已具备高性能产品生产实力

轴向磁通电机&#xff08;轴向电机&#xff09;属于高效节能型电机 本土企业已具备高性能产品生产实力 按照磁通路径方向不同&#xff0c;电机可分为径向磁通电机以及轴向磁通电机两种类型。轴向磁通电机又称轴向电机&#xff0c;指电机旋转轴与磁通方向平行的磁通电机。与径向…

Ai-M61-32SU+字库+LCD

Ai-M61-32SU 有4M flash&#xff0c;可以下载一个200多K的GB2312_80字库 一、将gb2312_80.bin(字库文件)烧录到Ai-M61-32SU中 1、将gb2312_80.bin放到工程的根目录 2、修改flash_prog_cfg.ini文件&#xff0c;增加了partition和media部分 [cfg] # 0: no erase, 1:programmed …

js视频上传的方法

一、视频上传于图片上传类似他们的上传方法一样。路径不同标签不同&#xff1b; 二、直接上效果 三、直接上代码 // // 上传图片 let urls "https://wwz.jingyi.icu/"; let a $("form img") // console.log(a);function fl() {let read document.getE…

探索制氮机在农产品保鲜中的应用方式

在现代生活中&#xff0c;农产品保鲜成为老生常谈的话题&#xff0c;水果数次厂商总是在为如何使水果蔬菜能够保存时间长一点而发愁&#xff0c;而制氮机的出现则解决了这一难题&#xff0c;为农产品保鲜技术带来了革命性的变革。本期恒业通小编和您一起了解制氮机在水果,蔬菜保…

Pytorch基础(21)-- torch.repeat_interleave()方法

分享一下自己目前在维护的Github项目&#xff0c;由于本人博士阶段接触了一个全新的研究方向-----使用机器学习、强化学习、深度学习等方法解决组合优化问题&#xff0c;维护这个项目的目的&#xff1a; &#xff08;1&#xff09;记录自己阅读过的paper&#xff0c;同时分享一…

【数学建模】熵权法 Python代码

熵权法是一种客观的赋权方法&#xff0c;它可以靠数据本身得出权重。 依据的原理&#xff1a;指标的变异程度越小&#xff0c;所反映的信息量也越少&#xff0c;其对应的权值也应该越低。 import numpy as np#自定义对数函数mylog&#xff0c;用于处理输入数组中的0元素 def m…

ROS机器人操作系统底层原理及代码剖析

本文介绍ROS机器人操作系统&#xff08;Robot Operating System&#xff09;的实现原理&#xff0c;从最底层分析ROS代码是如何实现的。 1、序列化 把通信的内容&#xff08;也就是消息message&#xff09;序列化是通信的基础&#xff0c;所以我们先研究序列化。 尽管笔者从事…

jenkins部署go应用 基于docker

丢弃旧的的构建 github 拉取代码 拉取代码排除指定配置文件 报错 环境变量失效 服务器版本为1.21.6 但是一直没有生效

字符串|替换数字

卡码网题目链接 #include<iostream> using namespace std; int main() {string s;while (cin >> s) {int count 0; // 统计数字的个数int sOldSize s.size();for (int i 0; i < s.size(); i) {if (s[i] > 0 && s[i] < 9) {count;}}// 扩充字符…

6.同步异步、正则表达式

JS执行机制 js的特点&#xff1a;单线程&#xff0c;同一时间只能做一件事 可以通过多核CPU解决这个问题&#xff0c;允许js脚本创建多个线程&#xff0c;于是js出现了同步和异步 同步 程序执行的时候按照顺序依次执行 异步 程序执行的时候&#xff0c;会跳过某个步骤继续…

基于Springboot的驾校预约学习系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的驾校预约学习系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

fate隐私求交案例

intersect组件是解决纵向联邦学习中的隐私求交问题 fate隐私求交的方式有三种&#xff1a;raw,rsa,dh。raw方式不安全&#xff0c;rsa和dh方式是安全的&#xff0c;dh是基于对称加密的安全交集 rsa是基于RSA(非对称加密)的安全交集&#xff0c;&#xff0c;dh方法也用于安全的…

供应链金融新篇章:2001-2022年上市公司金融水平测算概览

数据说明&#xff1a;参考周兰和吴慧君&#xff08;2022&#xff09;的方法测算出2001-2022年上市公司供应链金融水平&#xff0c;供大家研究使用。数据来源&#xff1a;企业年报等。时间跨度&#xff1a;2001-2022年 数据范围&#xff1a;A股上市公司 数据指标&#xff1a;…

实现swiper 3d 轮播效果

先上个效果图&#xff0c;代码可以直接拿~ 安装swiper和vue-awesome-swiper 因为项目用的是nuxt2&#xff0c;所以考虑到swiper的兼容问题&#xff0c;选择的是"swiper": “^5.2.0” 首先是安装swiper和vue-awesome-swiper&#xff0c;并指定版本 npm install s…

基于Unity3D的AVG卡牌游戏设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 C# 3 1.2 Unity3D 3 1.3 UGUI 3 1.4 XML 4 1.5 原型设计模式 4 1.6 本章小结 4 2 系统分析 5 2.1 用户需求 5 2.2 功能需求 5 2.3 非功能需求 6 2.4 本章小结 6 3 系统设计 7 3.1 系统该要设计 7 3.2 系统详细设计 7 3.2.…

数组和指针笔试题目解析---掌握他们拿下指针魔鬼

目录 一、前言二、一维数组2.1代码2.2分析2.3验证运行结果 三、字符数组3.1代码13.1.1分析3.1.2验证运行结果 3.2代码23.2.1分析3.2.2验证运行结果 3.3代码33.3.1分析3.3.2验证运行结果 3.4代码43.4.1分析3.4.2验证运行结果 3.5代码53.5.1分析3.5.2验证运行结果 3.6代码63.6.1分…

基于SpringBoot和VUE技术的智慧生活商城系统设计与实现

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 一、研究背景…