File size: 3,261 Bytes
a550c4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Loading BONES-SEED BVH data

The [BONES-SEED dataset](https://huggingface.co/datasets/bones-studio/seed) is a publicly available optical motion-capture dataset distributed as BVH files with the [SOMA 77-joint skeleton](../key_concepts/skeleton.md). This page walks through the steps to parse a SEED BVH file and convert it into Kimodo's internal motion representation.

This is a similar pipeline used by the benchmark to extract ground-truth motions from SEED data (see the [benchmark pipeline](../benchmark/pipeline.md)).

## Step-by-Step Conversion

### 1. Parse the BVH file

`parse_bvh_motion` reads a BVH file and returns local joint rotation matrices, root translation (in meters), and the source frame rate.

```python
from kimodo.skeleton.bvh import parse_bvh_motion

local_rot_mats, root_trans, bvh_fps = parse_bvh_motion(bvh_path)
```

### 2. Subsample to 30 FPS

Kimodo operates at 30 Hz. If the source BVH has a different frame rate (120 FPS for BONES-SEED), subsample by striding:

```python
fps = 30
step = round(bvh_fps / fps)
root_trans = root_trans[::step]
local_rot_mats = local_rot_mats[::step]
```

### 3. Convert to the standard T-pose

The SEED BVH rest pose differs from Kimodo's canonical T-pose. The `to_standard_tpose` function remaps the local rotations accordingly and returns both local and global rotation matrices:

```python
from kimodo.skeleton import SOMASkeleton77

skeleton = SOMASkeleton77()
local_rot_mats, global_rot_mats = skeleton.to_standard_tpose(local_rot_mats)
```

### 4. Compute Kimodo motion features

Build the motion feature tensor used by the model. The feature layout is described in [Motion representation](../key_concepts/motion_representation.md).

```python
from kimodo.motion_rep import KimodoMotionRep

motion_rep = KimodoMotionRep(skeleton, fps)
feats = motion_rep(local_rot_mats, root_trans, to_normalize=False)
```

### 5. Canonicalize (optionally) and recover the motion dictionary

Canonicalize so that the motion starts at the origin facing +Z, then invert the features back into a full motion dictionary:

```python
can_feats = motion_rep.canonicalize(feats)
motion_dict = motion_rep.inverse(can_feats, is_normalized=False)
```

`motion_dict` is a dictionary with keys such as `local_rot_mats`, `global_rot_mats`, `posed_joints`, `root_positions`, `smooth_root_pos`, `foot_contacts`, etc. See [Output formats](output_formats.md) for details on the Kimodo NPZ layout.

## Full script

```python
from kimodo.motion_rep import KimodoMotionRep
from kimodo.skeleton import SOMASkeleton77
from kimodo.skeleton.bvh import parse_bvh_motion

# 1. Parse BVH
local_rot_mats, root_trans, bvh_fps = parse_bvh_motion(bvh_path)

# 2. Subsample to 30 fps
fps = 30
step = round(bvh_fps / fps)
root_trans = root_trans[::step]
local_rot_mats = local_rot_mats[::step]

# 3. Convert to standard T-pose
skeleton = SOMASkeleton77()
local_rot_mats, global_rot_mats = skeleton.to_standard_tpose(local_rot_mats)

# 4. Compute motion features
motion_rep = KimodoMotionRep(skeleton, fps)
feats = motion_rep(local_rot_mats, root_trans, to_normalize=False)

# 5. Canonicalize and get the full motion dictionary
can_feats = motion_rep.canonicalize(feats)
motion_dict = motion_rep.inverse(can_feats, is_normalized=False)
```