MoveNet Pose Lightning TensorFlow关键点定位不准问题求助
MoveNet单姿态估计关键点错位问题修复方案
问题背景
使用TensorFlow Hub的MoveNet单姿态Lightning模型处理1280x720视频,帧缩放到192x192输入后,检测出的关键点与实际身体部位存在明显错位(如肘部关键点偏移),渲染逻辑遵循标准实践。
问题常见性说明
关键点错位是姿态估计部署阶段的常见问题,主要源于输入预处理错误、坐标映射逻辑偏差、低置信度点保留过多或模型精度不足。
针对性修复步骤
1. 修正坐标映射逻辑(核心问题)
MoveNet输出的关键点格式为[x坐标, y坐标, 置信度],但原代码中错误地用帧的[y, x]去缩放坐标,导致x/y轴反转,这是错位的主要原因。需调整缩放维度顺序:
- 在
draw_keypoints和draw_connections函数中,将:
修改为:shaped = np.squeeze(np.multiply(keypoints, [y,x,1]))shaped = np.squeeze(np.multiply(keypoints, [x,y,1])) - 同时对应调整关键点的拆解顺序,例如在
draw_keypoints中:kx, ky, kp_conf = kp # 原代码是ky, kx,需对应x/y顺序
2. 统一图像色彩空间
OpenCV默认读取视频帧为BGR格式,但MoveNet模型要求输入为RGB格式,色彩空间不匹配会降低检测精度:
cap = cv2.VideoCapture('federer.mp4') while cap.isOpened(): ret, frame = cap.read() if not ret: break # 转换为RGB格式供模型输入 rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Resize image img = tf.image.resize_with_pad(tf.expand_dims(rgb_frame, axis=0), 192,192) input_img = tf.cast(img, dtype=tf.int32) # Detection section results = movenet(input_img) keypoints_with_scores = results['output_0'].numpy()[:,:,:51].reshape((1,1,17,3)) # 渲染时使用原BGR帧(或转换回BGR) loop_through_people(frame, keypoints_with_scores, EDGES, 0.3) cv2.imshow('Movenet Singlepose', frame) if cv2.waitKey(10) & 0xFF==ord('q'): break
3. 提升置信度阈值
原代码使用0.1的极低阈值,会保留大量低置信度的错误关键点,建议将阈值提升至0.3-0.5,过滤无效点:
loop_through_people(frame, keypoints_with_scores, EDGES, 0.3)
4. 升级模型精度
若对推理速度要求不高,可替换为精度更高的MoveNet Thunder模型,进一步降低关键点偏移:
model = hub.load("https://tfhub.dev/google/movenet/singlepose/thunder/4")
修正后的完整渲染函数
def draw_keypoints(frame, keypoints, confidence_threshold): y, x, c = frame.shape # 修正坐标映射:模型输出[x,y,conf],对应帧宽x、帧高y shaped = np.squeeze(np.multiply(keypoints, [x, y, 1])) for kp in shaped: kx, ky, kp_conf = kp if kp_conf > confidence_threshold: cv2.circle(frame, (int(kx), int(ky)), 6, (0,255,0), -1) def draw_connections(frame, keypoints, edges, confidence_threshold): y, x, c = frame.shape shaped = np.squeeze(np.multiply(keypoints, [x, y, 1])) for edge, color in edges.items(): p1, p2 = edge x1, y1, c1 = shaped[p1] x2, y2, c2 = shaped[p2] if (c1 > confidence_threshold) & (c2 > confidence_threshold): cv2.line(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0,0,255), 4)
内容的提问来源于stack exchange,提问作者Thehound
相关产品推荐
相关产品推荐

