def __init__(self, garment_class, gender, shape_style_list_path='avail.txt', split=None): super(ShapeStyleCanonPose, self).__init__() self.garment_class = garment_class self.gender = gender root_dir = os.path.join(global_var.DATA_DIR, '{}_{}'.format(garment_class, gender)) if garment_class == 'old-t-shirt': betas = np.stack([ np.load( os.path.join(root_dir, 'shape/beta_{:03d}.npy'.format(i))) for i in range(9) ]).astype(np.float32)[:, :10] gammas = np.stack([ np.load( os.path.join(root_dir, 'style/gamma_{:03d}.npy'.format(i))) for i in range(26) ]).astype(np.float32) else: betas = np.load(os.path.join(root_dir, 'shape/betas.npy'))[:, :10] gammas = np.load(os.path.join(root_dir, 'style/gammas.npy')) with open(os.path.join(root_dir, shape_style_list_path), "r") as f: ss_list = [l.strip().split('_') for l in f.readlines()] assert (split in [None, 'train', 'test']) with open(os.path.join(root_dir, "test.txt"), "r") as f: test_ss = [l.strip().split('_') for l in f.readlines()] if split == 'train': ss_list = [ss for ss in ss_list if ss not in test_ss] elif split == 'test': ss_list = [ss for ss in ss_list if ss in test_ss] unpose_v = [] for shape_idx, style_idx in ss_list: fpath = os.path.join( root_dir, 'style_shape/beta{}_gamma{}.npy'.format(shape_idx, style_idx)) if not os.path.exists(fpath): print("shape {} and style {} not available".format( shape_idx, style_idx)) unpose_v.append(np.load(fpath)) unpose_v = np.stack(unpose_v) self.ss_list = ss_list self.betas = torch.from_numpy(betas.astype(np.float32)) self.gammas = torch.from_numpy(gammas.astype(np.float32)) self.unpose_v = torch.from_numpy(unpose_v.astype(np.float32)) self.apose = torch.from_numpy(get_Apose().astype(np.float32))
pca = PCA(n_components=4) pca.components_ = style_model['pca_w'] pca.mean_ = style_model['mean'] skirt_v = pca.inverse_transform(np.zeros([1, 4])).reshape([-1, 3]) # move the skirt to the right position with open(osp.join(ROOT, 'garment_class_info.pkl'), 'rb') as f: garment_meta = pickle.load(f) skirt_f = garment_meta['skirt']['f'] vert_indices = garment_meta['pant']['vert_indices'] up_bnd_inds = np.load(osp.join(ROOT, 'skirt_upper_boundary.npy')) pant_up_bnd_inds = np.load(osp.join(ROOT, 'pant_upper_boundary.npy')) waist_body_inds = vert_indices[pant_up_bnd_inds] smpl = SMPLNP(gender='female') apose = get_Apose() body_v, _ = smpl(np.zeros([300]), apose, None, None) trans = np.mean(body_v[waist_body_inds], 0, keepdims=True) - np.mean( skirt_v[up_bnd_inds], 0, keepdims=True) skirt_v = skirt_v + trans skirt_v[:, 0] -= 0.01 p = 1 K = 100 # find closest vertices dist = np.sqrt(np.sum(np.square(skirt_v[:, None] - body_v[None]), 2)) # n_skirt, n_body body_ind = np.argsort(dist, 1)[:, :K] body_dist = np.sort(dist, 1)[:, :K]
import os import os.path as osp import trimesh import numpy as np from utils.ios import save_pc2 from utils.rotation import interpolate_pose import pickle from smpl_torch import SMPLNP_Lres, SMPLNP from utils.rotation import get_Apose from sklearn.decomposition import PCA from utils.part_body import part_body_faces from utils.diffusion_smoothing import DiffusionSmoothing as DS from global_var import ROOT APOSE = get_Apose() def gamma_transform(gamma, coeff_mean, coeff_range): return coeff_mean + gamma * coeff_range def find_perpendicular_foot(x0, x1, x2): # x0, x1 define a line. x2 is an arbitary point x10 = x1 - x0 x02 = x0 - x2 return x0 - (x10) * np.dot(x10, x02) / np.dot(x10, x10) def polygon_area(v): x = v[:, 0].copy()
""" Go through the scanning dataset and find available registrations for each garment class save their displacement (in one .npy file) and meta information (triangulation, mapping with SMPL) INPUT: registration mesh under /BS/bharat-2/work/data/renderings OUTPUT: {ROOT}/raw_data/{garment_class}.npy {ROOT}/garment_class_info.pkl """ import os import json import numpy as np import pickle from utils.rotation import get_Apose import trimesh APOSE = get_Apose() upper_lower_dict = { 't-shirt': 'UpperClothes', 'pant': 'Pants', 'shirt': 'UpperClothes', 'short-pant': 'Pants' } v_num = { 't-shirt': 7702, 'shirt': 9723, 'pant': 4718, 'short-pant': 2710, 'coat': 10116, 'skirt': 7130 }
import numpy as np import trimesh from smpl_torch import SMPLNP from utils.rotation import get_Apose from utils.ios import read_pc2 from global_var import ROOT if __name__ == '__main__': garment_class = 'skirt' gender = 'female' lowest = -2 STABILITY_FRAMES = 2 smpl = SMPLNP(gender) apose = torch.from_numpy(get_Apose().astype(np.float32)) data_root = osp.join(ROOT, '{}_{}'.format(garment_class, gender)) pose_dir = osp.join(ROOT, '{}_{}'.format(garment_class, gender), 'pose') ss_dir = osp.join(data_root, 'style_shape') shape_dir = osp.join(data_root, 'shape') beta_strs = [k.replace('.obj', '') for k in os.listdir(shape_dir) if k.endswith('.obj')] betas = np.load(osp.join(data_root, 'shape', 'betas.npy')) all_ss = [k for k in os.listdir(pose_dir) if len(k) == 7] for ss in all_ss: beta_str, gamma_str = ss.split('_') pose_ss_dir = osp.join(pose_dir, ss) if garment_class in ['pant', 'skirt', 'short-pant']: transition_path = osp.join(ss_dir, f'motion_beta{beta_str}_gamma{gamma_str}.pc2')
def gen_pose(pose_num, betas, nfold=1, div_thresh=0.1, DEBUG=False, gender='neutral', intersection=True, garment_class=None): """ if beta is not None, we will discard frames with self-intersection """ t0 = time.time() apose = get_Apose() smpl = SMPLNP_Lres(gender=gender) if garment_class is None: faces = smpl.base.faces else: faces = part_body_faces(garment_class) dataset = Dataset() data_num = len(dataset) poses = np.copy(dataset.poses) beta_num = len(betas) if intersection: all_verts = [] for beta in betas: verts = smpl(np.tile(np.expand_dims(beta, 0), [poses.shape[0], 1]), poses, batch=True) all_verts.append(verts) good_poses = [] for pi in tqdm(range(len(poses))): p = poses[pi] no_intersec = True for beta_idx in range(beta_num): v = all_verts[beta_idx][pi] if is_intersec(v, faces): no_intersec = False break if no_intersec: good_poses.append(p) poses = np.array(good_poses) data_num = poses.shape[0] if 0 < pose_num < data_num: data_num = pose_num * nfold random_idx = np.arange(data_num) np.random.shuffle(random_idx) random_idx = random_idx[:data_num] poses = poses[random_idx] all_poses = np.copy(poses) all_data_num = data_num npose_pfold = int(np.ceil(1. * all_data_num / nfold)) all_thetas = [] all_pose_orders = [] for fold_i in range(nfold): poses = np.copy(all_poses[fold_i * npose_pfold:(fold_i + 1) * npose_pfold]) data_num = len(poses) verts, joints = smpl(np.tile(np.expand_dims(betas[0] * 0, 0), [data_num, 1]), poses, batch=True, return_J=True) _, apose_joints = smpl(betas[0] * 0, apose, return_J=True) pose_num = joints.shape[0] chosen_mask = np.zeros([joints.shape[0]], dtype=np.bool) dist = calc_dis(joints, joints, garment_class) a_dist = calc_dis(np.expand_dims(apose_joints, 0), joints, garment_class)[0] closest = np.argmin(a_dist) chosen_mask[closest] = True pose_order = [-2, closest] dist_path = [a_dist[closest]] thetas = [apose, poses[closest]] print(pose_num) for c in tqdm(range(pose_num - 1)): last_idx = pose_order[-1] cur_dist = dist[last_idx] cur_dist[np.where(chosen_mask)] = np.inf closest = np.argmin(cur_dist) d = cur_dist[closest] finished = False if d > div_thresh: if not intersection: div_num = int(d / div_thresh) inter_poses = interpolate_pose(poses[last_idx], poses[closest], div_num) inter_poses = inter_poses[1:-1] else: cur_dist_copy = np.copy(cur_dist) while True: closest = np.argmin(cur_dist_copy) d = cur_dist_copy[closest] if np.isinf(d): finished = True break cur_dist_copy[closest] = np.inf # interpolate and see if there's self-intersection div_num = int(d / div_thresh) inter_poses = interpolate_pose(poses[last_idx], poses[closest], div_num) inter_poses = inter_poses[1:-1] all_verts = [] for beta in betas: vs = smpl(np.tile(np.expand_dims(beta, 0), [len(inter_poses), 1]), inter_poses, batch=True) all_verts.append(vs) intersec = False for vs in all_verts: for v in vs: if is_intersec(v, faces): intersec = True break if intersec: break # if there's self-intersection, we should find a second closest pose. Otherwise, break the loop if not intersec: break # print(c) if not finished: for dd in range(div_num): pose_order.append(-1) dist_path.append(-1) thetas.append(inter_poses[dd]) if not finished: chosen_mask[closest] = True pose_order.append(closest) dist_path.append(cur_dist[closest]) thetas.append(poses[closest]) else: break pose_order = np.array(pose_order) thetas = np.array(thetas) dur = time.time() - t0 print("theta num: {}".format(thetas.shape[0])) print("time: {} s".format(dur)) glob_pose_order = find_index(dataset.poses, thetas) all_thetas.append(thetas) all_pose_orders.append(glob_pose_order) return all_thetas, all_pose_orders
TEST = True for gender in genders: GEN_POSE = True POSE_NUM = 50 STABILITY_FRAMES = 2 if TEST: batch_num = 1 else: batch_num = 18 # 0.1 for upper clothes. 0.05 for lower clothes DIV_THRESH = 0.1 lowest = -2 smpl = SMPLNP_Lres(gender=gender) A_theta = get_Apose() num_betas = 10 if gender == 'neutral' else 300 root_dir = osp.join(ROOT, '{}_{}'.format(garment_class, gender)) # read betas and gammas betas = np.load(osp.join(root_dir, 'shape', 'betas.npy')) gammas = np.load(osp.join(root_dir, 'style', 'gammas.npy')) for beta_i, beta in enumerate(betas): save_dir = os.path.join(root_dir, 'pose', 'beta_{:03d}'.format(beta_i)) if not os.path.exists(save_dir): os.makedirs(save_dir) pose_label_paths = [