Here is how to convert smpl to bvh:
- Clone https://github.com/sigal-raab/Motion.
- Read the npy file that sample/generate.py in this repo outputs. extract the 'motion' component out of it and use for the following method. The following method expects an npy file so you can either change it or save the aforementioned 'motion' component as an npy file.
- run this method:
def smpl2bvh():
from Motion.InverseKinematics import animation_from_positions
from Motion import BVH
npy_file = 'smpl_3D_joints.npy'
motion_path = f'/path/{npy_file}'
pos = np.load(motion_path)
pos = pos.transpose(0, 3, 1, 2) # samples x joints x coord x frames ==> samples x frames x joints x coord
parents = [-1, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 12, 13, 14, 16, 17, 18, 19, 20, 21]
bvh_path = motion_path[:-4] + 'anim{}.bvh'
SMPL_JOINT_NAMES = [
'Pelvis', # 0
'L_Hip', # 1
'R_Hip', # 2
'Spine1', # 3
'L_Knee', # 4
'R_Knee', # 5
'Spine2', # 6
'L_Ankle', # 7
'R_Ankle', # 8
'Spine3', # 9
'L_Foot', # 10
'R_Foot', # 11
'Neck', # 12
'L_Collar', # 13
'R_Collar', # 14
'Head', # 15
'L_Shoulder', # 16
'R_Shoulder', # 17
'L_Elbow', # 18
'R_Elbow', # 19
'L_Wrist', # 20
'R_Wrist', # 21
'L_Hand', # 22
'R_Hand', # 23
]
for i, p in enumerate(pos):
print(f'starting anim no. {i}')
anim, sorted_order, _ = animation_from_positions(p, parents)
BVH.save(bvh_path.format(i), anim, names=np.array(SMPL_JOINT_NAMES)[sorted_order])
The code above is correct when using the Humanact12 and the UESTC datasets.
If you are using the HumanML3D dataset, you need to drop the last two items from the parents and from the SMPL_JOINT_NAMES arrays.
In step2, "the npy file"refer to "results.npy" which is created by sample/generate.py?
used the "results.npy" and extract the 'motion' as a new npy,
Also, Please comment out line 105 in D:\text-to-motion-main\motion-diffusion-model\Motion\InverseKinematics.py ("assert no.allclose...") and run .
[Explanation: Sometimes the threshold when using np.allclose should be smaller than the default. Since the code in that method is already debugged, there is no need for this assertion.]
An error of 0.008 is actually very good.