图像处理篇---opencv实现坐姿检测

news2025/5/11 18:20:53

文章目录

  • 前言
  • 一、方法概述
    • 使用OpenCV和MediaPipe
    • 关键点检测
    • 角度计算
    • 姿态评估
  • 二、完整代码实现
  • 三、代码说明
    • PostureDetector类
      • find_pose()
      • get_landmarks()
      • cakculate_angle()
      • evaluate_posture()
  • 坐姿评估标准(可进行参数调整):
  • 可视化功能:
  • 如何使用
    • 安装依赖库:
    • 运行脚本:
  • 四、改进方向


前言

坐姿检测是计算机视觉中的一个应用,可以通过分析人体姿态来判断是否保持正确坐姿。下面我将介绍使用Python实现坐姿检测的方法和完整代码。


一、方法概述

使用OpenCV和MediaPipe

使用OpenCV和MediaPipe:MediaPipe提供了现成的人体姿态估计模型

关键点检测

关键点检测:检测身体关键点(如肩膀、耳朵、臀部等)

角度计算

角度计算:计算关键点之间的角度来判断坐姿

姿态评估

姿势评估:根据角度阈值判断坐姿是否正确

二、完整代码实现

import cv2
import mediapipe as mp
import numpy as np
import time

class PostureDetector:
    def __init__(self, mode=False, upBody=False, smooth=True, 
                 detectionCon=0.5, trackCon=0.5):
        """
        初始化姿势检测器
        参数:
            mode: 是否静态图像模式 (False表示视频流)
            upBody: 是否只检测上半身
            smooth: 是否平滑处理
            detectionCon: 检测置信度阈值
            trackCon: 跟踪置信度阈值
        """
        self.mode = mode
        self.upBody = upBody
        self.smooth = smooth
        self.detectionCon = detectionCon
        self.trackCon = trackCon
        
        self.mpDraw = mp.solutions.drawing_utils
        self.mpPose = mp.solutions.pose
        self.pose = self.mpPose.Pose(
            static_image_mode=self.mode,
            model_complexity=1,
            smooth_landmarks=self.smooth,
            enable_segmentation=False,
            smooth_segmentation=self.smooth,
            min_detection_confidence=self.detectionCon,
            min_tracking_confidence=self.trackCon
        )
        
        # 坐姿评估参数
        self.good_posture_time = 0
        self.bad_posture_time = 0
        self.posture_status = "Unknown"
        self.last_posture_change = time.time()
        
    def find_pose(self, img, draw=True):
        """
        检测图像中的姿势关键点
        参数:
            img: 输入图像 (BGR格式)
            draw: 是否绘制关键点和连接线
        返回:
            带标注的图像和姿势关键点
        """
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.pose.process(img_rgb)
        
        if self.results.pose_landmarks and draw:
            self.mpDraw.draw_landmarks(
                img, self.results.pose_landmarks, 
                self.mpPose.POSE_CONNECTIONS)
        
        return img
    
    def get_landmarks(self, img):
        """
        获取所有姿势关键点的坐标
        参数:
            img: 输入图像
        返回:
            关键点坐标列表 (x,y,z) 或 None
        """
        self.landmarks = []
        if self.results.pose_landmarks:
            for id, lm in enumerate(self.results.pose_landmarks.landmark):
                h, w, c = img.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                self.landmarks.append([id, cx, cy, lm.z])
        return self.landmarks
    
    def calculate_angle(self, a, b, c):
        """
        计算三个点之间的角度
        参数:
            a, b, c: 三个点的坐标 (x,y)
        返回:
            角度 (degrees)
        """
        a = np.array(a)
        b = np.array(b)
        c = np.array(c)
        
        radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - np.arctan2(a[1]-b[1], a[0]-b[0])
        angle = np.abs(radians * 180.0 / np.pi)
        
        if angle > 180.0:
            angle = 360 - angle
            
        return angle
    
    def evaluate_posture(self, img, draw=True):
        """
        评估坐姿是否正确
        参数:
            img: 输入图像
            draw: 是否在图像上绘制评估结果
        返回:
            图像和坐姿评估结果
        """
        current_time = time.time()
        posture_changed = False
        
        if not self.landmarks or len(self.landmarks) < 33:
            return img, "No person detected"
        
        # 获取需要的关节点
        left_shoulder = self.landmarks[11][1:3]  # 11: 左肩
        right_shoulder = self.landmarks[12][1:3]  # 12: 右肩
        left_ear = self.landmarks[7][1:3]  # 7: 左耳
        right_ear = self.landmarks[8][1:3]  # 8: 右耳
        left_hip = self.landmarks[23][1:3]  # 23: 左髋
        right_hip = self.landmarks[24][1:3]  # 24: 右髋
        
        # 计算肩膀中点
        shoulder_mid = (
            (left_shoulder[0] + right_shoulder[0]) // 2,
            (left_shoulder[1] + right_shoulder[1]) // 2
        )
        
        # 计算耳朵中点
        ear_mid = (
            (left_ear[0] + right_ear[0]) // 2,
            (left_ear[1] + right_ear[1]) // 2
        )
        
        # 计算髋部中点
        hip_mid = (
            (left_hip[0] + right_hip[0]) // 2,
            (left_hip[1] + right_hip[1]) // 2
        )
        
        # 计算脊柱角度 (肩膀-髋部-垂直线)
        spine_angle = self.calculate_angle(
            (shoulder_mid[0], shoulder_mid[1] - 100),  # 肩膀上方一点
            shoulder_mid,
            hip_mid
        )
        
        # 计算颈部角度 (耳朵-肩膀-水平线)
        neck_angle = self.calculate_angle(
            (ear_mid[0] - 100, ear_mid[1]),
            ear_mid,
            shoulder_mid
        )
        
        # 坐姿评估标准
        good_spine = 160 < spine_angle < 200  # 脊柱应该接近垂直
        good_neck = 70 < neck_angle < 110  # 颈部应该接近垂直
        
        # 判断坐姿
        new_status = "Good" if good_spine and good_neck else "Bad"
        
        # 更新姿势状态时间
        if new_status != self.posture_status:
            posture_changed = True
            self.last_posture_change = current_time
            self.posture_status = new_status
        else:
            if new_status == "Good":
                self.good_posture_time += 1
            else:
                self.bad_posture_time += 1
        
        # 在图像上绘制结果
        if draw:
            # 绘制关键点和连接线
            cv2.circle(img, ear_mid, 8, (255, 0, 0), cv2.FILLED)
            cv2.circle(img, shoulder_mid, 8, (255, 0, 0), cv2.FILLED)
            cv2.circle(img, hip_mid, 8, (255, 0, 0), cv2.FILLED)
            cv2.line(img, ear_mid, shoulder_mid, (255, 0, 0), 3)
            cv2.line(img, shoulder_mid, hip_mid, (255, 0, 0), 3)
            
            # 显示角度信息
            cv2.putText(img, f"Spine Angle: {int(spine_angle)}", 
                        (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv2.putText(img, f"Neck Angle: {int(neck_angle)}", 
                        (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            
            # 显示坐姿状态
            color = (0, 255, 0) if new_status == "Good" else (0, 0, 255)
            cv2.putText(img, f"Posture: {new_status}", 
                        (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)
            
            # 显示时间统计
            cv2.putText(img, f"Good Time: {self.good_posture_time//10}s", 
                        (10, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
            cv2.putText(img, f"Bad Time: {self.bad_posture_time//10}s", 
                        (10, 140), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
            
            # 如果姿势不良,添加警告
            if new_status == "Bad":
                cv2.putText(img, "WARNING: Bad Posture!", 
                            (img.shape[1]//2 - 150, 30), 
                            cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        
        return img, new_status

def main():
    cap = cv2.VideoCapture(0)  # 使用摄像头
    detector = PostureDetector()
    
    while True:
        success, img = cap.read()
        if not success:
            break
            
        img = detector.find_pose(img)
        landmarks = detector.get_landmarks(img)
        
        if landmarks:
            img, posture = detector.evaluate_posture(img)
        
        cv2.imshow("Posture Detection", img)
        
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    
    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

三、代码说明

PostureDetector类

PostureDetector类:核心坐姿检测类

find_pose()

find_pose(): 检测图像中的人体姿势

get_landmarks()

get_landmarks(): 获取姿势关键点坐标

cakculate_angle()

calculate_angle(): 计算三个关键点之间的角度

evaluate_posture()

evaluate_posture(): 评估坐姿是否正确

坐姿评估标准(可进行参数调整):

脊柱角度应在160-200度之间(接近垂直)
颈部角度应在70-110度之间(接近垂直)
满足以上条件判断为"Good"坐姿,否则为"Bad"

可视化功能:

  1. 绘制关键点和连接线
  2. 显示角度数值
  3. 显示坐姿状态和时间统计
  4. 不良坐姿时显示警告

如何使用

安装依赖库:

pip install opencv-python mediapipe numpy

运行脚本:

python posture_detection.py

调整摄像头位置,确保能清晰看到上半身

四、改进方向

  1. 添加更多评估标准(如肩膀是否前倾)
  2. 实现坐姿历史记录和统计分析
  3. 添加声音提醒功能
  4. 优化性能(如降低图像分辨率)
  5. 添加校准功能,适应不同体型
    这个实现提供了基本的坐姿检测功能,你可以根据需要进一步扩展完善

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

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

相关文章

优选算法——前缀和

目录 1. 数组的中心下标 2. 除自身以外数组的乘积 3. 和为k的子数组 4. 和可被K整除的子数组 5. 连续数组 6. 矩阵区域和 1. 数组的中心下标 题目链接&#xff1a;724. 寻找数组的中心下标 - 力扣&#xff08;LeetCode&#xff09; 题目展示&#xff1a; 题目分析&am…

用AI写简历是否可行?

让AI批量写简历然后投简历是绝对不行的&#xff01;&#xff01;&#xff01; 为什么不行&#xff0c;按照 "招聘经理" 工作经历举例&#xff1a; ai提示词&#xff1a;请帮我写一份招聘经理的工作经历内容&#xff1a; 招聘经理 | XXX科技有限公司 | 2020年…

力扣题解:2、两数相加

个人认为&#xff0c;该题目可以看作合并两个链表的变种题&#xff0c;本题与21题不同的是&#xff0c;再处理两个结点时&#xff0c;对比的不是两者的大小&#xff0c;而是两者和是否大于10&#xff0c;加法计算中大于10要进位&#xff0c;所以我们需要声明一个用来标记是否进…

IPM IMI111T-026H 高效风扇控制板

概述&#xff1a; REF-MHA50WIMI111T 是一款专为风扇驱动设计的参考开发板&#xff0c;搭载了英飞凌的IMI111T-026H iMOTION™智能功率模块(IPM)。这个模块集成了运动控制引擎(MCE)、三相栅极驱动器和基于IGBT的功率级&#xff0c;全部封装在一个紧凑的DSO22封装中。REF-MHA50…

武汉火影数字|数字科技馆打造:开启科技探索新大门

足不出户&#xff0c;就能畅游科技的奇幻世界&#xff0c;你相信吗&#xff1f;数字科技馆就能帮你实现&#xff01;在这个数字化的时代&#xff0c;数字科技馆如同一颗璀璨的新星&#xff0c;照亮了我们探索科学的道路。 那么&#xff0c;数字科技馆究竟是什么呢&#xff1f; …

suricata之日志截断

一、背景 在suricata的调试过程中&#xff0c;使用SCLogXXX api进行信息的输出&#xff0c;发现输出的日志被截断了&#xff0c;最开始以为是解析逻辑有问题&#xff0c;没有解析完整&#xff0c;经过排查后&#xff0c;发现SCLogXXX api内部进行了长度限制&#xff0c;最长2K…

简易图片编辑工具,支持抠图和替换背景

软件介绍 Photo Retouch是一款由微软官方商店推出的免费图片处理软件&#xff0c;具有抠图、换背景、修复等功能&#xff0c;操作便捷且效率极高&#xff0c;非常值得尝试。 功能详解 这款软件提供五大功能&#xff0c;包括删除物体、快速修复、一键抠图、背景调整和裁剪…

Java Bean容器详解:核心功能与最佳使用实践

在Java企业级开发中&#xff0c;Bean容器是框架的核心组件之一&#xff0c;它通过管理对象&#xff08;Bean&#xff09;的生命周期、依赖关系等&#xff0c;显著提升了代码的可维护性和扩展性。主流的框架如Spring、Jakarta EE&#xff08;原Java EE&#xff09;均提供了成熟的…

Spring Security 深度解析:打造坚不可摧的用户认证与授权系统

Spring Security 深度解析&#xff1a;打造坚不可摧的用户认证与授权系统 一、引言 在当今数字化时代&#xff0c;构建安全可靠的用户认证与授权系统是软件开发中的关键任务。Spring Security 作为一款功能强大的 Java 安全框架&#xff0c;为开发者提供了全面的解决方案。本…

Selenium模拟人类行为,操作网页的方法(全)

看到有朋友评论问&#xff0c;用selenium怎么模仿人类行为&#xff0c;去操作网页的页面呢&#xff1f; 我想了想&#xff0c;这确实是一个很大的点&#xff0c;不应该是一段代码能解决的&#xff0c; 就像是,如果让程序模拟人类的行为。例如模拟人类买菜&#xff0c;做饭&am…

右值引用的剖析

引入&#xff1a;为什么要有右值引用&#xff1f; 右值引用的存在&#xff0c;就是为了解决左值引用解决不了的问题&#xff01; 左值引用的问题&#xff1a; 我们知道&#xff0c;左值引用在做参数和做返回值都可以提高效率&#xff1b;但是有时候&#xff0c;我们无法用左…

高效Python开发:uv包管理器全面解析

目录 uv简介亮点与 pip、pip-tools、pipx、poetry、pyenv、virtualenv 对比 安装uv快速开始uv安装pythonuv运行脚本运行无依赖的脚本运行有依赖的脚本创建带元数据的 Python 脚本使用 shebang 创建可执行文件使用其他package indexes锁定依赖提高可复现性指定不同的 Python 版本…

【Linux系统编程】进程属性--进程状态

1.进程的状态 1.1进程的状态在PCB中就是一个变量 一般用宏来定义&#xff0c;例如&#xff1a; #define RUNNING 1 #define BLOCK 2 struct task_struct中的int status 1.2并行和并发 CPU执行代码&#xff0c;不是把进程代码执行完毕&#xff0c;才执行下一个&#xff0…

高精度之加减乘除之多解总结(加与减篇)

开篇总述&#xff1a;精度计算的教学比较杂乱&#xff0c;无系统的学习&#xff0c;且存在同法多线的方式进行同一种运算&#xff0c;所以我写此篇的目的只是为了直指本质&#xff0c;不走教科书方式&#xff0c;步骤冗杂。 一&#xff0c;加法 我在此讲两种方法&#xff1a; …

dify插件接入fastmcp示例

文章目录 1. 使用python完成mcp服务1.1 准备环境&#xff08;python安装fastmcp&#xff09;1.2 mcp服务端示例代码1.3 启动mcp服务端 2. dify接入2.1 安装MCP SSE和 Agent 策略&#xff08;支持 MCP 工具&#xff09; 插件2.2 dify agent插件配置mcp:2.3 mcp服务配置&#xff…

c++——二叉树进阶

1. 内容安排说明 二叉树在前面C数据结构阶段已经讲过&#xff0c;本节取名二叉树进阶是因为&#xff1a; 1. map和set特性需要先铺垫二叉搜索树&#xff0c;而二叉搜索树也是一种树形结构 2. 二叉搜索树的特性了解&#xff0c;有助于更好的理解map和set的特性 3. 二叉树中部…

基于flask+pandas+csv的报表实现

基于大模型根据提示词去写SQL执行SQL返回结果输出报表技术上可行的&#xff0c;但为啥还要基于pandas去实现呢&#xff1f; 原因有以下几点&#xff1a; 1、大模型无法满足实时性输出报表的需求&#xff1b; 2、使用大模型比较适合数据量比较大的场景&#xff0c;大模型主要…

PySide6 GUI 学习笔记——常用类及控件使用方法(常用类字体QFont)

文章目录 一、QFont常用方法二、常用方法总结1. 基础属性设置2. 高级样式控制3. 序列化与反序列化4. 字体信息获取 三、应用实例 字体类QFont用于设置界面控件上显示的字体&#xff0c;它包含字体名称、字体尺寸、粗体字、斜体字、删除线、上划线、下划线、字体间距等属性。 如…

宝塔服务安装使用的保姆级教程

宝塔介绍&#xff1a; 宝塔面板&#xff08;BT Panel&#xff09; 是一款 国产的服务器运维管理面板&#xff0c;主要用于简化 Linux/Windows 服务器的网站、数据库、FTP、防火墙等管理操作。它通过图形化界面&#xff08;Web端&#xff09;和命令行工具&#xff08;bt 命令&a…

Linux平台下SSH 协议克隆Github远程仓库并配置密钥

目录 注意&#xff1a;先提前配置好SSH密钥&#xff0c;然后再git clone 1. 检查现有 SSH 密钥 2. 生成新的 SSH 密钥 3. 将 SSH 密钥添加到 ssh-agent 4. 将公钥添加到 GitHub 5. 测试 SSH 连接 6. 配置 Git 使用 SSH 注意&#xff1a;先提前配置好SSH密钥&#xff0c;然…