如何使用MediaPipe的draw_landmarks仅绘制身体关键点?
问题分析与解决方案
你报错的核心原因是**mp_drawing.draw_landmarks要求landmark_list参数必须是MediaPipe定义的NormalizedLandmarkList对象**,而你手动生成的landmark_list_body是普通的像素坐标列表,完全不符合参数格式要求。
不需要手动转换像素坐标,MediaPipe的draw_landmarks会自动完成归一化坐标到像素坐标的转换。正确的做法是从原始的results.pose_landmarks中筛选出需要的关键点,构建一个新的NormalizedLandmarkList对象,同时还要对应筛选出有效的连接(否则会尝试绘制不存在的关键点连接,导致异常)。
完整修正代码
首先导入对应的proto模块:
from mediapipe.framework.formats import landmark_pb2
替换你原来的关键点筛选和绘制代码:
# 定义需要保留的身体关键点索引(对应MediaPipe Pose官方索引,无需减1) body_landmark_indices = [11,12,13,14,15,16,23,24,25,26,27,28,29,30,31,32] # 构建新的NormalizedLandmarkList对象 filtered_landmarks = landmark_pb2.NormalizedLandmarkList() for idx in body_landmark_indices: # 从原始结果中取出对应索引的关键点,完整复制属性(x/y/z/visibility等) filtered_landmarks.landmark.add().CopyFrom(results.pose_landmarks.landmark[idx]) # 定义只包含目标关键点的有效连接(匹配你的索引列表) filtered_connections = [ (11,12), (11,23), (12,24), (23,24), (11,13), (13,15), (12,14), (14,16), (23,25), (25,27), (27,29), (27,31), (24,26), (26,28), (28,30), (28,32) ] # 调用draw_landmarks绘制指定关键点 mp_drawing.draw_landmarks( image=output_image, landmark_list=filtered_landmarks, connections=filtered_connections, landmark_drawing_spec=landmark_drawing_spec, connection_drawing_spec=connection_drawing_spec )
关键说明
- 直接复用MediaPipe原始的归一化关键点数据,
draw_landmarks会自动根据传入的image尺寸完成坐标转换,不需要手动计算像素坐标。 - 必须同步筛选连接列表,若使用原始的
POSE_CONNECTIONS,其中包含面部等非目标关键点的连接,会因找不到对应关键点而报错。 - 使用
CopyFrom方法可以完整保留原始关键点的所有属性,确保绘制的准确性(比如可见性判断)。
内容的提问来源于stack exchange,提问作者Ghulam
相关产品推荐
相关产品推荐

