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

Written by

in

文章目录
  • 坐姿检测是计算机视觉中的一个应用,可以通过分析人体姿态来判断是否保持正确坐姿。下面我将介绍使用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()
  • 脊柱角度应在160-200度之间(接近垂直)颈部角度应在70-110度之间(接近垂直)满足以上条件判断为"Good"坐姿,否则为"Bad"
  • 绘制关键点和连接线 显示角度数值 显示坐姿状态和时间统计 不良坐姿时显示警告
  • 添加更多评估标准(如肩膀是否前倾) 实现坐姿历史记录和统计分析 添加声音提醒功能 优化性能(如降低图像分辨率) 添加校准功能,适应不同体型这个实现提供了基本的坐姿检测功能,你可以根据需要进一步扩展和完善。
  • 到此这篇关于Python图像处理篇之opencv实现坐姿检测的文章就介绍到这了,更多相关Python opencv坐姿检测内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Python+Opencv识别两张相似图片 opencv 做人脸识别 opencv 人脸匹配分析 简单了解OpenCV是个什么东西 python结合opencv实现人脸检测与跟踪
  • 目录
    • 前言
    • 一、方法概述
      • 使用OpenCV和MediaPipe
      • 关键点检测
      • 角度计算
      • 姿态评估
    • 二、完整代码实现
      • 三、代码说明
        • PostureDetector类
        • find_pose()
        • get_landmarks()
        • cakculate_angle()
        • evaluate_posture()
      • 坐姿评估标准(可进行参数调整):
        • 可视化功能:
          • 如何使用
            • 安装依赖库:
            • 运行脚本:
          • 四、改进方向
            • 总结 

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

              使用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类:核心坐姿检测类

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

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

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

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

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

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

              pip install opencv-python mediapipe numpy
              

              python posture_detection.py
              

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

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

              到此这篇关于Python图像处理篇之opencv实现坐姿检测的文章就介绍到这了,更多相关Python opencv坐姿检测内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

              您可能感兴趣的文章:

              • Python+Opencv识别两张相似图片
              • opencv 做人脸识别 opencv 人脸匹配分析
              • 简单了解OpenCV是个什么东西
              • python结合opencv实现人脸检测与跟踪

              站内搜索