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


文章目录


前言

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


一、方法概述

使用OpenCV和MediaPipe

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

关键点检测

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

角度计算

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

姿态评估

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

二、完整代码实现

python 复制代码
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. 不良坐姿时显示警告

如何使用

安装依赖库:

python 复制代码
pip install opencv-python mediapipe numpy

运行脚本:

python 复制代码
python posture_detection.py

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

四、改进方向

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

相关推荐
liliangcsdn1 小时前
python如何写数据到excel示例
开发语言·python·excel
CNRio1 小时前
将word和excel快速转换为markdown格式
python·word·excel
小白银子4 小时前
零基础从头教学Linux(Day 52)
linux·运维·服务器·python·python3.11
wb043072015 小时前
性能优化实战:基于方法执行监控与AI调用链分析
java·人工智能·spring boot·语言模型·性能优化
AAA小肥杨5 小时前
基于k8s的Python的分布式深度学习训练平台搭建简单实践
人工智能·分布式·python·ai·kubernetes·gpu
lichong9517 小时前
Git 检出到HEAD 再修改提交commit 会消失解决方案
java·前端·git·python·github·大前端·大前端++
Tiny番茄7 小时前
31.下一个排列
数据结构·python·算法·leetcode
mit6.8247 小时前
[Agent可视化] 配置系统 | 实现AI模型切换 | 热重载机制 | fsnotify库(go)
开发语言·人工智能·golang
Percent_bigdata8 小时前
百分点科技发布中国首个AI原生GEO产品Generforce,助力品牌决胜AI搜索新时代
人工智能·科技·ai-native
Gloria_niki8 小时前
YOLOv4 学习总结
人工智能·计算机视觉·目标跟踪