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

    # 计算FPS
    fps_frame_count += 1
    if fps_frame_count >= 15:
        fps_end_time = time.time()
        fps = round(fps_frame_count / (fps_end_time - fps_start_time), 2)
        fps_frame_count = 0
        fps_start_time = time.time()

    # 显示FPS
    cv2.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 = 0

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

    # 计算FPS
    fps_frame_count += 1
    if fps_frame_count >= 15:
        fps_end_time = time.time()
        fps = round(fps_frame_count / (fps_end_time - fps_start_time), 2)
        fps_frame_count = 0
        fps_start_time = time.time()

    # 显示FPS
    cv2.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~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

300分钟吃透分布式缓存-28讲:如何构建一个高性能、易扩展的Redis集群?

Redis 集群的分布式方案主要有 3 种。分别是 Client 端分区方案&#xff0c;Proxy 分区方案&#xff0c;以及原生的 Redis Cluster 分区方案。 Client 端分区 Client 端分区方案就是由 Client 决定数据被存储到哪个 Redis 分片&#xff0c;或者由哪个 Redis 分片来获取数据。…

DVWA靶场-暴力破解

DVWA是一个适合新手锻炼的靶机&#xff0c;是由PHP/MySQL组成的 Web应用程序&#xff0c;帮助大家了解web应用的攻击手段 DVWA大致能分成以下几个模块&#xff0c;包含了OWASP Top 10大主流漏洞环境。 Brute Force——暴力破解 Command Injection——命令注入 CSRF——跨站请…

职场中的创新思维与执行力

在职场中&#xff0c;创新思维和执行力是两个关键要素。创新思维能够帮助员工在工作中找到更好的解决方案&#xff0c;而执行力则是将想法付诸实践的能力。本文将探讨如何在职场中培养创新思维和提升执行力。 一、创新思维的重要性 在职场中&#xff0c;创新思维是推动企业发展…

Docker容器化技术(互联机制实现便捷互访)

容器的互联是一种让多个容器中的应用进行快速交互的方式。它会在源和接收容器之间创建连接关系&#xff0c;接收容器可以通过容器名快速访问到源容器&#xff0c;而不用指定具体的IP地址。 1.自定义容器命名 连接系统依据容器的名称来执行。因此&#xff0c;首先需要自定义一…

Django 模版基本语法

Django学习笔记 模版语法 本质&#xff1a;在HTML中写一些占位符&#xff0c;由数据对这些占位符进行替换和处理。 views.py def page2(request):#定义一些变量将变量传送给templates中的html文件name1 sallyname2 yingyinghobbys [swimming,badminton,reading]person {…

惬意上手Redis

Redis介绍 Redis&#xff08;全称为REmote Dictionary Server&#xff09;是一个开源的、内存中的数据存储结构&#xff0c;主要用作应用程序缓存或快速相应数据库。 REmote Dictionary Server: 有道翻译Redis是“远程字典服务”&#xff0c;远程不过是远程访问&#xff0c;而…

Ingress 实战:从零到一构建高可用服务

Ingress 是 Kubernetes 中一种用于控制流量进入集群的资源。它可以为集群内的服务提供统一的访问入口&#xff0c;并提供一些额外的功能&#xff0c;例如&#xff1a; 路由流量到不同的服务 提供基于路径的路由 提供基于主机的路由 提供 TLS 加密 使用身份验证和授权 Ing…

SQL: 触发器/存储过程/游标的操作

目录 触发器存储过程创建存储过程修改存储过程删除存储过程执行存储过程 游标待续、更新中 触发器 待更新存储过程 定义 是一组TSQL语句的预编译集合&#xff0c;能实现特定的功能 是一种独立的数据库对象&#xff0c;在服务器上创建和运行 类似于编程语言中的过程或函数分类…

SublimeText4 安装

Sublime Text 可以编写html&#xff0c;css&#xff0c;js&#xff0c;php等等&#xff0c;是一个轻量、简洁、高效、跨平台的编辑器。 图1&#xff1a;SublimeText官网 Sublime Text具有漂亮的用户界面和强大的功能&#xff0c;例如代码缩略图&#xff0c;Python的插件&#…

Java学习记录(十九)多线程(一)

线程 线程是操作系统能进行调度的最小单位&#xff0c;他是被包含在进程中的&#xff0c;一个运行的软件可以看作为一个进程&#xff0c;而在该软件中执行的各种功能自身可以理解为一个线程&#xff0c;可以理解为在软件中互相独立又可以同时进行的功能&#xff0c;他是进程中…

js视频上传的方法

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

计算机网络面经八股-解释一下HTTP长连接和短连接?

在HTTP/1.0中&#xff0c;默认使用的是短连接。也就是说&#xff0c;浏览器和服务器每进行一次HTTP操作&#xff0c;就建立一次连接&#xff0c;但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源&#xff0c;如JavaScript文件、图…

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

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

k8s+wordpress+zabbix+elastic+filebeat+kibana服务搭建以及测试

一&#xff0c;环境&#xff1a;docker&#xff0c;k8s&#xff0c;zabbix&#xff0c;以及搭建worpdress&#xff0c;elasticsearch&#xff0c;filebeat&#xff0c;kibana 二&#xff0c;主机分配&#xff1a; 名称host详述个人博客3192.168.142.133 搭配mysql8.0.36的数据…

ubuntu安装并使用Anaconda

0、说明 对应着 Python 有 2.x 版本和 3.x 版本&#xff0c;Anaconda 也有 Anaconda2 以及 Anaconda 3 两个版本&#xff0c;考虑其流行度&#xff0c;一般谈及 Anaconda 时&#xff0c;默认为 Anaconda3。本人使用的ubuntu20.04。 1、Anaconda 简介 Anaconda 是一个用于科学…

【大模型API调用初尝试二】星火认知大模型 百度千帆大模型

大模型API调用初尝试二 科大讯飞—星火认知大模型单论会话调用多轮会话调用 百度—千帆大模型获取access_token单轮会话多轮会话 科大讯飞—星火认知大模型 星火认知大模型是科大讯飞开发的&#xff0c;直接使用可以点击星火认知大模型&#xff0c;要调用API的话在讯飞开发平台…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的交通信号灯识别系统(深度学习+UI界面+训练数据集+Python代码)

摘要&#xff1a;本研究详细介绍了一种采用深度学习技术的交通信号灯识别系统&#xff0c;该系统集成了最新的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等早期算法进行了性能评估对比。该系统能够在各种媒介——包括图像、视频文件、实时视频流及批量文件中——准确地…

Xilinx 7系列FPGA的配置流程

目录 1.4配置流程 1.4.1 设备上电 ​编辑1.4.2 清除配置寄存器 1.4.3 采样模式引脚 1.4.4 同步 ​编辑1.4.5 检测设备ID ​编辑1.4.6 加载配置数据 1.4.7 CRC校验 1.4.8 启动序列 1.4配置流程 对于所有配置模式&#xff0c;7系列的基本配置流程都是相同的&…

算法练习:二分查找

目录 1. 朴素二分查找2. 在排序数组中查找元素的第一个和最后一个位置3. 搜索插入位置4. x的平方根5. 山脉数组的峰值索引6. 寻找峰值7. 寻找旋转排序数组中的最小值8. 点名 1. 朴素二分查找 题目信息&#xff1a; 题目链接&#xff1a; 二分查找二分查找的使用前提为数据具有&…

leetcode精选算法刷题训练篇 之 链表OJ(包含题目链接以及详细讲解)

好好学习&#xff0c;giao哥给你补&#x1f95a; 1、移除链表元素 难度等级&#xff1a;⭐ 题目链接&#xff1a;移除链表元素 2、链表的中间节点 难度等级&#xff1a;⭐⭐ 题目链接&#xff1a;链表的中间节点 3、反转链表 难度等级&#xff1a;⭐⭐⭐ 题目链接&#x…