流程
目前主流機器人舞蹈開發(fā)主要分為以下幾個步驟(超鏈接均為github):
- 獲得指定舞蹈的視頻或動捕數(shù)據(jù).bvh
- 將上述數(shù)據(jù)轉(zhuǎn)為SMPL格式,目前SMPLX更常用,對于視頻可以使用TRAM(ASAP使用)或GVHMR(宇樹官方使用),對于動捕直接使用GMR重定向或bvh2smpl(待驗證)
- 將SMPL數(shù)據(jù)重定向到機器人的各個關(guān)節(jié),可用算法H2O或OmniH2O(ASAP使用),也可GMR(宇樹官方使用)
- 通過DeepMimic系列RL算法訓(xùn)練(目前BeyondMimic較常用),仿真通常使用IsaacGym(較老)或IsaacLab配合Isaacsim(較新)等
- 將.onnx動作策略部署至mujoco進行sim2sim驗證
- 將.onnx動作策略部署至實機進行sim2real測試,目前推薦代碼簡潔robomimic-deploy,多合一robojudo。
以上1-3為數(shù)據(jù)處理階段,目的是給訓(xùn)練算法提供可用的高質(zhì)量數(shù)據(jù)。
第4步訓(xùn)練通常被認為是決定最終效果的關(guān)鍵步驟,也是算法工程師主要的工作內(nèi)容,包括對算法的改進如與最新算法的結(jié)合、調(diào)參等。一個熟練的訓(xùn)練通常耗時20小時(4090),但新算法的調(diào)試可能需要一個月。
之所以使用IsaacLab訓(xùn)練、用mujoco驗證是因為前者容易上手訓(xùn)練速度快,后者仿真更精準但學(xué)習(xí)較難。而最近的mujocolab結(jié)合了兩者的優(yōu)勢,使用IsaacLab的API和mujoco的物理引擎,其RL算法使用BeyondMimic,其動作數(shù)據(jù)使用wandb線上存取,并于昨天(2025-10-10)上線了第一個訓(xùn)練案例:G1回旋踢
MJLAB的使用說明
雖然github上已有詳細的readme,但其中存在若干不詳盡或錯誤,因此記錄。
1. 關(guān)于mjlab本體
- 安裝方式建議使用Method 1, Option A, 提示錯誤時按提示加上--dev。
-
run demo沒必要。 - 使用wandb時
- 在終端輸入
wandb login或wandb login --relogin,粘貼API key。 - 在wandb新建一個名為Motions的registry,類型為all types。
- 將
csv_to_npz.py中的wandb.init(..., entity='<自己的team名字如: unitree>')。 - 訓(xùn)練第一步使用csv_to_npz.py,會在wandb生成一個csv_to_npz的project并將動作存在其下,例如fkdance。
- 在終端輸入
MUJOCO_GL=egl uv run src/mjlab/scripts/csv_to_npz.py --input-file /path/to/motion.csv --output-name /path/to/motion.npz --input-fps 30 --output-fps 50 --render
更新后的csv_to_npz可以在前后加入過渡動作,以使得開始前和結(jié)束后平滑過渡:
python src/mjlab/scripts/csv_to_npz.py --input_file data/tu/unitree_joint_data_tu3_2.csv --output_name tu3_2 --render --add-start-transition --add-end-transition --pad-duration 1.5 --transition-duration 1.5
- train時
--registry-name設(shè)置為unitree/csv_to_npz/fkdance(默認使用最新版,也可以自己指定版本,如fkdance:v0),訓(xùn)練時會生成一個mjlab的project,并在其下生成一個隨機碼(例如fk1234fk)的run代表本次訓(xùn)練,點進該run,點擊overview的頁簽,其中有一條run path,用于play時的--wandb-run-path
MUJOCO_GL=egl uv run train Mjlab-Tracking-Flat-Unitree-G1 \
--registry-name unitree/csv_to_npz/fkdance \ #npz動作路徑
--env.scene.num-envs 4096
- 離線train腳本:
MUJOCO_GL=egl uv run train Mjlab-Tracking-Flat-Unitree-G1-No-State-Estimation \
--motion_file artifacts/local/conduct1min.npz \
--env.scene.num-envs 4096
- 中斷后繼續(xù)訓(xùn)練:
uv run train Mjlab-Tracking-Flat-Unitree-G1-No-State-Estimation --motion_file artifacts/local/tu3_2.npz --env.scene.num-envs 4096 --agent.resume True --agent.load_run "2025-12-12_17-48-20"
- play時修改wandb-run-path即可。
uv run play Mjlab-Tracking-Flat-Unitree-G1 \
--wandb-run-path unitree/mjlab/fk1234fk
- 聯(lián)網(wǎng)跑經(jīng)常面臨連接問題,因此可以本地跑策略,要給出.pt文件和.npz動作文件路徑:
uv run play Mjlab-Tracking-Flat-Unitree-G1-No-State-Estimation-Play \
--checkpoint_file logs/rsl_rl/g1_tracking/2025-11-14_11-45-58/model_14999.pt \
--motion_file artifacts/fkdance\:v0/motion.npz
agent配置文件
路徑:/mjlab/src/mjlab/tasks/tracking/config/g1/rl_cfg.py
可修改save_interval, max_iterations等。
PS
- 訓(xùn)練時任務(wù)可用Mjlab-Tracking-Flat-Unitree-G1-No-State-Estimation,其obs為154維,少了motion anchor的pos以及base_lin_vel。
- 單獨運行
csv_to_npz.py時本地是沒有.npz文件的,還需要下載一下,創(chuàng)建一個download_npz.py如下:
import wandb
run = wandb.init()
artifact = run.use_artifact('unitree/csv_to_npz/fkdance:v0', type='motions')
artifact_dir = artifact.download()
原始視頻通過GVHMR以及GMR、mjlab的處理流程
- 按readme安裝GVHMR之后使用代碼轉(zhuǎn)換
python tools/demo/demo.py --video=../motion_data/..
注意:之前同名的輸出results會影響再次輸出,因此要先刪掉。
- 按readme安裝GMR之后運行。
python scripts/gvhmr_to_robot.py \
--gvhmr_pred_file ../GVHMR/outputs/demo/tennis/hmr4d_results.pt \
--robot unitree_g1 --record_video \
--save_path outputs/tennis_motion.pkl # 自定義保存路徑
- 通過mjlab轉(zhuǎn)換pkl文件為csv:
python src/mjlab/scripts/pkl_to_csv_gmr.py \
--pkl-file ../motion_data/..pkl \
--csv-file ../motion_data/cartwheel.csv \
--add-start-transition --add-end-transition \
--transition-duration 1.0 \
--pad-duration 1.0
注意:mjlab的倉庫中的pkl_to_csv.py有問題(2025-11-26),其中第85、86行的.frames .fps要改成dict調(diào)用key的方式fps = data["fps"]。對于gmr轉(zhuǎn)換的pkl,需要將81-93行改為:
with open(pkl_file, "rb") as f:
# 直接讀取你的 pkl 字典(無需 RobustUnpickler,因為你的 pkl 是標準字典)
data = pickle.load(f)
# 從你的 pkl 字典中提取關(guān)鍵字段
fps = data["fps"]
root_pos = data["root_pos"] # (N, 3):x,y,z
root_rot = data["root_rot"] # (N, 4):你的 pkl 中是 xyzw 四元數(shù)
dof_pos = data["dof_pos"] # (N, D):關(guān)節(jié)角度(D 是機器人自由度,如 G1 是 20 左右)
# 關(guān)鍵:重組為腳本需要的 frames 數(shù)組(格式:每一行 = 3位姿 + 3旋轉(zhuǎn) + D關(guān)節(jié))
# 第一步:將你的四元數(shù)(xyzw)轉(zhuǎn)換為腳本需要的“軸角”(3維向量)
print("Converting quaternion (xyzw) to axis-angle (3D vector)...")
root_rot_axisangle = []
for quat in root_rot:
# 四元數(shù)格式:x,y,z,w(你的 pkl 中存儲的格式)
rotation = Rotation.from_quat(quat) # 直接用 scipy 轉(zhuǎn)換
rot_vec = rotation.as_rotvec() # 轉(zhuǎn)為軸角(3維向量)
root_rot_axisangle.append(rot_vec)
root_rot_axisangle = np.array(root_rot_axisangle) # (N, 3)
# 第二步:拼接成 frames 數(shù)組(順序:root_pos(3) + 軸角(3) + 關(guān)節(jié)角度(D))
frames = np.concatenate([root_pos, root_rot_axisangle, dof_pos], axis=1)
original_duration = frames.shape[0] / fps
print(f"Loaded motion with shape: {frames.shape}")
print(f"FPS: {fps}")
print(
f"Original duration: {original_duration:.2f} seconds ({frames.shape[0]} frames)"
)
AMASS通過GMR轉(zhuǎn)換
以CMU為例(fps=120)
GMR環(huán)境轉(zhuǎn)原始數(shù)據(jù)為pkl,此時腳本默認fps=30:
python scripts/smplx_to_robot.py --smplx_file ../motion_data/CMU/05/05_05_stageii.npz --robot unitree_g1 --save_path ../motion_data/pkl/amass0505.pkl --rate_limit --record_video
mjlab轉(zhuǎn)pkl_to_csv:
python src/mjlab/scripts/pkl_to_csv_gmr.py --pkl-file ../motion_data/pkl/amass0505.pkl --csv-file ../motion_data/csv/amass0505.csv --add-start-transition --add-end-transition --transition-duration 1.0 --pad-duration 1.0
mjlab轉(zhuǎn)csv_to_npz,fps轉(zhuǎn)為50:
MUJOCO_GL=egl uv run src/mjlab/scripts/csv_to_npz.py --input-file ../motion_data/csv/amass0505.csv --output-name artifacts/local/amass0505 --input-fps 30 --output-fps 50 --render
以上fps的先降低后升高能夠消除原始數(shù)據(jù)的波動,不必修改。
AMASS數(shù)據(jù)集中CMU數(shù)據(jù)集
其官方網(wǎng)站中包含了對該數(shù)據(jù)集的說明。數(shù)據(jù)格式是SMPL系列,分為140+個包,命名中只有序號,具體動作內(nèi)容可在網(wǎng)站查詢。其中87~90包含一些酷炫動作。使用gmr可直接轉(zhuǎn)換為pkl并保存視頻。
數(shù)據(jù)集
AMASS數(shù)據(jù)集
*amass.npz 是 AMASS 數(shù)據(jù)集(Animation of 3D Human Motion)中常見的壓縮文件格式,存儲了人體運動捕捉(MoCap)數(shù)據(jù)(如關(guān)節(jié)角度、位置、旋轉(zhuǎn)等)。.npz 是 NumPy 的壓縮歸檔格式,可通過 Python 的 numpy 庫直接讀取。
import numpy as np
# 讀取 .npz 文件
amass_data = np.load("amass.npz") # 替換為你的文件路徑
# 查看文件中包含的所有數(shù)據(jù)鍵(keys)
print("包含的數(shù)據(jù)集鍵:", amass_data.files)
可能的結(jié)果: 包含的數(shù)據(jù)集鍵: ['trans', 'poses', 'betas', 'dmpls', 'gender', 'mocap_framerate', ...]
其中
- trans 根節(jié)點(通常是骨盆)的平移數(shù)據(jù)(3D 位置,單位:米) (N, 3) N 為幀數(shù)
- poses 人體關(guān)節(jié)的旋轉(zhuǎn)數(shù)據(jù)(軸角格式,前 3 個值是根節(jié)點旋轉(zhuǎn),后續(xù)每 3 個值對應(yīng)一個關(guān)節(jié)) (N, 156) 52 個關(guān)節(jié) ×3
- betas 人體形狀參數(shù)(SMPL 模型的體型參數(shù),前 10 個為主) (10,) 或 (N, 10)
- dmpls 動態(tài)形狀參數(shù)(可選,用于精細刻畫運動中的體型變化) (N, 8) 或 (N, 12)
- gender 性別標簽('male'/'female'/'neutral') 字符串
- mocap_framerate 運動捕捉的幀率(每秒幀數(shù)) 整數(shù)(如 100)
- frame_time 每幀的時間間隔(秒),通常為 1/mocap_framerate 浮點數(shù)(如 0.01)
- id 運動數(shù)據(jù)的唯一標識(如動作名稱) 字符串
從加載的 amass_data 中提取具體數(shù)據(jù),例如獲取關(guān)節(jié)旋轉(zhuǎn)和根節(jié)點平移:
# 提取核心數(shù)據(jù)
trans = amass_data["trans"] # 根節(jié)點平移 (N, 3)
poses = amass_data["poses"] # 關(guān)節(jié)旋轉(zhuǎn) (N, 156)
betas = amass_data["betas"] # 體型參數(shù) (10,)
fps = amass_data["mocap_framerate"] # 幀率
gender = amass_data["gender"] # 性別
# 打印數(shù)據(jù)形狀
print(f"總幀數(shù):{trans.shape[0]}")
print(f"根節(jié)點平移形狀:{trans.shape}")
print(f"關(guān)節(jié)旋轉(zhuǎn)形狀:{poses.shape}")
print(f"幀率:{fps} FPS")
print(f"性別:{gender}")
若要直觀查看運動序列,可結(jié)合 SMPL 模型和可視化工具(如 pyrender):
import pyrender
import trimesh
from smplx import SMPL # 需要安裝 smplx 庫(處理人體模型)
# 加載 SMPL 模型(需提前下載 SMPL 模型文件,如 smplh中性模型)
smpl_model = SMPL(
model_path="path/to/smpl/models", # 替換為你的 SMPL 模型路徑
gender=gender.decode() if isinstance(gender, bytes) else gender,
batch_size=1
)
# 提取第 i 幀的姿勢和形狀
i = 100 # 第100幀
root_rot = poses[i, :3] # 根節(jié)點旋轉(zhuǎn)(軸角)
body_poses = poses[i, 3:66] # 身體關(guān)節(jié)旋轉(zhuǎn)(前21個關(guān)節(jié),63維)
betas_i = betas[:10] # 前10個形狀參數(shù)
# 用 SMPL 模型生成網(wǎng)格
output = smpl_model(
betas=betas_i[None, :], # 擴展為 batch 維度
global_orient=root_rot[None, :], # 根節(jié)點旋轉(zhuǎn)
body_pose=body_poses[None, :] # 身體關(guān)節(jié)旋轉(zhuǎn)
)
vertices = output.vertices[0].detach().numpy() # 頂點坐標
faces = smpl_model.faces # 面索引
# 用 trimesh 和 pyrender 可視化
mesh = trimesh.Trimesh(vertices=vertices, faces=faces)
scene = pyrender.Scene()
mesh_node = pyrender.Mesh.from_trimesh(mesh)
scene.add(mesh_node)
viewer = pyrender.Viewer(scene, use_raymond_lighting=True)
注意:可視化需要 SMPL 模型文件(需從 SMPL 官網(wǎng) 申請)和
smplx庫(pip install smplx)。
SMPL數(shù)據(jù)集
SMPL(Skinned Multi-Person Linear Model)是一種參數(shù)化人體模型,通過少量參數(shù)(形狀、姿勢)即可生成逼真的 3D 人體網(wǎng)格,廣泛用于計算機視覺(如人體姿態(tài)估計)、動畫生成、機器人模仿學(xué)習(xí)等領(lǐng)域?!癝MPL 格式數(shù)據(jù)” 指適配該模型的輸入 / 輸出數(shù)據(jù),核心圍繞 “形狀參數(shù)” 和 “姿勢參數(shù)” 展開,同時包含模型結(jié)構(gòu)相關(guān)的固定信息(如頂點、骨骼權(quán)重)。
公開SMPL數(shù)據(jù)集下載。
一、SMPL 模型的核心參數(shù)(數(shù)據(jù)核心)
SMPL 模型的輸入數(shù)據(jù)主要分為兩類:形狀參數(shù)(Betas) 和姿勢參數(shù)(Pose),二者共同決定人體的 3D 形態(tài)。對于通用的機器人運動,還有一個根部平移(Trans)。
1. 形狀參數(shù)(Betas,β)
- 作用:定義人體的靜態(tài)體型特征(如身高、胖瘦、肩寬、腿長等),刻畫個體差異。
- 維度:默認 10 維(部分擴展模型如 SMPL-H/SMPL-X 支持 20 維),前 3-5 維貢獻了 95% 以上的體型差異,后續(xù)維度對應(yīng)細微特征(如手指粗細)。
-
數(shù)據(jù)格式:
- 單個個體:1D 數(shù)組
(10,)或(20,)(固定體型,如 “標準男性”“標準女性”)。 - 序列數(shù)據(jù)(如運動捕捉):2D 數(shù)組
(N, 10)(N 為幀數(shù),若體型不變,所有幀的 Betas 相同)。
- 單個個體:1D 數(shù)組
-
取值范圍:通常在
[-3, 3]之間(超出范圍可能生成不自然體型)。
2. 姿勢參數(shù)(Pose,θ)
- 作用:定義人體的動態(tài)姿態(tài)(如關(guān)節(jié)旋轉(zhuǎn)、身體朝向),決定人體的動作狀態(tài)。
-
維度與結(jié)構(gòu):
- SMPL 模型包含 24個關(guān)節(jié)(根節(jié)點 + 23 個身體關(guān)節(jié),不含手指),每個關(guān)節(jié)的旋轉(zhuǎn)用軸角(Axis-Angle) 表示(3 個數(shù)值,描述旋轉(zhuǎn)軸和角度),因此總維度為
24×3=69。 - 姿勢參數(shù)通常拆分為兩部分:
- 全局朝向(Global Orientation):前 3 個值,描述人體根節(jié)點(通常是骨盆)在世界坐標系中的旋轉(zhuǎn)(如面向 X 軸正方向、側(cè)身等)。
- 身體關(guān)節(jié)旋轉(zhuǎn)(Body Pose):后 69 個值(23個關(guān)節(jié) ×3),描述頸部、肩部、髖部、膝蓋等關(guān)節(jié)的旋轉(zhuǎn)。
- SMPL 模型包含 24個關(guān)節(jié)(根節(jié)點 + 23 個身體關(guān)節(jié),不含手指),每個關(guān)節(jié)的旋轉(zhuǎn)用軸角(Axis-Angle) 表示(3 個數(shù)值,描述旋轉(zhuǎn)軸和角度),因此總維度為
-
數(shù)據(jù)格式:
- 單幀姿勢:1D 數(shù)組
(72,)。 - 運動序列:2D 數(shù)組
(N, 72)(N 為幀數(shù),每幀對應(yīng)一個姿勢)。
- 單幀姿勢:1D 數(shù)組
- 注意:軸角格式需通過羅德里格斯公式(Rodrigues' Formula)轉(zhuǎn)換為旋轉(zhuǎn)矩陣,才能用于計算關(guān)節(jié)變換。
3. 根部平移(Trans,p)
維度同上
二、SMPL 模型的輸出數(shù)據(jù)(網(wǎng)格與骨骼)
輸入 Betas 和 Pose 后,SMPL 模型會輸出人體的 3D 網(wǎng)格和骨骼信息,是后續(xù)可視化、動畫生成的核心數(shù)據(jù)。
1. 頂點網(wǎng)格(Vertices)
- 作用:3D 人體的表面網(wǎng)格,由大量頂點組成(SMPL 默認 6890 個頂點)。
-
數(shù)據(jù)格式:
- 單幀網(wǎng)格:2D 數(shù)組
(6890, 3)(每個頂點對應(yīng) 3 個坐標值(x, y, z),世界坐標系)。 - 運動序列:3D 數(shù)組
(N, 6890, 3)(N 為幀數(shù),每幀對應(yīng)一個網(wǎng)格)。
- 單幀網(wǎng)格:2D 數(shù)組
-
用途:直接用于可視化(如通過
pyrender、MeshLab渲染人體)、碰撞檢測(機器人交互場景)。
2. 骨骼權(quán)重(Blend Weights)
- 作用:描述每個頂點受哪些關(guān)節(jié)旋轉(zhuǎn)的影響(蒙皮權(quán)重),用于計算關(guān)節(jié)運動時頂點的位置變化(線性混合蒙皮,Linear Blend Skinning)。
-
數(shù)據(jù)格式:2D 數(shù)組
(6890, 23)(每個頂點對應(yīng) 23 個關(guān)節(jié)的權(quán)重值,權(quán)重和為 1)。 - 特點:SMPL 模型的骨骼權(quán)重是固定的(隨模型文件存儲,不隨姿勢 / 形狀變化),無需實時計算。
3. 關(guān)節(jié)位置(Joints)
- 作用:人體骨骼的關(guān)節(jié)中心點坐標(如骨盆、肩關(guān)節(jié)、膝關(guān)節(jié)),用于骨骼結(jié)構(gòu)分析、運動學(xué)計算。
-
數(shù)據(jù)格式:
- 單幀關(guān)節(jié):2D 數(shù)組
(23, 3)(23 個關(guān)節(jié),每個關(guān)節(jié)的 3D 坐標)。 - 運動序列:3D 數(shù)組
(N, 23, 3)。
- 單幀關(guān)節(jié):2D 數(shù)組
-
分類:
- 局部關(guān)節(jié)位置:相對于父關(guān)節(jié)的坐標(運動學(xué)樹結(jié)構(gòu))。
- 全局關(guān)節(jié)位置:在世界坐標系中的坐標(需結(jié)合全局朝向和根節(jié)點平移計算)。
三、SMPL 相關(guān)擴展模型的格式差異
SMPL 有多個擴展版本,數(shù)據(jù)格式在基礎(chǔ)上略有調(diào)整,需注意區(qū)分:
| 模型版本 | 核心差異 | 姿勢參數(shù)維度 | 頂點數(shù) | 適用場景 |
|---|---|---|---|---|
| SMPL | 基礎(chǔ)人體模型(無手指、表情) | 69(23 關(guān)節(jié) ×3) | 6890 | 全身運動捕捉、動畫生成 |
| SMPL-H | 增加手部模型(15 個手指關(guān)節(jié)) | 165(55 關(guān)節(jié) ×3) | 6890 | 需精細手部動作的場景(如手勢識別) |
| SMPL-X | 增加面部表情(50 個面部關(guān)節(jié))+ 手部 | 225(75 關(guān)節(jié) ×3) | 10475 | 表情 + 手部 + 身體的完整人體建模(如虛擬人) |
| SMPL-A | 適配動物模型(如狗、馬) | 隨動物骨骼數(shù)量變化 | 隨模型變化 | 動物運動捕捉、仿真 |
四、SMPL 格式數(shù)據(jù)的存儲與讀取
SMPL 格式數(shù)據(jù)通常以以下方式存儲,讀取時需對應(yīng)模型版本:
1. 模型文件(固定結(jié)構(gòu))
SMPL 模型的固定參數(shù)(如基礎(chǔ)形狀頂點、骨骼權(quán)重、關(guān)節(jié)父節(jié)點關(guān)系)存儲在 .pkl(Python pickle)文件中,需從官方網(wǎng)站申請(需學(xué)術(shù)許可)。常見文件包括:
-
SMPL_NEUTRAL.pkl(中性體型)、SMPL_MALE.pkl(男性)、SMPL_FEMALE.pkl(女性)。 - 文件內(nèi)包含的關(guān)鍵鍵(key):
-
v_template:基礎(chǔ)形狀頂點(6890, 3)。 -
weights:骨骼權(quán)重(6890, 23)。 -
kintree_table:骨骼運動樹(父關(guān)節(jié)索引)。 -
shapedirs:形狀基函數(shù)(用于計算 Betas 對頂點的影響)。 -
posedirs:姿勢基函數(shù)(用于計算 Pose 對頂點的影響)。
-
2. 運動數(shù)據(jù)文件(動態(tài)參數(shù))
SMPL 格式的運動數(shù)據(jù)(Betas+Pose + 根節(jié)點平移)常存儲在 .npz(NumPy 壓縮文件)或 .json 中,例如 AMASS 數(shù)據(jù)集、MPI-INF-3DHP 數(shù)據(jù)集:
- 典型
.npz文件包含的鍵:-
betas:形狀參數(shù)(10,)或(N, 10)。 -
poses:姿勢參數(shù)(N, 69)(SMPL)或(N, 165)(SMPL-H)。 -
trans:根節(jié)點平移(N, 3)(描述人體在世界坐標系中的位置變化,如行走時的位移)。 -
mocap_framerate:幀率(如 30 FPS、100 FPS)。
-
3. 讀取工具
-
Python 庫:
-
smplx:官方推薦的 SMPL 系列模型庫,支持加載模型、輸入?yún)?shù)生成網(wǎng)格(pip install smplx)。 -
numpy:讀取.npz格式的運動數(shù)據(jù)(np.load("smpl_data.npz"))。 -
trimesh/pyrender:可視化 SMPL 頂點網(wǎng)格(渲染 3D 人體)。
-
-
示例代碼(用
smplx加載模型并生成網(wǎng)格):import numpy as np from smplx import SMPL # 1\. 加載SMPL模型(需指定模型文件路徑) smpl = SMPL( model_path="path/to/smpl/models", # 存放.pkl文件的目錄 gender="neutral", # 中性/男性/女性 batch_size=1 # 批量處理幀數(shù)(1表示單幀) ) # 2\. 準備輸入?yún)?shù)(示例:標準姿勢,輕微胖體型) betas = np.array([[0.5, 0.2, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.float32) # 形狀參數(shù)(10維) global_orient = np.array([[0, 0, 0]], dtype=np.float32) # 全局朝向(無旋轉(zhuǎn)) body_pose = np.array([[0]*66], dtype=np.float32) # 身體關(guān)節(jié)(無旋轉(zhuǎn),標準站立) # 3\. 生成人體網(wǎng)格 output = smpl( betas=betas, global_orient=global_orient, body_pose=body_pose ) # 4\. 提取輸出數(shù)據(jù) vertices = output.vertices[0].detach().numpy() # 頂點網(wǎng)格 (6890, 3) joints = output.joints[0].detach().numpy() # 關(guān)節(jié)位置 (23, 3) print(f"頂點數(shù):{vertices.shape[0]}, 關(guān)節(jié)數(shù):{joints.shape[0]}")
五、SMPL 格式數(shù)據(jù)的核心應(yīng)用場景
- 人體姿態(tài)估計:從 2D 圖像 / 視頻中預(yù)測 SMPL 的 Pose 參數(shù),反推 3D 人體姿態(tài)。
- 運動捕捉數(shù)據(jù)處理:將 MoCap 設(shè)備(如 Vicon)的原始關(guān)節(jié)數(shù)據(jù)轉(zhuǎn)換為 SMPL Pose,用于動畫生成。
- 機器人模仿學(xué)習(xí):讓機器人通過 SMPL 格式的人類運動數(shù)據(jù),學(xué)習(xí)抓取、行走等動作。
- 虛擬人 / 元宇宙:結(jié)合 SMPL-X 的表情和手部參數(shù),構(gòu)建可交互的虛擬人形象。
總結(jié)
SMPL 格式數(shù)據(jù)的核心是 “少參數(shù)控制多維度人體形態(tài)”,關(guān)鍵在于理解:
輸入:Betas(體型)+ Pose(姿態(tài))+ trans(根節(jié)點平移);
輸出:Vertices(網(wǎng)格)+ Joints(關(guān)節(jié))+ weights(骨骼權(quán)重);
擴展:SMPL-H/X 等版本增加了手指、表情參數(shù),需匹配對應(yīng)維度的 Pose 數(shù)據(jù)。
處理時需注意模型版本與數(shù)據(jù)維度的匹配,常用smplx庫加載模型、numpy讀取數(shù)據(jù),結(jié)合可視化工具驗證結(jié)果。
算法
TRAM: Global Trajectory and Motion of 3D Humans from in-the-wild Videos
TRAM(Global Trajectory and Motion of 3D Humans from in-the-wild Videos)是由賓夕法尼亞大學(xué)研究團隊提出的開源4D人體捕捉系統(tǒng),專注于從非受控的真實場景視頻中精準重建3D人體的全局軌跡與運動狀態(tài),為計算機視覺領(lǐng)域的人體運動分析提供了創(chuàng)新解決方案。
核心目標
在計算機視覺領(lǐng)域,從普通視頻中捕捉人體運動時,若不考慮相機運動,多數(shù)方法僅能在相機坐標系中重建人體,難以結(jié)合環(huán)境準確分析人體動作。TRAM旨在解決這一問題,通過兩階段方法實現(xiàn)世界空間中3D人體運動的精準恢復(fù),既捕捉人體運動學(xué)姿態(tài),又獲取其在世界空間中的全局軌跡。對于人型機器人舞蹈的任務(wù),可以根據(jù)人形動作視頻得到SMPL的全局動作軌跡。
工作原理與流程
TRAM集成多種先進技術(shù),通過多步驟協(xié)作實現(xiàn)3D人體運動重建,具體流程如下:
- 相機位姿估計:運行改進的DROID-SLAM算法,對人體區(qū)域進行遮罩處理,降低動態(tài)人體對相機運動估計的干擾,同時結(jié)合ZoeDepth預(yù)測視頻深度信息,提升場景重建精度,并利用場景背景推導(dǎo)運動比例尺,確定相機在全局坐標系中的軌跡與姿態(tài)。
- 人體檢測跟蹤與運動捕捉:采用Detectron2、Segment-Anything進行人體檢測與分割,結(jié)合DEVA-Track-Anything實現(xiàn)復(fù)雜場景下的人體跟蹤;再通過VIMO視頻變換模型,以恢復(fù)的相機為度量尺度參考幀,回歸人體運動學(xué)運動,精準估計3D人體姿態(tài)。
- 結(jié)果整合與輸出:整合相機位姿數(shù)據(jù)與人體運動數(shù)據(jù),將人體運動映射到全局坐標系,渲染輸出包含3D人體全局軌跡與運動的最終視頻,所有中間結(jié)果與最終數(shù)據(jù)會保存在對應(yīng)文件夾中。
如果需要復(fù)現(xiàn)視頻的人形機器人動作,在通過TRAM獲得SMPL數(shù)據(jù)集后,可以利用isaacgym中的maskedmimic模仿SMPL中的動作,通過仿真即可清洗掉其中不可能實現(xiàn)的動作(sim2data,驗證其動作在仿真中可行)。后將其重定向為機器人的動作,此部分技術(shù)代表為H2O與OmniH2O(human2humanoid代碼),具體原理可參照此文。