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

如何基于MediaPipe Hands计算真实手部关节解剖学角度?

问题:MediaPipe手部关节角度计算偏差问题

我尝试用Python结合MediaPipe Hands计算手部关节角度,从results.multi_hand_landmarks获取X、Y、Z坐标后,算出的角度和解剖学角度存在偏差。考虑改用results.multi_hand_world_landmarks替代,但用它计算出的结果更不合理,无法理解原因。

MediaPipe官方说明引用

WORLD_LANDMARKS和LANDMARKS使用相同的 landmark 拓扑结构。但LANDMARKS提供的是3D物体投影到2D图像表面的像素坐标,而WORLD_LANDMARKS提供的是3D物体本身的米制坐标。
output_stream: "WORLD_LANDMARKS:multi_hand_world_landmarks"

实现代码

import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands
import numpy as np
import os

dir = "p"
os.listdir(dir)
print(os.listdir(dir))
# Read images with OpenCV.
images = {name: cv2.imread(f"{dir}/{name}") for name in os.listdir(dir)}

def get_3D_angle(p1,p2,p3):
    # Calculate the vectors between the points
    v1 = p2 - p1
    v2 = p3 - p2
    # Calculate the dot product of the vectors
    dot_product = np.dot(v1, v2)
    # Calculate the magnitudes of the vectors
    magnitude_v1 = np.linalg.norm(v1)
    magnitude_v2 = np.linalg.norm(v2)
    # Calculate the cosine of the angle
    cos_angle = dot_product / (magnitude_v1 * magnitude_v2)
    # Calculate the angle in radians
    angle_rad = np.arccos(cos_angle)
    # Convert the angle to degrees
    angle_deg = np.degrees(angle_rad)
    return angle_deg


# Run MediaPipe Hands.
with mp_hands.Hands(
        static_image_mode=True,
        max_num_hands=1,
        min_detection_confidence=0.8) as hands:
    for name, image in images.items():
        print(f'Analyzing {name}:')
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image.flags.writeable = False
        results = hands.process(image)
        image.flags.writeable = True
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
        annotated_image = image.copy()
        if not results.multi_hand_landmarks:
            continue
        for h in results.multi_hand_landmarks:
            mp_drawing.draw_landmarks(annotated_image, h, mp_hands.HAND_CONNECTIONS,
                                      mp_drawing_styles.get_default_hand_landmarks_style(),
                                      mp_drawing_styles.get_default_hand_connections_style())
        cv2.imwrite(f"{dir}/a_{name}", annotated_image)

        if not results.multi_hand_world_landmarks:
            continue
        for hw in results.multi_hand_world_landmarks:
            mp_drawing.plot_landmarks(hw, mp_hands.HAND_CONNECTIONS, azimuth=5)

            WRIST = hw.landmark[mp_hands.HandLandmark.WRIST]
            MIDDLE_FINGER_MCP = hw.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_MCP]
            MIDDLE_FINGER_PIP = hw.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_PIP]
            MIDDLE_FINGER_DIP = hw.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_DIP]
            MIDDLE_FINGER_TIP = hw.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP]

            # NUMPY
            W = np.array([WRIST.x, WRIST.y, WRIST.z])
            D3MCP = np.array([MIDDLE_FINGER_MCP.x, MIDDLE_FINGER_MCP.y, MIDDLE_FINGER_MCP.z])
            D3PIP = np.array([MIDDLE_FINGER_PIP.x, MIDDLE_FINGER_PIP.y, MIDDLE_FINGER_PIP.z])
            D3DIP = np.array([MIDDLE_FINGER_DIP.x, MIDDLE_FINGER_DIP.y, MIDDLE_FINGER_DIP.z])
            D3TIP = np.array([MIDDLE_FINGER_TIP.x, MIDDLE_FINGER_TIP.y, MIDDLE_FINGER_TIP.z])

            # JOINTS
            JD3MCP = get_3D_angle(W, D3MCP, D3PIP)
            JD3PIP = get_3D_angle(D3MCP, D3PIP, D3DIP)
            JD3DIP = get_3D_angle(D3PIP, D3DIP, D3TIP)

            print("L'angle JD3MCP:", JD3MCP, "degrés")
            print("L'angle JD3PIP:", JD3PIP, "degrés")
            print("L'angle JD3DIP:", JD3DIP, "degrés")

实际计算结果

L'angle JD3MCP: 56.78408447612209 degrés
L'angle JD3PIP: 168.25722369459407 degrés
L'angle JD3DIP: 24.703166329593024 degrés

预期解剖学角度

  • JD3MCP:8°
  • JD3PIP:20°
  • JD3DIP:13°

标注结果图

2D手部标注图(mp_drawing.draw_landmarks输出)

2D手部标注结果

3D世界坐标手部标注图(mp_drawing.plot_landmarks输出)

3D手部世界坐标标注结果


内容的提问来源于stack exchange,提问作者Thomas Dutrey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:44:58