【深度学习实战—9】:基于MediaPipe的坐姿检测

✨博客主页:王乐予🎈
✨年轻人要:Living for the moment(活在当下)!💪
🏆推荐专栏:【图像处理】【千锤百炼Python】【深度学习】【排序算法】

目录

  • 😺一、MediaPipe概述
  • 😺二、MediaPipe姿态特征点检测
    • 🐶2.1 概述
    • 🐶2.2 度量函数
  • 😺三、代码实现
    • 🐶3.1 utils.py
    • 🐶3.2 main.py
  • 😺四、参考

😺一、MediaPipe概述

MediaPipe 是一款由 Google Research 开发并开源的多媒体机器学习模型应用框架。

MediaPipe目前支持的解决方案(Solution)及支持的平台如下图所示:
在这里插入图片描述

😺二、MediaPipe姿态特征点检测

🐶2.1 概述

通过 MediaPipe Pose Marker,可以检测图片或视频中人体的特征点。使用此任务识别关键的身体位置,分析姿势并对动作进行分类。该任务会在图片坐标和三维世界坐标中输出身体姿势地标。

姿势特征点使用一系列模型来预测姿势特征点。第一个模型检测图片帧中是否存在人体,第二个模型则在身体上定位地标。

姿势特征点模型会跟踪 33 个身体特征点位置,表示以下身体部位的大致位置:
请添加图片描述
点位信息如下:

0 - nose
1 - left eye (inner)
2 - left eye
3 - left eye (outer)
4 - right eye (inner)
5 - right eye
6 - right eye (outer)
7 - left ear
8 - right ear
9 - mouth (left)
10 - mouth (right)
11 - left shoulder
12 - right shoulder
13 - left elbow
14 - right elbow
15 - left wrist
16 - right wrist
17 - left pinky
18 - right pinky
19 - left index
20 - right index
21 - left thumb
22 - right thumb
23 - left hip
24 - right hip
25 - left knee
26 - right knee
27 - left ankle
28 - right ankle
29 - left heel
30 - right heel
31 - left foot index
32 - right foot index

🐶2.2 度量函数

坐姿检测将使用不同关键点的向量夹角做判定,向量内角图如下:
在这里插入图片描述
内角计算与向量的起止顺序有关,在上图中,假定选择kpt1和kpt2为人体的两个关键点,kpt3为向量起始点即kpt1的垂直方向任意位置的点,则夹角为:
θ = arccos ⁡ ( P 12 → × P 13 → ∣ P 12 → ∣ ∣ P 13 → ∣ ) \theta =\arccos (\frac{\overrightarrow{P_{12} } \times \overrightarrow{P_{13} } }{\left | \overrightarrow{P_{12} } \right | \left | \overrightarrow{P_{13} } \right | } ) θ=arccos( P12 P13 P12 ×P13 )

不妨设kpt3的y3坐标为0,则带入坐标值有:
θ = arccos ⁡ ( y 1 2 − y 1 × y 2 y 1 ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 ) \theta =\arccos (\frac{y_{1}^{2} - y_{1}\times y_{2} }{y_{1}\sqrt{(x_{2}-x_{1})^{2}+(y_{2}-y_{1})^{2} } } ) θ=arccos(y1(x2x1)2+(y2y1)2 y12y1×y2)

根据上图可知 θ \theta θ为锐角,如果向量方向为由kpt2指向kpt1,则需要在kpt2的垂直方向标记点kpt3,此时 θ \theta θ为钝角。

😺三、代码实现

  • utils.py:包含度量函数的定义与姿态检测函数
  • main.py:主函数,获取需要的关键点数据,绘图

🐶3.1 utils.py

import math as m# 度量函数
def findAngle(x1, y1, x2, y2):theta = m.acos((y2 - y1) * (-y1) / (m.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) * y1))degree = int(180/m.pi)*thetareturn degree"""
歪头监控:计算 左耳(7点)和 右耳(8点)的夹角
低头监控:计算 左嘴角(9点)和 左肩膀(11点)的夹角
侧脸监控:计算 右眼内(4点)和 左耳(7点)的距离,计算 左眼内(1点)和 右耳(8点)的距离
高低肩监控:计算 左肩膀(11点)和 右肩膀(12点)的夹角            *****有的人左肩和右肩一个高一个低*****
撑桌监控:如果 左嘴角(9点)或者 右嘴角(10点)的 y 坐标 大于 左肩膀(11点)或 右肩膀(12点)的 y 坐标,视为撑桌
仰头监控:计算 鼻子(0点)和 左耳(7点)的夹角
趴桌监控:如果 左肩膀(11点)和 右肩膀(12点)的 归一化y坐标 之和大于0.75,判定为趴桌
"""
def all_detection(nose_x, nose_y,                               # 鼻子(0点)的 x 坐标 和 y 坐标left_eye_inner_x, left_eye_inner_y,           # 左眼内(1点)的 x 坐标 和 y 坐标right_eye_inner_x, right_eye_inner_y,         # 右眼内(4点)的 x 坐标 和 y 坐标left_ear_x, left_ear_y,                       # 左耳(7点)的 x 坐标 和 y 坐标right_ear_x, right_ear_y,                     # 右耳(8点)的 x 坐标 和 y 坐标left_mouth_x, left_mouth_y,                   # 左嘴角(9点)的 x 坐标 和 y 坐标right_mouth_x, right_mouth_y,                 # 右嘴角(10点)的 x 坐标 和 y 坐标left_shoulder_x, left_shoulder_y,             # 左肩膀(11点)的 x 坐标 和 y 坐标right_shoulder_x, right_shoulder_y,           # 右肩膀(12点)的 x 坐标 和 y 坐标left_shoulder_x_norm, left_shoulder_y_norm,   # 归一化后的左肩膀(11点)的 x 坐标 和 y 坐标right_shoulder_x_norm, right_shoulder_y_norm  # 归一化后的右肩膀(12点)的 x 坐标 和 y 坐标):waitou_inclination = findAngle(left_ear_x, left_ear_y, right_ear_x, right_ear_y)ditou_inclination = findAngle(left_mouth_x, left_mouth_y, left_shoulder_x, left_shoulder_y)gaodijian_inclination = findAngle(left_shoulder_x, left_shoulder_y, right_shoulder_x, right_shoulder_y)yangtou_inclination = findAngle(nose_x, nose_y, left_ear_x, left_ear_y)if waitou_inclination < 80:tmp = '左歪头'elif waitou_inclination > 100:tmp = '右歪头'elif (left_shoulder_y_norm + right_shoulder_y_norm) > 1.5:tmp = '趴桌'elif ditou_inclination < 115:tmp = '低头'elif left_ear_x < right_eye_inner_x:tmp = '左侧脸'elif right_ear_x > left_eye_inner_x:tmp = '右侧脸'elif gaodijian_inclination > 100:tmp = '高低肩'elif gaodijian_inclination < 80:tmp = '高低肩'elif (left_mouth_y or right_mouth_y) > (left_shoulder_y or right_shoulder_y):tmp = '撑桌'elif yangtou_inclination > 90:tmp = '仰头'else:tmp = '正脸'return tmp

🐶3.2 main.py

import cv2
import mediapipe as mp
from utils import *mp_pose = mp.solutions.pose
pose = mp_pose.Pose(model_complexity=1, min_detection_confidence=0.5, min_tracking_confidence=0.5)
mp_drawing = mp.solutions.drawing_utilscap = cv2.VideoCapture(0)while True:ret, frame = cap.read()h, w = frame.shape[:2]image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)keypoints = pose.process(image)image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)lm = keypoints.pose_landmarkslmPose = mp_pose.PoseLandmark# 歪头监控left_ear_x = int(lm.landmark[lmPose.LEFT_EAR].x * w)    # 左耳(7点)x 坐标left_ear_y = int(lm.landmark[lmPose.LEFT_EAR].y * h)    # 左耳(7点)y 坐标right_ear_x = int(lm.landmark[lmPose.RIGHT_EAR].x * w)  # 右耳(8点)x 坐标right_ear_y = int(lm.landmark[lmPose.RIGHT_EAR].y * h)  # 右耳(8点)y 坐标# 低头监控left_mouth_x = int(lm.landmark[lmPose.MOUTH_LEFT].x * w)    # 左嘴角(9点)x 坐标left_mouth_y = int(lm.landmark[lmPose.MOUTH_LEFT].y * h)    # 左嘴角(9点)y 坐标left_shoulder_x = int(lm.landmark[lmPose.LEFT_SHOULDER].x * w)    # 左肩膀(11点)x 坐标left_shoulder_y = int(lm.landmark[lmPose.LEFT_SHOULDER].y * h)    # 左肩膀(11点)y 坐标# 侧脸监控left_eye_inner_x = int(lm.landmark[lmPose.LEFT_EYE_INNER].x * w)    # 左眼内(1点)x 坐标left_eye_inner_y = int(lm.landmark[lmPose.LEFT_EYE_INNER].y * h)    # 左眼内(1点)y 坐标right_eye_inner_x = int(lm.landmark[lmPose.RIGHT_EYE_INNER].x * w)  # 右眼内(4点)x 坐标right_eye_inner_y = int(lm.landmark[lmPose.RIGHT_EYE_INNER].y * h)  # 右眼内(4点)y 坐标# 高低肩监控right_shoulder_x = int(lm.landmark[lmPose.RIGHT_SHOULDER].x * w)  # 右肩膀(12点)x 坐标right_shoulder_y = int(lm.landmark[lmPose.RIGHT_SHOULDER].y * h)  # 右肩膀(12点)y 坐标# 撑桌监控right_mouth_x = int(lm.landmark[lmPose.MOUTH_RIGHT].x * w)  # 左嘴角(10点)x 坐标right_mouth_y = int(lm.landmark[lmPose.MOUTH_RIGHT].y * h)  # 左嘴角(10点)y 坐标# 仰头监控nose_x = int(lm.landmark[lmPose.NOSE].x * w)    # 鼻子(0点)x 坐标nose_y = int(lm.landmark[lmPose.NOSE].y * h)    # 鼻子(0点)y 坐标# 趴桌监控left_shoulder_x_norm = lm.landmark[lmPose.LEFT_SHOULDER].x  # 左肩膀(11点)x 坐标-归一化left_shoulder_y_norm = lm.landmark[lmPose.LEFT_SHOULDER].y  # 左肩膀(11点)y 坐标-归一化right_shoulder_x_norm = lm.landmark[lmPose.RIGHT_SHOULDER].x  # 右肩膀(12点)x 坐标-归一化right_shoulder_y_norm = lm.landmark[lmPose.RIGHT_SHOULDER].y  # 右肩膀(12点)y 坐标-归一化results = all_detection(nose_x, nose_y,left_eye_inner_x, left_eye_inner_y,right_eye_inner_x, right_eye_inner_y,left_ear_x, left_ear_y,right_ear_x, right_ear_y,left_mouth_x, left_mouth_y,right_mouth_x, right_mouth_y,left_shoulder_x, left_shoulder_y,right_shoulder_x, right_shoulder_y,left_shoulder_x_norm, left_shoulder_y_norm,right_shoulder_x_norm, right_shoulder_y_norm)print(results)mp_drawing.draw_landmarks(image, keypoints.pose_landmarks, mp_pose.POSE_CONNECTIONS)cv2.imshow("Image", image)if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()

需要注意的是utils.py中的判定指标不是固定的,根据摄像头的位置动态调整才能达到满意的效果。

😺四、参考

Google:pose_landmarker
LearnOpencv:building-a-body-posture-analysis-system-using-mediapipe

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

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

相关文章

5个免费下载音乐的网站,喜欢听什么就搜什么

以下5个音乐下载网站&#xff0c;中国人不骗中国人&#xff0c;全部免费。个个曲库丰富&#xff0c;喜欢听什么就搜什么&#xff0c;还能下载mp3格式&#xff0c;点赞收藏即刻拥有&#xff01; 1、MyFreeMP3 tools.liumingye.cn/music/ MyFreeMP3是一个提供音乐播放和下载服…

富凡行是什么软件,来具体聊一聊它的详情,感兴趣的不要错过了

目前做网络项目的人很多&#xff0c;也就衍生出了很多的软件、项目、平台。接触过了很多的产品&#xff0c;感触颇深&#xff0c;确实市面上的东西差别都很大&#xff0c;有好的&#xff0c;有不好的。 我也是喜欢在网上做点副业&#xff0c;自己捣鼓一下&#xff0c;毕竟互联网…

GPT-4:定义未来工作的超级工具

在人工智能的黄金时代&#xff0c;GPT-4&#xff08;Generative Pre-trained Transformer 4&#xff09;以其前所未有的能力&#xff0c;重新定义了工作效率和智能自动化的边界。作为最新一代的语言处理模型&#xff0c;GPT-4不仅仅是一个工具&#xff0c;它是一个全面的解决方…

1.spring源码:初步认识

准备工作 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://www.springframewor…

2024-5-29 石群电路-17

2024-5-29&#xff0c;星期三&#xff0c;17:26&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴.今天又是阳光明媚的一天&#xff0c;没有什么特别的事情发生&#xff0c;给女朋友做了好吃的&#xff0c;吃了西瓜&#xff0c;加油学习&#xff0c;嘻嘻嘻~~~~ 今…

学会前端虚拟滚动,看这篇就够了

一. 虚拟滚动是什么&#xff1f; 前端虚拟滚动是一种用于优化长列表或大量数据展示的技术。它的主要原理是只渲染用户当前可见区域的数据&#xff0c;而不是一次性渲染整个列表或数据集。 在传统的列表渲染中&#xff0c;如果数据量很大&#xff0c;渲染所有数据可能会导致性…

四川易点慧电商抖音小店信誉之店

在当下这个电商飞速发展的时代&#xff0c;如何在众多网店中挑选出一家既可靠又值得信赖的店铺&#xff0c;成为了消费者们关注的焦点。四川易点慧电子商务有限公司抖音小店以其卓越的品质和诚信的经营&#xff0c;逐渐在抖音平台上崭露头角&#xff0c;成为了众多消费者心中的…

HDRnet

local feature and global feature 在这里插入图片描述 Local features and Global features in Image Local feature also known as local descriptors, are distinct, informative characteristics of an image or video frame that are used in computer vision and image…

electron应用安装包瘦身

在win-unpacked目录下 在resources目录下借助asar查看编译后文件 pnpm add asar -g # asar extract /[sourcePath]/app.asar /[targetPath]/app文件夹中的产物有render和main编译文件 其中有soruceMap文件可以通过配置删除 node-modules目录下确认如果没有跨平台需要都移动到…

随机生成pytorch算子测试序列且保证算子参数合法

随机生成pytorch算子测试序列且保证算子参数合法 代码输出 背景: 1.一些对维度进行操作的算子的单算子测试,结果正常,但多个算子组合在一起,结果就不对。是否能给一个算子列表,随机生成它们的组合呢 功能描述: 1.此程序用于在 CUDA 环境中生成随机张量并对其施加一系列随机选…

PHP 汉字转拼音

使用 overtrue/pinyin 库将汉字转换为拼音 在这篇文章中&#xff0c;我将向大家介绍如何使用 overtrue/pinyin 库来将汉字转换为拼音。这是一个非常方便的PHP库&#xff0c;能够帮助我们轻松地进行汉字到拼音的转换。 安装 overtrue/pinyin 库 首先&#xff0c;我们需要通过 C…

redis--集群节点维护

添加节点 因公司业务发展迅猛&#xff0c;现有的三主三从redis cluster架构可能无法满足现有业务的并发写入需求&#xff0c;因此公司紧急采购一台服务器192.168.7.107&#xff0c;需要将其动态添加到集群当中其不能影响业务使用和数据丢失&#xff0c;则添加过程如下: 同步之…

Pandas-中axis的用法

在Pandas中&#xff0c;min(axis)方法是计算DataFrame或Series中每行或每列的最小值的函数。该函数可以接受一个参数axis&#xff0c;用于指定计算最小值的方向。当axis0时&#xff0c;表示沿着行的方向计算最小值&#xff1b;当axis1时&#xff0c;表示沿着列的方向计算最小值…

买入看跌期权怎么理解?

今天带你了解买入看跌期权怎么理解&#xff1f;看跌期权买入者往往预期市场价格将下跌。 买入看跌期权怎么理解&#xff1f; 买入看跌期权是指购买者支付权利金&#xff0c;获得以特定价格向期权出售者卖出一定数量的某种特定商品的权利。看跌期权买入者往往预期市场价格将下跌…

【YOLOv5/v7改进系列】引入AKConv——即插即用的卷积块

一、导言 介绍了一种名为AKConv&#xff08;Alterable Kernel Convolution&#xff09;的新型卷积操作&#xff0c;旨在解决标准卷积操作存在的两个根本性问题。首先&#xff0c;标准卷积操作受限于局部窗口&#xff0c;无法捕获来自其他位置的信息&#xff0c;且其采样形状固…

软件系统测试的类型和方法介绍

测试是软件开发过程中至关重要的一环&#xff0c;负责验证和确认软件系统是否符合预期的需求&#xff0c;并帮助开发团队消除潜在的缺陷。系统测试作为软件测试中不可缺少的过程&#xff0c;是根据预先制定的测试计划和测试用例&#xff0c;以检查软件系统功能、性能、安全性和…

JavaScript tab选项卡切换

下面是一个简单的JavaScript代码示例&#xff0c;展示如何使用tab选项卡来切换内容。 HTML代码&#xff1a; <div class"tab"><button class"tablinks" onclick"openTab(event, tab1)">选项卡1</button><button class&qu…

仿真51单片机程序(下载安装+Proteus)

我是看的这个大佬的:http://t.csdnimg.cn/Z07SZ 大佬写的很详细了,我就不献丑了. 贴上俩个运行成功的截图,有碰到问题的欢迎交流.

初识BootLoader

一、 BootLoader的概念 引导加载程序是系统加电后运行的第一段软件代码。回忆一下PC的体系结构我们可以知道&#xff0c;PC机中的引导加载程序由BIOS&#xff08;本质是一段固件程序&#xff09;和位于硬盘MBR中的BootLoader&#xff08;如LILO、GRUB等&#xff09;组成。BIOS…

【学习Day2】计算机基础

✍&#x1f3fb;记录学习过程中的输出&#xff0c;坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;指点&#x1f64f; 1.4 校验码 奇偶校验 ● 奇偶校验码的编码方法是&#xff1a; 由若干位有效信息的头部或者…