def construct_matrices(self): """ Construct FEM matrices """ V = p2e(self.vertices) F = p2e(self.faces) # Compute gradient operator: #F*3 by #V G = igl.eigen.SparseMatrixd() L = igl.eigen.SparseMatrixd() M = igl.eigen.SparseMatrixd() N = igl.eigen.MatrixXd() A = igl.eigen.MatrixXd() igl.grad(V, F, G) igl.cotmatrix(V, F, L) igl.per_face_normals(V, F, N) igl.doublearea(V, F, A) igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M) G = e2p(G) L = e2p(L) N = e2p(N) A = e2p(A) M = e2p(M) M = M.data # Compute latitude and longitude directional vector fields NS = np.reshape(G.dot(self.lat), [self.nf, 3], order='F') EW = np.cross(NS, N) # Compute F2V matrix (weigh by area) # adjacency i = self.faces.ravel() j = np.arange(self.nf).repeat(3) one = np.ones(self.nf * 3) adj = sparse.csc_matrix((one, (i, j)), shape=(self.nv, self.nf)) tot_area = adj.dot(A) norm_area = A.ravel().repeat(3) / np.squeeze(tot_area[i]) F2V = sparse.csc_matrix((norm_area, (i, j)), shape=(self.nv, self.nf)) # Compute interpolation matrix if self.level > 0: intp = self.intp[self.nv_prev:] i = np.concatenate( (np.arange(self.nv), np.arange(self.nv_prev, self.nv))) j = np.concatenate((np.arange(self.nv_prev), intp[:, 0], intp[:, 1])) ratio = np.concatenate( (np.ones(self.nv_prev), 0.5 * np.ones(2 * intp.shape[0]))) intp = sparse.csc_matrix((ratio, (i, j)), shape=(self.nv, self.nv_prev)) else: intp = sparse.csc_matrix(np.eye(self.nv)) # Compute vertex mean matrix self.G = G # gradient matrix self.L = L # laplacian matrix self.N = N # normal vectors (per-triangle) self.NS = NS # north-south vectors (per-triangle) self.EW = EW # east-west vectors (per-triangle) self.F2V = F2V # map face quantities to vertices self.M = M # mass matrix (area of voronoi cell around node. for integration) self.Seq = self._rotseq(self.vertices) self.Intp = intp
def grad_fun(index, gt_transient, transient, v, f, opt): mesh = MESH() mesh.v = igl.eigen.MatrixXd(v) mesh.f = igl.eigen.MatrixXi(f) igl.per_face_normals(mesh.v, mesh.f, mesh.fn) igl.doublearea(mesh.v, mesh.f, mesh.doublearea) gradient = grad_collocate(index, gt_transient, transient, mesh, opt) return gradient
def render_all_fun(i, v, f, opt): mesh = MESH() mesh.v = igl.eigen.MatrixXd(v) mesh.f = igl.eigen.MatrixXi(f) igl.per_face_normals(mesh.v, mesh.f, mesh.fn) igl.doublearea(mesh.v, mesh.f, mesh.doublearea) transient = mesh_sampling_collocate(mesh, opt.lighting[i,:], opt.lighting_normal[i,:], opt) return transient
def render_all_fun(i, v, f, vn, opt): mesh = MESH() mesh.v = igl.eigen.MatrixXd(v) mesh.f = igl.eigen.MatrixXi(f) mesh.vn = vn igl.per_face_normals(mesh.v, mesh.f, mesh.fn) igl.doublearea(mesh.v, mesh.f, mesh.doublearea) if opt.method == 'n': transient = mesh_sampling_collocate(mesh, opt.lighting[int(i),:], opt.lighting_normal[int(i),:], opt) else: transient = stratified_mesh_sampling_collocate(mesh, opt.lighting[int(i),:], opt.lighting_normal[int(i),:], opt) return transient
def key_pressed(viewer, key, modifier): global V global U global F global L if key == ord('r') or key == ord('R'): U = V; elif key == ord(' '): # Recompute just mass matrix on each step M = igl.eigen.SparseMatrixd() igl.massmatrix(U,F,igl.MASSMATRIX_TYPE_BARYCENTRIC,M); # Solve (M-delta*L) U = M*U S = (M - 0.001*L) solver = igl.eigen.SimplicialLLTsparse(S) U = solver.solve(M*U) # Compute centroid and subtract (also important for numerics) dblA = igl.eigen.MatrixXd() igl.doublearea(U,F,dblA) print(dblA.sum()) area = 0.5*dblA.sum() BC = igl.eigen.MatrixXd() igl.barycenter(U,F,BC) centroid = igl.eigen.MatrixXd([[0.0,0.0,0.0]]) for i in range(0,BC.rows()): centroid += 0.5*dblA[i,0]/area*BC.row(i) U -= centroid.replicate(U.rows(),1) # Normalize to unit surface area (important for numerics) U = U / math.sqrt(area) else: return False # Send new positions, update normals, recenter viewer.data.set_vertices(U) viewer.data.compute_normals() viewer.core.align_camera_center(U,F) return True
def key_pressed(viewer, key, modifier): global V global U global F global L if key == ord('r') or key == ord('R'): U = V elif key == ord(' '): # Recompute just mass matrix on each step M = igl.eigen.SparseMatrixd() igl.massmatrix(U, F, igl.MASSMATRIX_TYPE_BARYCENTRIC, M) # Solve (M-delta*L) U = M*U S = (M - 0.001 * L) solver = igl.eigen.SimplicialLLTsparse(S) U = solver.solve(M * U) # Compute centroid and subtract (also important for numerics) dblA = igl.eigen.MatrixXd() igl.doublearea(U, F, dblA) print(dblA.sum()) area = 0.5 * dblA.sum() BC = igl.eigen.MatrixXd() igl.barycenter(U, F, BC) centroid = igl.eigen.MatrixXd([[0.0, 0.0, 0.0]]) for i in range(0, BC.rows()): centroid += 0.5 * dblA[i, 0] / area * BC.row(i) U -= centroid.replicate(U.rows(), 1) # Normalize to unit surface area (important for numerics) U = U / math.sqrt(area) else: return False # Send new positions, update normals, recenter viewer.data.set_vertices(U) viewer.data.compute_normals() viewer.core.align_camera_center(U, F) return True
# Load a mesh in OFF format igl.readOFF("../../tutorial/shared/cow.off", V, F) # Compute Laplace-Beltrami operator: #V by #V igl.cotmatrix(V,F,L) # Alternative construction of same Laplacian G = igl.eigen.SparseMatrixd() K = igl.eigen.SparseMatrixd() # Gradient/Divergence igl.grad(V,F,G); # Diagonal per-triangle "mass matrix" dblA = igl.eigen.MatrixXd() igl.doublearea(V,F,dblA) # Place areas along diagonal #dim times T = (dblA.replicate(3,1)*0.5).asDiagonal() * 1 # Laplacian K built as discrete divergence of gradient or equivalently # discrete Dirichelet energy Hessian temp = -G.transpose() K = -G.transpose() * T * G print("|K-L|: ",(K-L).norm()) def key_pressed(viewer, key, modifier): global V global U
# Load meshes in OFF format igl.readOBJ(TUTORIAL_SHARED_PATH + "horse_quad.obj", V, F) # Count the number of irregular vertices, the border is ignored irregular = igl.is_irregular_vertex(V, F) vertex_count = V.rows() irregular_vertex_count = sum(irregular) irregular_ratio = irregular_vertex_count / vertex_count print("Irregular vertices: \n%d/%d (%.2f%%)\n" % (irregular_vertex_count, vertex_count, irregular_ratio * 100)) # Compute areas, min, max and standard deviation area = igl.eigen.MatrixXd() igl.doublearea(V, F, area) area /= 2.0 area_avg = area.mean() area_min = area.minCoeff() / area_avg area_max = area.maxCoeff() / area_avg area_ns = (area - area_avg) / area_avg area_sigma = math.sqrt(area_ns.squaredMean()) print("Areas (Min/Max)/Avg_Area Sigma: \n%.2f/%.2f (%.2f)\n" % (area_min, area_max, area_sigma)) # Compute per face angles, min, max and standard deviation angles = igl.eigen.MatrixXd() igl.internal_angles(V, F, angles) angles = 360.0 * (angles / (2 * math.pi))
import pymmgs import numpy as np import sys, os sys.path.insert(0, os.path.expanduser('~/Workspace/libigl/python')) import pyigl as igl import pyigl.eigen as Eigen from iglhelpers import p2e, e2p V = igl.eigen.MatrixXd() F = igl.eigen.MatrixXi() igl.read_triangle_mesh('/Users/zhongshi/1399_standing_clap_000010.obj', V, F) # SV, SVI, SVJ, SF = igl.eigen.MatrixXd(), igl.eigen.MatrixXi(), igl.eigen.MatrixXi(), igl.eigen.MatrixXi() # igl.remove_duplicate_vertices(V,F,1e-10, SV, SVI, SVJ, SF) M = igl.eigen.MatrixXd() igl.doublearea(V, F, M) M = e2p(M).flatten() # F0 = e2p(F)[np.where(M > 1e-9)[0],:] # npl = np.load('/Users/zhongshi/1006_jump_from_wall_000003.obj.npz') V0, F0 = e2p(V), e2p(F) # igl.writeOBJ('1399.obj',V, F) V, F = pymmgs.MMGS(V0, F0, 0.005) vw = igl.glfw.Viewer() vw.data().set_mesh(p2e(V), p2e(F)) vw.launch()
# Load a mesh in OFF format igl.readOFF("../../tutorial/shared/cow.off", V, F) # Compute Laplace-Beltrami operator: #V by #V igl.cotmatrix(V, F, L) # Alternative construction of same Laplacian G = igl.eigen.SparseMatrixd() K = igl.eigen.SparseMatrixd() # Gradient/Divergence igl.grad(V, F, G) # Diagonal per-triangle "mass matrix" dblA = igl.eigen.MatrixXd() igl.doublearea(V, F, dblA) # Place areas along diagonal #dim times T = (dblA.replicate(3, 1) * 0.5).asDiagonal() * 1 # Laplacian K built as discrete divergence of gradient or equivalently # discrete Dirichelet energy Hessian temp = -G.transpose() K = -G.transpose() * T * G print("|K-L|: ", (K - L).norm()) def key_pressed(viewer, key, modifier): global V
f = igl.eigen.MatrixXi() fn = igl.eigen.MatrixXd() vn = igl.eigen.MatrixXd() doublearea = igl.eigen.MatrixXd() mesh_location = '../mesh_processing/data/bunny.obj' mesh = MESH() #mesh.v = igl.eigen.MatrixXd([[-1,-1,0.9],[1, -1, 1],[1, 1, 1.2],[-1, 1, 1],[-2, -2, 1], [2,1, 1]]) #mesh.f = igl.eigen.MatrixXd([[0,2,1],[0, 3,2], [4,3,0], [1,2,5]]).castint() read_file = igl.readOBJ(mesh_location, mesh.v, mesh.f) igl.per_face_normals(mesh.v, mesh.f, mesh.fn) igl.per_vertex_normals(mesh.v, mesh.f, mesh.vn) igl.doublearea(mesh.v, mesh.f, mesh.doublearea) mesh.fn = np.array(mesh.fn) mesh.vn = np.array(mesh.vn) f = 0.5 z = -2 sensor = np.array([f, 0, z]) lighting = np.array([-f, 0, z]) sensor_normal = np.array([0, 0, 1]) lighting_normal = np.array([0, 0, 1]) opt = OPT() opt.normal = 'n' barycoord = rendering_igl.random_barycoord(mesh, opt.sample_num)
gt_mesh = MESH() [x, y] = np.meshgrid(np.linspace(-1, 1, 7), np.linspace(-1, 1, 7)) x = np.concatenate(x) y = np.concatenate(y) z = -0.5 + np.sqrt(4 - np.multiply(x, x) - np.multiply(y, y)) v = np.vstack((x, y, z)).T vn = -np.vstack((x, y, z + 0.5)).T / 2 tri = Delaunay(v[:, 0:2]) gt_mesh.vn = -np.vstack((x, y, z + 0.5)).T / 2 gt_mesh.f = igl.eigen.MatrixXi(tri.simplices[:, [0, 2, 1]]) gt_mesh.v = igl.eigen.MatrixXd(v) igl.per_face_normals(gt_mesh.v, gt_mesh.f, gt_mesh.fn) igl.doublearea(gt_mesh.v, gt_mesh.f, gt_mesh.doublearea) gt_mesh.fn = np.array(gt_mesh.fn) gt_render_opt = OPT(5000000) gt_render_opt.normal = 'n' tic = time.time() gt_transient = rendering.render_all_collocate(gt_mesh, gt_render_opt) print(time.time() - tic) filename = os.getcwd() + '/setup_3.mat' scipy.io.savemat(filename, mdict={ 'bin_width': gt_render_opt.distance_resolution, 'lighting': gt_render_opt.lighting, 'sensor': gt_render_opt.sensor,
# Load meshes in OFF format igl.readOBJ(TUTORIAL_SHARED_PATH + "horse_quad.obj", V, F) # Count the number of irregular vertices, the border is ignored irregular = igl.is_irregular_vertex(V, F) vertex_count = V.rows() irregular_vertex_count = sum(irregular) irregular_ratio = irregular_vertex_count / vertex_count print("Irregular vertices: \n%d/%d (%.2f%%)\n" % ( irregular_vertex_count, vertex_count, irregular_ratio * 100)) # Compute areas, min, max and standard deviation area = igl.eigen.MatrixXd() igl.doublearea(V, F, area) area /= 2.0 area_avg = area.mean() area_min = area.minCoeff() / area_avg area_max = area.maxCoeff() / area_avg area_ns = (area - area_avg) / area_avg area_sigma = math.sqrt(area_ns.squaredMean()) print("Areas (Min/Max)/Avg_Area Sigma: \n%.2f/%.2f (%.2f)\n" % ( area_min, area_max, area_sigma)) # Compute per face angles, min, max and standard deviation angles = igl.eigen.MatrixXd() igl.internal_angles(V, F, angles) angles = 360.0 * (angles / (2 * math.pi))
def optimization(lr): folder_name = os.getcwd() + '/progress3-%f/' % lr if not os.path.isdir(folder_name): os.mkdir(folder_name) filename = os.getcwd() + '/setup_4.mat' setup = scipy.io.loadmat(filename) gt_transient = setup['gt_transient'] gt_mesh = MESH() gt_mesh.v = igl.eigen.MatrixXd(torch.from_numpy(setup['gt_v']).numpy()) gt_mesh.f = igl.eigen.MatrixXi(torch.from_numpy(setup['gt_f']).numpy()) igl.per_face_normals(gt_mesh.v, gt_mesh.f, gt_mesh.fn) igl.doublearea(gt_mesh.v, gt_mesh.f, gt_mesh.doublearea) opt = OPT(5000) render_opt = OPT(50000) smooth_opt = SMOOTH_OPT() opt.space_carving_projection = 1 space_carving_location = os.getcwd() + '/space_carving_mesh4.obj' space_carving_mesh = MESH() igl.readOBJ(space_carving_location, space_carving_mesh.v, space_carving_mesh.f) mesh = MESH() mesh_init_location = os.getcwd() + '/cnlos_5.obj' igl.readOBJ(mesh_init_location, mesh.v, mesh.f) #rendering.space_carving_initialization(mesh, space_carving_mesh, opt) igl.per_face_normals(mesh.v, mesh.f, mesh.fn) igl.doublearea(mesh.v, mesh.f, mesh.doublearea) mesh_optimization = MESH() mesh_optimization.v = torch.from_numpy(np.array(mesh.v)) mesh_optimization.v.requires_grad_() l2, transient, original_l2 = rendering.evaluate_smooth_L2_collocate( gt_transient, mesh, render_opt, smooth_opt) print('%05d update time: %5.5f L2 loss: %5.5f old L2 loss: %5.5f' % (0, 0, l2, original_l2)) filename = folder_name + 'init.mat' scipy.io.savemat(filename, mdict={ 'f': np.array(mesh.f), 'v': np.array(mesh.v), 'optim_v': mesh_optimization.v.data.numpy(), 'gt_v': np.array(gt_mesh.v), 'transient': transient, 'l2': l2, 'gt_transient': gt_transient }) optimizer = optim.Adam([mesh_optimization.v], lr=lr) dummy_loss = torch.sum(mesh_optimization.v) dummy_loss.backward() T = 10 l2_record = np.empty(T) for t in range(T): if t % 30 == 0: if opt.w_width >= 10: opt.w_width -= 10 render_opt.w_width -= 10 opt.sample_num += 500 render_opt.sample_num += 5000 tic = time.time() optimizer.zero_grad() #grad = np.zeros((mesh.v.rows(),3)) #for index in range(opt.lighting.shape[0]): # grad += rendering.grad_collocate(index, gt_transient, transient, mesh, opt) grad = rendering.grad_parallel(gt_transient, transient, mesh, opt) grad += rendering.smooth_grad(mesh, smooth_opt) mesh_optimization.v.grad.data = torch.from_numpy(grad) optimizer.step() if opt.space_carving_projection == 1: mesh.v = rendering.space_carving_projection( mesh_optimization, space_carving_mesh) else: mesh.v = igl.eigen.MatrixXd(mesh_optimization.v.data.numpy()) igl.per_face_normals(mesh.v, mesh.f, mesh.fn) igl.doublearea(mesh.v, mesh.f, mesh.doublearea) l2, transient, original_l2 = rendering.evaluate_smooth_L2_collocate( gt_transient, mesh, render_opt, smooth_opt) print('%05d update time: %5.5f L2 loss: %5.5f old L2 loss: %5.5f' % (t, time.time() - tic, l2, original_l2)) l2_record[t] = l2 filename = folder_name + '%05d.mat' % (t) scipy.io.savemat(filename, mdict={ 'v': np.array(mesh.v), 'transient': transient, 'l2': l2, 'origin_v': mesh_optimization.v.data.numpy(), 'grad': mesh_optimization.v.grad.data.numpy(), 'w_width': opt.w_width }) mesh_optimization.v.data = torch.from_numpy(np.array(mesh.v)) filename = folder_name + 'loss_val.mat' scipy.io.savemat(filename, mdict={'l2': l2_record})