move-it / representation_272.py
zirobtc's picture
Upload folder using huggingface_hub
d2a17a9 verified
# representation: 272 dim
# :2 local xz velocities of root, no heading, can recover translation
# 2:8 heading angular velocities, 6d rotation, can recover heading
# 8:8+3*njoint local position, no heading, all at xz origin
# 8+3*njoint:8+6*njoint local velocities, no heading, all at xz origin, can recover local postion
# 8+6*njoint:8+12*njoint local rotations, 6d rotation, no heading, all frames z+
import numpy as np
from utils.face_z_align_util import expmap_to_quaternion, quaternion_to_matrix, quaternion_to_matrix_np, matrix_to_rotation_6d, qrot_np, rotation_6d_to_matrix, matrix_to_axis_angle
import copy
import torch
import scipy.ndimage as ndimage
from tqdm import tqdm
import os
import argparse
def findAllFile(base):
file_path = []
for root, ds, fs in os.walk(base, followlinks=True):
for f in fs:
fullname = os.path.join(root, f)
file_path.append(fullname)
return file_path
def rot_yaw(yaw):
cs = np.cos(yaw)
sn = np.sin(yaw)
return np.array([[cs,0,sn],[0,1,0],[-sn,0,cs]])
def foot_detect(global_positions, thres):
"""
derived from https://github.com/orangeduck/Motion-Matching/blob/37df18afc44e8acca3af5e85dff96effa6a34b03/resources/generate_database.py#L160
"""
left_foot = 10
right_foot = 11
global_velocities = global_positions[1:] - global_positions[:-1]
contact_velocities = np.sqrt(np.sum(global_velocities[:, np.array([left_foot, right_foot])]**2, axis=-1))
contacts = contact_velocities < thres
# Median filter here acts as a kind of "majority vote", and removes
# small regions where contact is either active or inactive
for ci in range(contacts.shape[1]):
contacts[:,ci] = ndimage.median_filter(
contacts[:,ci],
size=6,
mode='nearest')
return contacts
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Process some paths.')
parser.add_argument('--filedir', type=str, required=True, help='Input directory path')
args = parser.parse_args()
bad_cnt = 0
for file in tqdm(findAllFile(os.path.join(args.filedir, 'smpl_85_face_z_transform_joints'))):
output_file = file.replace('smpl_85_face_z_transform_joints', 'Representation_272')
os.makedirs(os.path.dirname(output_file), exist_ok=True)
root_idx = 0
# get joint positions
position_data = np.load(file)
position_data = position_data[:, :22, :3]
nfrm, njoint, _ = position_data.shape
# get smpl rotations
rotation_smpl_axis_angle = np.load(file.replace('smpl_85_face_z_transform_joints', 'smpl_85_face_z_transform'))
rotations_wxyz = expmap_to_quaternion(rotation_smpl_axis_angle[:, :66].reshape(nfrm, njoint, 3))
rotations_matrix = quaternion_to_matrix_np(rotations_wxyz) # nframe, njoint, 3, 3
# put on floor and put root on origin for the first frame
ori = copy.deepcopy(position_data[0,root_idx]) # first frame root position
y_min = np.min(position_data[:,:,1])
ori[1] = y_min
position_data = position_data - ori
velocities_root = position_data[1:,root_idx,:] - position_data[:-1,root_idx,:]
# smpl unit is m and 0.15 is given as cm, may need to change depending on the datasets
contacts = foot_detect(position_data, 0.15/100)
# calculate local position, all frames on xz origin
position_data[:,:,0] -= position_data[:,0:1,0]
position_data[:,:,2] -= position_data[:,0:1,2]
# calculate heading
global_heading = - np.arctan2(rotations_matrix[:,root_idx,0,2], rotations_matrix[:, root_idx, 2,2])
global_heading_rot = np.array([rot_yaw(x) for x in global_heading])
global_heading_diff = global_heading[1:] - global_heading[:-1]
global_heading_diff_rot = np.array([rot_yaw(x) for x in global_heading_diff])
# calculate positions no heading
positions_no_heading = np.matmul(np.repeat(global_heading_rot[:, None,:, :], njoint, axis=1), position_data[...,None]).squeeze(-1)
# calculate velocity no heading
velocities_no_heading = positions_no_heading[1:] - positions_no_heading[:-1]
# calculate root velocity_xz_no_heading
velocities_root_xy_no_heading = np.matmul(global_heading_rot[:-1], velocities_root[:, :, None]).squeeze()[...,[0,2]]
# calculate rotations no heading
rotations_matrix[:,0,...] = np.matmul(global_heading_rot, rotations_matrix[:,0,...])
# concat all
size_frame = 8+njoint*3+njoint*3+njoint*6
final_x = np.zeros((nfrm, size_frame))
# set the first frame of the root rotation to identity
final_x[0, 2] = 1
final_x[0, 6] = 1
try:
final_x[1:,2:8] = matrix_to_rotation_6d(torch.from_numpy(global_heading_diff_rot)).numpy() # take 6D rotation
except:
bad_cnt += 1
continue
final_x[1:,:2] = velocities_root_xy_no_heading
final_x[:,8:8+3*njoint] = np.reshape(positions_no_heading, (nfrm,-1))
final_x[1:,8+3*njoint:8+6*njoint] = np.reshape(velocities_no_heading, (nfrm-1,-1))
final_x[:,8+6*njoint:8+12*njoint] = np.reshape(rotations_matrix[..., :, :2, :], (nfrm,-1)) # take 6D rotation
np.save(output_file, final_x)
print(f"bad_cnt: {bad_cnt}")
print(f"Processed files are saved in {args.filedir}/Representation_272")