肢体动作识别和数据发送

用python写个程序,调用本机摄像头,使用mediapipe库识别我的肢体动作,通过udp发送获得的动作数据 以下是增加关键点可视化功能的改进代码,包含详细的注释说明:

import cv2
import mediapipe as mp
import socket
import json

# 初始化MediaPipe组件
mp_pose = mp.solutions.pose
mp_drawing = mp.solutions.drawing_utils  # 新增绘图工具
pose = mp_pose.Pose(
    static_image_mode=False,
    model_complexity=1,
    enable_segmentation=False,
    min_detection_confidence=0.5
)

# 配置UDP
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 自定义绘图样式
landmark_drawing_spec = mp_drawing.DrawingSpec(
    color=(0, 255, 0),   # 关键点颜色 (BGR)
    thickness=2,         # 关键点粗细
    circle_radius=2      # 关键点半径
)
connection_drawing_spec = mp_drawing.DrawingSpec(
    color=(255, 0, 0),   # 连接线颜色
    thickness=2          # 连接线粗细
)

cap = cv2.VideoCapture(0)

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

    # 转换为RGB格式进行检测
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = pose.process(rgb_frame)

    if results.pose_landmarks:
        # 发送数据逻辑保持不变
        landmarks = []
        for idx, landmark in enumerate(results.pose_landmarks.landmark):
            landmarks.append({
                "id": idx,
                "x": landmark.x,
                "y": landmark.y,
                "z": landmark.z,
                "visibility": landmark.visibility
            })
        data = json.dumps(landmarks).encode('utf-8')
        sock.sendto(data, (UDP_IP, UDP_PORT))

        # 新增可视化部分 ---------------------------
        # 绘制关键点和连接线
        mp_drawing.draw_landmarks(
            frame,
            results.pose_landmarks,
            mp_pose.POSE_CONNECTIONS,
            landmark_drawing_spec=landmark_drawing_spec,
            connection_drawing_spec=connection_drawing_spec
        )

        # 显示关键点编号
        h, w, _ = frame.shape  # 获取画面尺寸
        for idx, lm in enumerate(results.pose_landmarks.landmark):
            # 将归一化坐标转换为实际像素坐标
            cx, cy = int(lm.x * w), int(lm.y * h)
            # 在关键点旁显示编号
            cv2.putText(frame, 
                       str(idx), 
                       (cx+5, cy+5), 
                       cv2.FONT_HERSHEY_SIMPLEX, 
                       0.4, 
                       (0, 0, 255),  # 红色编号
                       1)

    # 显示处理后的画面
    cv2.imshow('Pose Detection with Landmarks', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
pose.close()
sock.close()

新增功能说明:

  1. 关键点可视化
    • 使用mp_drawing.draw_landmarks绘制:
      • 绿色关键点(可自定义颜色/大小)
      • 蓝色连接线(显示身体部位之间的连接)
    • 在关键点右侧显示红色编号(0-32)
  2. 自定义样式
    • 通过DrawingSpec对象可调节:
      landmark_drawing_spec = mp_drawing.DrawingSpec(
      color=(0, 255, 0),  # BGR颜色格式
      thickness=2,        # 线宽
      circle_radius=2     # 关键点半径
      )
  3. 坐标转换
    cx, cy = int(lm.x * w), int(lm.y * h)  # 将归一化坐标转换为实际像素坐标

效果增强建议:

  1. 按可见性过滤关键点
    if lm.visibility > 0.5:  # 只显示可见性大于50%的关键点
       cv2.putText(...)
  2. 不同部位使用不同颜色
    # 为上半身设置不同颜色
    if idx in [11,12,13,14,15,16]:  # 肩部、手肘等
       color = (0, 165, 255)  # 橙色
  3. 显示坐标信息
    cv2.putText(frame, 
              f"{cx},{cy}", 
              (cx+15, cy-5), 
              cv2.FONT_HERSHEY_PLAIN,
              0.8,
              (255,255,255))

各关键点对应身体部位:

编号 身体部位 编号 身体部位
0 鼻子 16 右手腕
11 左肩 17 右手小指根部
12 右肩 18 右手无名指根部
13 左手肘 19 右手中指根部
14 右手肘 20 右手食指根部
15 左手腕 21 右手拇指根部

完整对应表建议参考 https://ai.google.dev/edge/mediapipe/solutions/guide?hl=zh-cn

运行效果:

  • 实时视频窗口中将显示:
    • 带编号的身体关键点
    • 蓝色连接线表示骨骼结构
    • 红色数字标识具体关键点编号
    • 原始UDP数据发送功能保持不变

可以通过调整circle_radiusthickness参数来优化显示效果以适应不同分辨率的摄像头。

此条目发表在Media Pipe分类目录。将固定链接加入收藏夹。