用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()
新增功能说明:
- 关键点可视化:
- 使用
mp_drawing.draw_landmarks绘制:- 绿色关键点(可自定义颜色/大小)
- 蓝色连接线(显示身体部位之间的连接)
- 在关键点右侧显示红色编号(0-32)
- 使用
- 自定义样式:
- 通过
DrawingSpec对象可调节:landmark_drawing_spec = mp_drawing.DrawingSpec( color=(0, 255, 0), # BGR颜色格式 thickness=2, # 线宽 circle_radius=2 # 关键点半径 )
- 通过
- 坐标转换:
cx, cy = int(lm.x * w), int(lm.y * h) # 将归一化坐标转换为实际像素坐标
效果增强建议:
- 按可见性过滤关键点:
if lm.visibility > 0.5: # 只显示可见性大于50%的关键点 cv2.putText(...) - 不同部位使用不同颜色:
# 为上半身设置不同颜色 if idx in [11,12,13,14,15,16]: # 肩部、手肘等 color = (0, 165, 255) # 橙色 - 显示坐标信息:
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_radius和thickness参数来优化显示效果以适应不同分辨率的摄像头。