You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 02:17:18