当前位置: 首页 > news >正文

脚对齐调研学习笔记

目录

LODGE 音乐生成舞蹈:

脚对齐注释版:


Foot alignment: Positioning the feet in contact with the ground.

2. Foot-ground alignment: Ensuring the feet make proper contact with the ground surface.

3. Align feet to ground level.

LODGE 音乐生成舞蹈:

LODGE/metric/foot_skating.py at a898e5914d325ec1016302b2a7760e56437e2b9c · li-ronghui/LODGE · GitHub

脚对齐注释版:

# 导入必要的库和模块
from cgi import test
from turtle import left
import numpy as np
import torch
import os
import sys

# 将当前工作目录添加到系统路径,以便导入项目中的其他模块
sys.path.append(os.getcwd())

# 从自定义模块中导入SMPL-X相关函数和类
from dld.data.render_joints.smplfk import do_smplxfk, ax_from_6v, ax_to_6v, SMPLX_Skeleton

def set_on_ground_139(data, smplx_model, ground_h=0):
    """
    调整SMPL-X姿势数据,使脚部接触地面
    
    参数:
        data (torch.Tensor): SMPL-X姿势参数,形状为[帧数, 139]
        smplx_model (SMPLX_Skeleton): SMPLX模型实例,用于前向运动学计算
        ground_h (float): 地面的高度,默认为0
    
    返回:
        torch.Tensor: 调整后的姿势数据,确保脚部接触地面
    """
    length = data.shape[0]
    assert len(data.shape) == 2 and data.shape[1] == 139
    
    # 使用前向运动学计算关节位置
    positions = do_smplxfk(data, smplx_model)
    
    # 获取第一帧左右脚趾的Y轴高度
    l_toe_h = positions[0, 10, 1]
    r_toe_h = positions[0, 11, 1]
    
    # 计算需要调整的高度差
    if abs(l_toe_h - r_toe_h) < 0.02:  # 如果双脚高度接近,取平均
        height = (l_toe_h + r_toe_h)/2
    else:  # 否则取较小值(更接近地面的脚)
        height = min(l_toe_h, r_toe_h)
    
    # 调整全局平移的Y分量,使脚部接触地面
    data[:, 5] -= (height - ground_h)
    return data

def calc_foot_skating_ratio(data, ground_height=0):
    """
    计算脚部滑动比例指标
    
    参数:
        data (numpy.ndarray): 输入姿势数据,形状为[帧数, 139/319/135/315]
        ground_height (float): 地面高度,默认为0
    
    返回:
        tuple: 左/右脚滑动比例 (left_ratio, right_ratio)
    """
    smplx = SMPLX_Skeleton()  # 初始化SMPLX骨骼模型
    
    # 数据预处理,统一转换为139维格式
    if data.shape[1] == 139 or data.shape[1] == 319:
        data = torch.from_numpy(data[:,:139])
    elif data.shape[1] in [135, 315]:
        data = torch.cat([torch.zeros([data.shape[0],4]), torch.from_numpy(data[:,:135])], dim=-1)
    else:
        raise ValueError(f"输入数据维度错误! 实际维度: {data.shape[1]}")
    
    # 调整姿势数据使脚部接触地面
    data = set_on_ground_139(data, smplx, ground_height)
    
    # 前向运动学计算关节三维坐标
    with torch.no_grad():
        model_xp = do_smplxfk(data, smplx)
    
    # 定义相关关节索引(左/右脚踝和脚趾)
    l_ankle_idx, r_ankle_idx, l_foot_idx, r_foot_idx = 7, 8, 10, 11
    relevant_joints = [l_ankle_idx, r_ankle_idx, l_foot_idx, r_foot_idx]
    
    # 提取相关关节坐标并计算速度
    pred_joint_xyz = model_xp[:, relevant_joints, :]  # [T, 4, 3]
    pred_vel = torch.zeros_like(pred_joint_xyz)
    pred_vel[:-1] = pred_joint_xyz[1:] - pred_joint_xyz[:-1]  # 速度计算(位移差)

    # 获取脚部高度信息
    left_foot_y_ankle = model_xp[:, l_ankle_idx, 1]    # 左脚踝Y坐标
    right_foot_y_ankle = model_xp[:, r_ankle_idx, 1]   # 右脚踝Y坐标
    left_foot_y_toe = model_xp[:, l_foot_idx, 1]       # 左脚趾Y坐标
    right_foot_y_toe = model_xp[:, r_foot_idx, 1]      # 右脚趾Y坐标

    # 创建脚部接触地面的掩码(基于高度阈值)
    left_fc_mask = (left_foot_y_ankle <= (ground_height+0.08)) & (left_foot_y_toe <= (ground_height+0.05))
    right_fc_mask = (right_foot_y_ankle <= (ground_height+0.08)) & (right_foot_y_toe <= (ground_height+0.05))

    # 分离左右脚的速度数据
    left_pred_vel = torch.cat([pred_vel[:, 0:1, :], pred_vel[:, 2:3, :]], dim=1)  # 左脚踝和脚趾速度
    right_pred_vel = torch.cat([pred_vel[:, 1:2, :], pred_vel[:, 3:4, :]], dim=1) # 右脚踝和脚趾速度

    # 将非接触期的速度置零
    left_pred_vel[~left_fc_mask] = 0
    right_pred_vel[~right_fc_mask] = 0

    # 统计脚部接触地面的帧数
    left_static_num = torch.sum(left_fc_mask)
    right_static_num = torch.sum(right_fc_mask)

    # 计算水平面(XZ方向)的速度幅值
    left_velocity_tangent = torch.cat([left_pred_vel[..., [0]], left_pred_vel[..., [2]]], dim=-1)
    left_speed = torch.abs(torch.mean(left_velocity_tangent, dim=-1))  # [T, 2] -> [T]
    right_velocity_tangent = torch.cat([right_pred_vel[..., [0]], right_pred_vel[..., [2]]], dim=-1)
    right_speed = torch.abs(torch.mean(right_velocity_tangent, dim=-1))

    # 检测滑动帧(速度超过阈值0.01)
    left_slide_frames = torch.any(left_speed > 0.01, dim=-1)
    right_slide_frames = torch.any(right_speed > 0.01, dim=-1)

    # 计算滑动比例
    left_ratio = torch.sum(left_slide_frames) / left_static_num if left_static_num > 0 else 0
    right_ratio = torch.sum(right_slide_frames) / right_static_num if right_static_num > 0 else 0

    return left_ratio.item(), right_ratio.item()

if __name__ == '__main__':
    # 测试参数设置
    test_dir = '/path/to/test/data'  # 替换为实际测试数据路径
    ground_height = 0                # 设定地面高度
    
    # 初始化统计列表
    left_ratios, right_ratios = [], []
    
    # 遍历测试目录下的所有npy文件
    for file in os.listdir(test_dir):
        if not file.endswith('.npy'):
            continue
        
        # 加载数据并计算滑动比例
        data = np.load(os.path.join(test_dir, file))
        l_ratio, r_ratio = calc_foot_skating_ratio(data, ground_height)
        
        # 收集结果
        left_ratios.append(l_ratio)
        right_ratios.append(r_ratio)
    
    # 输出统计结果
    print(f"测试目录: {test_dir}")
    print(f"左脚平均滑动比例: {np.mean(left_ratios):.4f}")
    print(f"右脚平均滑动比例: {np.mean(right_ratios):.4f}")
    print(f"整体平均滑动比例: {(np.mean(left_ratios)+np.mean(right_ratios))/2:.4f}")

相关文章:

  • 【多线程】synchronized底层实现的方式
  • GPU 模型部署实战以 Llama3 70B、Qwen 与 DeepSeek 为例
  • 算法方法快速回顾
  • mysql入门操作
  • 交易在规则框架下运作,反而能强化自身纪律
  • JavaScript 在 Chrome 中运行详解
  • Buildroot 增加系统启动项并解决后台无法获取输入(串口)
  • PV操作指南
  • 【漏洞复现】Next.js中间件权限绕过漏洞 CVE-2025-29927
  • 穿越之程序员周树人的狂人日记Part7__教育战争2.0
  • C语言 —— 此去经年梦浪荡魂音 - 深入理解指针(卷四)
  • C++类与对象的第一个简单的实战练习-3.24笔记
  • 洛谷题单入门4-P5729 【深基5.例7】工艺品制作-python
  • 一文了解Gradle 依赖管理(五)- 依赖管理缓存依赖
  • K8S学习之基础四十五:k8s中部署elasticsearch
  • Spec2MP:项目管理之项目质量管理
  • oracle数据库(数据库启动关闭/sqlplus登录及基本操作/设置字符集/distinct去重)
  • 光流 | 基于光流的人体异常行为检测算法原理,公式,算法改进,matlab代码
  • 大模型应用(Java)2025/3/24
  • 运维面试题(八)
  • 巴基斯坦全国航班仍持续延误或取消
  • 上海与世界|环城生态公园带是上海绿色发展新名片
  • 呼和浩特推进新一轮国企重组整合:杜绝一项目一公司、一业务一公司
  • 重视体重管理,筑牢健康基石
  • 涨知识|没想到吧,体育老师强调的运动恢复方法是错的?
  • 股价两天涨超30%,中航成飞:不存在应披露而未披露的重大事项