def cut_from_shoulder(display=False): smpl = get_tpose_smpl() verts = smpl.vertices.detach().cpu().numpy().squeeze() faces = smpl.faces ms = Mesh(v=verts, f=faces) col = np.zeros(verts.shape[0]) col[verts[:, 1] > 0.15] = 1 if display: ms.set_vertex_colors_from_weights(col) ms.show() np.save('from_shoulder_idx.npy', np.where(col)[0]) print('from_shoulder ', np.where(col)[0].shape) return col
def cut_head(display=False): smpl = get_tpose_smpl() verts = smpl.r faces = smpl.f ms = Mesh(v=verts, f=faces) col = np.zeros(verts.shape[0]) col[verts[:, 1] > 0.3] = 1 if display: ms.set_vertex_colors_from_weights(col) ms.show() print('head ', np.where(col)[0].shape) return col
def run(self, beta=None, theta=None, garment_d=None, garment_class=None): """Outputs body and garment of specified garment class given theta, beta and displacements.""" if beta is not None: self.smpl_base.betas[:beta.shape[0]] = beta else: self.smpl_base.betas[:] = 0 if theta is not None: self.smpl_base.pose[:] = theta else: self.smpl_base.pose[:] = 0 self.smpl_base.v_personal[:] = 0 if garment_d is not None and garment_class is not None: if 'skirt' not in garment_class: vert_indices = self.class_info[garment_class]['vert_indices'] f = self.class_info[garment_class]['f'] self.smpl_base.v_personal[vert_indices] = garment_d garment_m = Mesh(v=self.smpl_base.r[vert_indices], f=f) else: vert_indices = self.class_info[garment_class]['vert_indices'] f = self.class_info[garment_class]['f'] verts = self.smpl_base.v_poseshaped[vert_indices] + garment_d verts_h = ch.hstack((verts, ch.ones((verts.shape[0], 1)))) verts = ch.sum(self.smpl_base.V.T[vert_indices] * verts_h.reshape(-1, 4, 1), axis=1)[:, :3] # if theta is not None: # rotmat = self.smpl_base.A.r[:, :, 0] # verts_homo = np.hstack( # (verts, np.ones((verts.shape[0], 1)))) # verts = verts_homo.dot(rotmat.T)[:, :3] garment_m = Mesh(v=verts, f=f) else: garment_m = None self.smpl_base.v_personal[:] = 0 body_m = Mesh(v=self.smpl_base.r, f=self.smpl_base.f) return body_m, garment_m
def test(): name = join('assets/rp_eric_rigged_005_zup_a_smpl.obj') # Load SMPL params dat = pkl.load(open(name.replace('_smpl.obj', '_param.pkl'), 'rb'), encoding='latin-1') vsmpl = VolumetricSMPL('assets/volumetric_smpl_function_64', 'cuda', 'male') '''Sanity check: transform SMPL vertices using SMPL and VolumetricSMPL''' corr = init_SMPL('male', dat) corr.pose[:] = 0 corr.trans[:] = 0 corr.betas[:] = 0 p = torch.tensor([corr.r.astype('float32')] * 2).to('cuda') b = torch.tensor([dat['betas'][:10].astype('float32')] * 2).to('cuda') po = torch.tensor([dat['pose'].astype('float32')] * 2).to('cuda') t = torch.tensor([dat['trans'].astype('float32')] * 2).to('cuda') ptr = vsmpl(p, po, b, t) Mesh(ptr[0].cpu().numpy(), []).write_ply('assets/test.ply') corr = init_SMPL('male', dat) Mesh(corr.r, corr.f).write_ply('assets/org.ply') print('Done')
def cut_left_upperarm(display=False): smpl = get_tpose_smpl() verts = smpl.r faces = smpl.f ms = Mesh(v=verts, f=faces) col = np.zeros(verts.shape[0]) col[(verts[:, 0] <= 0.4) & (verts[:, 0] > 0.2)] = 1 if display: ms.set_vertex_colors_from_weights(col) ms.show() print('left_upperarm ', np.where(col)[0].shape) return col
def cut_left_hand(display=False): smpl = get_tpose_smpl() verts = smpl.vertices.detach().cpu().numpy().squeeze() faces = smpl.faces ms = Mesh(v=verts, f=faces) col = np.zeros(verts.shape[0]) col[verts[:, 0] > 0.69] = 1 # left hand if display: ms.set_vertex_colors_from_weights(col) ms.show() np.save('smpl_left_hand_idx.npy', np.where(col)[0]) print('left_hand ', np.where(col)[0].shape) return col
def cut_right_midarm(display=False): smpl = get_tpose_smpl() verts = smpl.vertices.detach().cpu().numpy().squeeze() faces = smpl.faces ms = Mesh(v=verts, f=faces) col = np.zeros(verts.shape[0]) col[(verts[:, 0] >= -0.6) & (verts[:, 0] < -0.4)] = 1 if display: ms.set_vertex_colors_from_weights(col) ms.show() print('right_midarm ', np.where(col)[0].shape) return col
def vis_offsets_debug(self, offsetsList, posePara, row=1, col=2): """visualize the offsets in the give pose; for debug.""" assert len(offsetsList ) == row * col, 'please set row and col to display meshes.' bodyList = [] for offset in offsetsList: if offset.shape[0] > 6890: smpl = smplFromParas(self.hresSMPL, offset, posePara[0], posePara[1], posePara[2]) hresbody = Mesh(smpl.r, smpl.f) bodyList.append(hresbody) else: smpl = smplFromParas(self.stdSMPL, offset, posePara[0], posePara[1], posePara[2]) stdbody = Mesh(smpl.r, smpl.f) bodyList.append(stdbody) mvs = MeshViewers((row, col)) for r in range(row): for c in range(col): mvs[r][c].set_static_meshes([bodyList[r * col + c]])
def cut_right_foot(display=False): smpl = get_tpose_smpl() verts = smpl.vertices.detach().cpu().numpy().squeeze() faces = smpl.faces ms = Mesh(v=verts, f=faces) col = np.zeros(verts.shape[0]) col[(verts[:, 1] < -1) & (verts[:, 0] < 0)] = 1 if display: ms.set_vertex_colors_from_weights(col) ms.show() np.save('smpl_right_foot_idx.npy', np.where(col)[0]) print('right_foot ', np.where(col)[0].shape) return col
def construct_geometric_object(obj_fp, offset): mesh = Mesh(filename=obj_fp) obj = go.Mesh3d(x=mesh.v[:, 0] + offset[0], y=mesh.v[:, 1] + offset[1], z=mesh.v[:, 2] + offset[2], colorbar_title='z', colorscale=[[0, 'gold'], [0.5, 'mediumturquoise'], [1, 'magenta']], intensity=mesh.v[:, 2], i=mesh.f[:, 0], j=mesh.f[:, 1], k=mesh.f[:, 2], showscale=True) return obj
def cut_upper_left_leg(display=False): smplx = get_tpose_smplx() verts = smplx.vertices.detach().cpu().numpy().squeeze() faces = smplx.faces ms = Mesh(v=verts, f=faces) col = np.zeros(verts.shape[0]) col[(verts[:, 1] < -0.44) & (verts[:, 0] >= 0) & (verts[:, 1] >= -0.84)] = 1 if display: ms.set_vertex_colors_from_weights(col) ms.show() print('upper_left_leg ', np.where(col)[0].shape) return col
def calc_laplacian(mesh): """ メッシュに対して Laplacian deformation での Laplacian を計算する """ # pytorch3d -> psbody.mesh への変換 mesh = Mesh(mesh.verts_packed().detach().cpu().numpy(), mesh.faces_packed().detach().cpu().numpy()) # メッシュを頂点連結関係を取得? connectivity = get_vert_connectivity(mesh) # connectivity is a sparse matrix, and np.clip can not applied directly on a sparse matrix. connectivity.data = np.clip(connectivity.data, 0, 1) laplacian = normalize(connectivity, norm='l1', axis=1) laplacian = sp.eye(connectivity.shape[0]) - laplacian return laplacian
def generate_transform_matrices(mesh, factors): factors = map(lambda x: 1.0 / x, factors) M, A, D, U = [], [], [], [] A.append(get_vert_connectivity(mesh.v, mesh.f)) M.append(mesh) for factor in factors: ds_f, ds_D = qslim_decimator_transformer(M[-1], factor=factor) D.append(ds_D) new_mesh_v = ds_D.dot(M[-1].v) new_mesh = Mesh(v=new_mesh_v, f=ds_f) M.append(new_mesh) A.append(get_vert_connectivity(new_mesh.v, new_mesh.f)) U.append(setup_deformation_transfer(M[-1], M[-2])) return M, A, D, U
def main(mesh, sv_file, side, size, fmap_location, bmap_location, cam_file, gar_type): from opendr.camera import ProjectPoints from psbody.mesh import Mesh print(fmap_location) cam_data = pkl.load(open(cam_file, 'r')) cam_z, cam_y = cam_data[gar_type]['cam_z'], cam_data[gar_type]['cam_y'] mesh = Mesh(filename=mesh) fmap = np.load(fmap_location) bmap = np.load(bmap_location) cam = ProjectPoints(v=mesh.v, t=np.array([0, cam_y, cam_z]), rt=np.zeros(3), f=[1000, 1000], c=[1000 / 2., 1000 / 2.], k=np.zeros(5)) points = uv_to_xyz_and_normals(mesh, fmap, bmap) cam.v = points projection = cam.r.astype(np.int32) projection[projection > 999] = 999 projection = np.fliplr(np.around(projection.squeeze())).astype(np.int32) pixels_to_set = np.array(np.where(fmap != -1)).T x_to_set = pixels_to_set[:, 0] y_to_set = pixels_to_set[:, 1] cords_ret = -999 * np.ones((fmap.shape[0], fmap.shape[1], 2)) cords_ret[x_to_set, y_to_set, :] = projection cords_ret = cords_ret.astype('float64') cords_ret = 2 * ((cords_ret) / 999) - 1 cords_ret = np.flip(cords_ret, 2) if side == 'front': cords_ret = cords_ret[500:1500, 0:1000] else: cords_ret = cords_ret[500:1500, 1000:2000] cords_ret = cv2.resize(cords_ret, (size, size)) np.save(sv_file, cords_ret)
def computeOffsets_guided(self, coatPath: str, pantsPath: str, tarPara: list, subObj: Mesh = None, subTex: str = None, is_hres: bool = True): """use the N G M to compute the offset in t pose.""" smpl = self.hresSMPL.copy() if is_hres else self.stdSMPL.copy() splt = self.num_separation['hres' if is_hres else 'std'] ## per-vertex offsets v_offsets_t = np.zeros_like(smpl.r) ## Pants offset_pants_t = compute_offset_tPose(smpl, pantsPath, self.thresholds['pants'], splt, self.verbose_on) mask = np.linalg.norm(offset_pants_t, axis=1) > np.linalg.norm( v_offsets_t, axis=1) v_offsets_t[mask] = offset_pants_t[mask] ## coat # None for sub84 and others subs without coat in their folder if coatPath is not None: offset_coat_t = compute_offset_tPose(smpl, coatPath, self.thresholds['coats'], splt, self.verbose_on) mask = np.linalg.norm(offset_coat_t, axis=1) > np.linalg.norm( v_offsets_t, axis=1) v_offsets_t[mask] = offset_coat_t[mask] ## Dress body if self.verbose_on and subObj is not None: print('show mesh in self.computeOffsets_guided().') smpl = smplFromParas(smpl, v_offsets_t, tarPara[0], tarPara[1], tarPara[2]) dressed_body = Mesh(smpl.r, smpl.f) dressed_body.vt = subObj.vt dressed_body.ft = subObj.ft dressed_body.set_texture_image(subTex) mvs = MeshViewers((1, 1)) mvs[0][0].set_static_meshes([dressed_body]) return v_offsets_t
def split_garments(pca, mesh, vertex_label, gar): ''' Since garments are layered we do net get high frequency parts for invisible garment vertices. Hence we generate the base garment from pca predictions and add the hf term whenever available. :param pred_mesh: :param garments: :return: ''' vertex_label = vertex_label.reshape(-1,) base = pca_verts[config.garmentKeys[gar]].inverse_transform(pca).reshape(-1, 3) ind = np.where(TEMPLATE[config.garmentKeys[gar]][1])[0] gar_mesh = Mesh(mesh.v, mesh.f) gar_mesh.v[ind] = base gar_mesh.v[vertex_label] = mesh.v[vertex_label] gar_mesh.keep_vertices(ind) return gar_mesh
def to_mesh(self, point_color=name_to_rgb['red']): v = np.array([[-1., -1., -1.], [-1., -1., 1.], [-1., 1., 1.], [-1., 1., -1.], [-1., 1., -1.], [-1., 1., 1.], [1., 1., 1.], [1., 1., -1.], [1., 1., -1.], [1., 1., 1.], [1., -1., 1.], [1., -1., -1.], [-1., -1., 1.], [-1., -1., -1.], [1., -1., -1.], [1., -1., 1.], [1., -1., -1.], [-1., -1., -1.], [-1., 1., -1.], [1., 1., -1.], [1., 1., 1.], [-1., 1., 1.], [-1., -1., 1.], [1., -1., 1.]]) f = np.array([[0, 1, 2], [0, 2, 3], [4, 5, 6], [4, 6, 7], [8, 9, 10], [8, 10, 11], [12, 13, 14], [12, 14, 15], [16, 17, 18], [16, 18, 19], [20, 21, 22], [20, 22, 23]]) return Mesh(v=v * self.radius + self.center, f=f, vc=np.tile(point_color, (v.shape[0], 1)))
def __init__(self, model, name, dataset, data_dir, datadir_root, n_sample, save_obj, sample_option='normal', smpl_model_folder='', vis=True): self.n_sample = n_sample self.sample_option = sample_option self.name = name self.data_dir = data_dir self.datadir_root = datadir_root self.model = model self.dataset = dataset self.save_obj = save_obj self.vis = vis self.smpl_model = smplx.body_models.create( model_type='smpl', model_path=smpl_model_folder, gender='neutral') script_dir = os.path.dirname(os.path.realpath(__file__)) self.clothing_verts_idx = np.load( join(script_dir, 'data', 'clothing_verts_idx.npy')) self.ref_mesh = Mesh( filename=join(script_dir, 'data', 'template_mesh.obj')) self.minimal_shape = self.ref_mesh.v self.rot = np.load( join(script_dir, 'data', 'demo_data', 'demo_pose_params.npz'))['rot'] # 216 dim pose vector self.pose = np.load( join(script_dir, 'data', 'demo_data', 'demo_pose_params.npz'))['pose'] train_stats = np.load( join(script_dir, 'data', 'demo_data', 'trainset_stats.npz')) self.train_mean = train_stats['mean'] self.train_std = train_stats['std'] self.results_dir = join(script_dir, 'results', name) if not exists(self.results_dir): os.makedirs(self.results_dir)
def create_smplD_psbody(SMPL :Smpl, offsets_t :array, pose :array, betas :array, trans :array, rtnMesh :bool=True): ''' This function create a SMPLD body model and mesh from the given data. Parameters ---------- SMPL : Smpl SMPLD model. If None, create one. offsets_t : array The per-vertex offsets in t-pose representing garments. pose : array The axis angle of 23+1 joints describing the rotation of each joint. betas : array The body shape coefficients. trans : array The global translation of the body. rtnMesh : bool, optional If return the created mesh in the output. The default is True. Returns ------- out : TYPE List of SMPL model and corresponding mesh if required. ''' if SMPL is None: # create a new smplD model, res depends on offsets_t dp = SmplPaths() is_hres = offsets_t.shape[0]>6890 if isinstance(offsets_t, array) else False SMPL = Smpl( dp.get_hres_smpl_model_data() if is_hres else dp.get_smpl_file() ) SMPL.v_personal[:] = offsets_t SMPL.pose[:] = pose SMPL.betas[:] = betas SMPL.trans[:] = trans out = [SMPL] if rtnMesh: body = Mesh(SMPL.r, SMPL.f) out.append(body) return out
def on_step(verts, scale, faces, target_img, target_lmks, opt_lmks, lmk_dist=0.0, shape_reg=0.0, exp_reg=0.0, neck_pose_reg=0.0, jaw_pose_reg=0.0, eyeballs_pose_reg=0.0): import cv2 import sys import numpy as np from psbody.mesh import Mesh from utils.render_mesh import render_mesh if lmk_dist > 0.0 or shape_reg > 0.0 or exp_reg > 0.0 or neck_pose_reg > 0.0 or jaw_pose_reg > 0.0 or eyeballs_pose_reg > 0.0: print( 'lmk_dist: %f, shape_reg: %f, exp_reg: %f, neck_pose_reg: %f, jaw_pose_reg: %f, eyeballs_pose_reg: %f' % (lmk_dist, shape_reg, exp_reg, neck_pose_reg, jaw_pose_reg, eyeballs_pose_reg)) plt_target_lmks = target_lmks.copy() plt_target_lmks[:, 1] = target_img.shape[0] - plt_target_lmks[:, 1] for (x, y) in plt_target_lmks: cv2.circle(target_img, (int(x), int(y)), 4, (0, 0, 255), -1) plt_opt_lmks = opt_lmks.copy() plt_opt_lmks[:, 1] = target_img.shape[0] - plt_opt_lmks[:, 1] for (x, y) in plt_opt_lmks: cv2.circle(target_img, (int(x), int(y)), 4, (255, 0, 0), -1) if sys.version_info >= (3, 0): rendered_img = render_mesh(Mesh(scale * verts, faces), height=target_img.shape[0], width=target_img.shape[1]) for (x, y) in plt_opt_lmks: cv2.circle(rendered_img, (int(x), int(y)), 4, (255, 0, 0), -1) target_img = np.hstack((target_img, rendered_img)) cv2.imshow('img', target_img) cv2.waitKey(10)
def convert_smpl_seq2mesh(smpl_model_path, _pose, _transl, _beta, gender="female"): device = _pose.device smplh = SMPL2Mesh(smpl_model_path=smpl_model_path, gender=gender) smplh.to(device) smplh_model = smplh.smplh smplh_outputs = smplh.forward(_pose=_pose, _transl=_transl, _beta=_beta) faces = smplh_model.faces vertices = smplh_outputs.vertices.detach().to("cpu").numpy() meshes = [] for verts in vertices: mesh = Mesh(v=verts, f=faces) meshes.append(mesh) return meshes
def pose_garment(garment, vert_indices, smpl_params): ''' :param smpl_params: dict with pose, betas, v_template, trans, gender ''' dp = SmplPaths(gender=smpl_params['gender']) smpl = Smpl(dp.get_hres_smpl_model_data()) smpl.pose[:] = 0 smpl.betas[:] = smpl_params['betas'] # smpl.v_template[:] = smpl_params['v_template'] offsets = np.zeros_like(smpl.r) offsets[vert_indices] = garment.v - smpl.r[vert_indices] smpl.v_personal[:] = offsets smpl.pose[:] = smpl_params['pose'] smpl.trans[:] = smpl_params['trans'] mesh = Mesh(smpl.r, smpl.f).keep_vertices(vert_indices) return mesh
def output_meshes(meshes, epoch, config, samples=5): data = meshes[:samples].reshape(samples, -1, 6890, 3) bm_path = config['path']['body_models'] data_path = config['path']['processed_data'] vis_path = config['path']['visualization'] bm = np.load(os.path.join(bm_path, 'male/model.npz')) if not os.path.isdir(os.path.join(vis_path, 'epoch_{}'.format(epoch))): os.mkdir(os.path.join(vis_path, 'epoch_{}'.format(epoch))) for i in range(samples): for j in range(data.shape[1]): mesh = Mesh(v=data[i, j], f=bm['f']) mesh.write_ply( os.path.join(vis_path, 'epoch_{}/{}_{}.ply'.format(epoch, i, j)))
def convert_points_to_mesh(points, radius=0.02, colormap=cm.get_cmap("jet"), return_ps_mesh=False): sphere = trimesh.primitives.Sphere(radius=radius) new_mesh = trimesh.Trimesh() # new_mesh = [] for _, point in enumerate(points): new_sphere = trimesh.Trimesh(sphere.vertices + point, sphere.faces * 1) new_mesh += new_sphere # new_mesh.append(new_sphere) # color = colormap(px*1.0/ 20) # vc = trimesh.visual.color.VertexColor(color) if return_ps_mesh: new_mesh = Mesh(new_mesh.vertices, new_mesh.faces) return new_mesh
def inference(tf_model_fname, ds_fname, audio_fname, template_fname, condition_idx, out_path): template = Mesh(filename=template_fname) sample_rate, audio = wavfile.read(audio_fname) if audio.ndim != 1: print('Audio has multiple channels, only first channel is considered') audio = audio[:, 0] processed_audio = process_audio(ds_fname, audio, sample_rate) # Load previously saved meta graph in the default graph saver = tf.train.import_meta_graph(tf_model_fname + '.meta') graph = tf.get_default_graph() speech_features = graph.get_tensor_by_name( u'VOCA/Inputs_encoder/speech_features:0') condition_subject_id = graph.get_tensor_by_name( u'VOCA/Inputs_encoder/condition_subject_id:0') is_training = graph.get_tensor_by_name( u'VOCA/Inputs_encoder/is_training:0') input_template = graph.get_tensor_by_name( u'VOCA/Inputs_decoder/template_placeholder:0') output_decoder = graph.get_tensor_by_name(u'VOCA/output_decoder:0') num_frames = processed_audio.shape[0] feed_dict = { speech_features: np.expand_dims(np.stack(processed_audio), -1), condition_subject_id: np.repeat(condition_idx - 1, num_frames), is_training: False, input_template: np.repeat(template.v[np.newaxis, :, :, np.newaxis], num_frames, axis=0) } with tf.Session() as session: # Restore trained model saver.restore(session, tf_model_fname) predicted_vertices = np.squeeze(session.run(output_decoder, feed_dict)) output_sequence_meshes(predicted_vertices, template, out_path) tf.reset_default_graph()
def part_labelling(sampling_path, reg_path, name, out_path, sigma=0.05, ext=''): out_file = join( out_path, name + '_boundary_all_parts_sigma_{}_{}.npz'.format(sigma, ext)) if exists(out_file) and REDO is False: print('File already exists, ', out_file) return if not exists(sampling_path): print('sampling_path not found, ', sampling_path) return samp_dat = np.load(sampling_path) boundary_points = samp_dat['points'] # Load with psbody.mesh as trimesh changes the vertex ordering. Need to keep it same as when cutting SMPL parts. reg = Mesh(filename=reg_path) # Parts part_labels = pkl.load( open('/BS/bharat-3/work/IPNet/assets/smpl_parts_dense.pkl', 'rb')) labels = np.zeros((6890, ), dtype='int32') for n, k in enumerate(part_labels): labels[part_labels[k]] = n kdtree = KDTree(reg.v) _, vert_ids = kdtree.query(boundary_points) jidx = labels[vert_ids] if not exists(out_path): os.makedirs(out_path) np.savez(out_file, points=boundary_points, occupancies=samp_dat['occupancies'], grid_coords=samp_dat['grid_coords'], parts=jidx) print('Done part labelling, ', out_file)
def visualize(self, verts, mv=None): # Visualizes the laplacian. # Verts is B x N x 3 Variable Lx = self.Lx[0].data.cpu().numpy() V = verts[0].data.cpu().numpy() from psbody.mesh import Mesh F = self.laplacian.F_np[0] mesh = Mesh(V, F) weights = np.linalg.norm(Lx, axis=1) mesh.set_vertex_colors_from_weights(weights) if mv is not None: mv.set_dynamic_meshes([mesh]) else: mesh.show()
def visualize(self, verts, F_np, mv=None): from psbody.mesh import Mesh V = verts[0].data.cpu().numpy() mesh = Mesh(V, F_np) dist = self.dist[0].data.cpu().numpy() v_weights = np.zeros((V.shape[0])) for e_id, (v1_id, v2_id) in enumerate(zip(self.v1, self.v2)): v_weights[v1_id] += dist[e_id] v_weights[v2_id] += dist[e_id] mesh.set_vertex_colors_from_weights(v_weights) if mv is not None: mv.set_dynamic_meshes([mesh]) else: mesh.show() import ipdb; ipdb.set_trace()
def remove_interpenetration_fast(mesh, base, L=None): """ Laplacian can be cached. Computing laplacian takes 60% of the total runtime. """ import scipy.sparse as sp from scipy.sparse import vstack, csr_matrix from scipy.sparse.linalg import spsolve from psbody.mesh import Mesh eps = 0.001 ww = 2.0 nverts = mesh.v.shape[0] if L is None: L = laplacian(mesh) nearest_points, nearest_normals = get_nearest_points_and_normals( mesh.v, base.v, base.f) direction = np.sign( np.sum((mesh.v - nearest_points) * nearest_normals, axis=-1)) indices = np.where(direction < 0)[0] pentgt_points = nearest_points[indices] - mesh.v[indices] pentgt_points = nearest_points[indices] \ + eps * pentgt_points / \ np.expand_dims(0.0001 + np.linalg.norm(pentgt_points, axis=1), 1) tgt_points = mesh.v.copy() tgt_points[indices] = ww * pentgt_points rc = np.arange(nverts) data = np.ones(nverts) data[indices] *= ww I = csr_matrix((data, (rc, rc)), shape=(nverts, nverts)) A = vstack([L, I]) b = np.vstack((L.dot(mesh.v), tgt_points)) res = spsolve(A.T.dot(A), A.T.dot(b)) mres = Mesh(v=res, f=mesh.f) return mres
def __init__(self, plpath, batch_size=1, dtype=torch.float32): super(RigidObjectModel, self).__init__() trans = torch.tensor(np.zeros((batch_size, 3)), dtype=dtype, requires_grad=True) self.register_parameter('trans', nn.Parameter(trans, requires_grad=True)) root_orient = torch.tensor(np.zeros((batch_size, 3)), dtype=dtype, requires_grad=True) self.register_parameter('root_orient', nn.Parameter(root_orient, requires_grad=True)) mesh = Mesh(filename=plpath) self.rigid_v = torch.from_numpy( np.repeat(mesh.v[np.newaxis], batch_size, axis=0)).type(dtype) self.f = torch.from_numpy(mesh.f.astype(np.int32))