如何使用MediaPipe归一化视频帧中的手部关键点位置?
手部关键点归一化方案(适配尺度、旋转、平移)
针对MediaPipe检测到手部关键点的尺度、旋转、平移差异,可通过以下步骤实现归一化,让不同帧的手部动作具备可比性:
核心思路
以手部的稳定解剖学特征为基准,依次消除平移、尺度、旋转带来的差异,将所有帧的手部关键点映射到统一的坐标系中。
具体实现步骤
1. 消除平移差异:以手腕为原点
MediaPipe手部关键点的索引0是手腕根部,这是手部的固定根节点。将所有关键点的坐标减去手腕点的坐标,把手腕移到坐标系原点,这样不管手部在画面中的位置如何,都能统一基准位置。
2. 消除尺度差异:基于稳定骨长做缩放
选择手部相对稳定的骨骼长度作为尺度基准,比如**手腕(索引0)到中指掌指关节(索引9)**的距离——这段骨骼长度不会因手部动作(如握拳、伸展)发生明显变化,适合作为尺度参考:
- 计算基准骨骼的欧氏距离(即两点坐标的L2范数);
- 将所有平移后的关键点坐标除以这个距离,这样基准骨骼的长度会被归一化为1,其他部位的相对尺寸也会按比例缩放,彻底消除相机距离带来的尺寸差异。
3. 消除旋转差异:对齐到固定方向
以基准骨骼的向量为参考,将手部旋转对齐到统一方向(比如x轴正方向):
- 计算基准向量与x轴的夹角θ(用
arctan2(y, x)计算); - 用旋转矩阵对所有尺度归一化后的关键点做旋转变换,公式如下:
这样无论手部朝向如何旋转,基准骨骼都会对齐到x轴,跨帧的手部姿态对比就不会受朝向影响。x' = x * cosθ + y * sinθ y' = -x * sinθ + y * cosθ
关键细节处理
- 过滤低置信度关键点:MediaPipe返回每个关键点的置信度,处理前先过滤置信度低于阈值(比如0.5)的点,避免错误计算;
- 备选基准点:如果某帧中中指掌指关节的置信度不足,可替换为拇指掌指关节(索引2)或食指掌指关节(索引5)作为基准;
- 可选范围归一化:如果需要将坐标限制在固定区间(如[0,1]),可在上述步骤后,将所有坐标除以最大的坐标绝对值,进一步统一数值范围。
示例代码(Python)
import numpy as np def normalize_hand_keypoints(keypoints, conf_threshold=0.5): # 输入:keypoints是(21, 3)数组,包含x,y,confidence;输出:归一化后的(21,2)坐标 # 先过滤低置信度点 valid_mask = keypoints[:, 2] >= conf_threshold if not valid_mask[0] or not valid_mask[9]: # 确保手腕和中指MCP有效 return None # 提取x,y坐标 coords = keypoints[:, :2] # 1. 平移:以手腕为原点 wrist = coords[0] shifted_coords = coords - wrist # 2. 尺度归一化 ref_vector = shifted_coords[9] ref_length = np.linalg.norm(ref_vector) if ref_length < 1e-6: # 避免除以0 return shifted_coords scaled_coords = shifted_coords / ref_length # 3. 旋转归一化 theta = np.arctan2(ref_vector[1], ref_vector[0]) rotation_matrix = np.array([ [np.cos(theta), np.sin(theta)], [-np.sin(theta), np.cos(theta)] ]) normalized_coords = scaled_coords @ rotation_matrix return normalized_coords
内容的提问来源于stack exchange,提问作者aron bleier
相关产品推荐
相关产品推荐

