def naive_approach(pathes1, pathes2, r=9):
    """
    A naive approch at image warping. We justproject the vertices on both
    images and associate the corresponding pixels
    This methods only recover a small amount of pixels
    ----
    input:
        pathes1, pathes2: tuple containing 4 strings corresponding, in this
            order, to the path to the image, the keypoints .txt file, the mesh
            .obj file and the camera calibration folder
        r: int -> radius of the patch of pixels we copy when we find a match
    ----
    output:
        None
    """
    path_img1, path_kpt1, path_mesh1, path_cameras1 = pathes1
    path_img2, path_kpt2, path_mesh2, path_cameras2 = pathes2
    db1 = "BEE10" if "BEE10" in path_img1 else "Emily"
    db2 = "BEE10" if "BEE10" in path_img2 else "Emily"

    img1 = io.imread(path_img1)[..., :3]
    img2 = io.imread(path_img2)[..., :3]

    kpt1 = io_keypoints.recover_keypoints(path_kpt1, have_indices=False)
    kpt2 = io_keypoints.recover_keypoints(path_kpt2, have_indices=False)

    *_, tform_2_1 = mesh_helper.procrustes(kpt1[:27], kpt2[:27])

    v1, _ = igl.read_triangle_mesh(path_mesh1)
    v2, _ = igl.read_triangle_mesh(path_mesh2)

    cams1, *_ = tfm.get_info_cameras(path_cameras1, dataset=db1)
    cams2, *_ = tfm.get_info_cameras(path_cameras2, dataset=db2)

    cam1 = cams1[2]
    cam2 = cams2[5]

    M1, N1, _ = img1.shape
    M2, N2, _ = img2.shape
    new_img1 = np.zeros((M1, N1, 3), dtype=np.int)

    for k in range(len(v1)):
        pt1 = v1[k]
        pt2 = v2[k]

        y1, x1 = np.round(tfm.project_point(pt1, cam1)).astype(int)
        y2, x2 = np.round(tfm.project_point(pt2, cam2)).astype(int)

        if 0 <= x1 - r and x1 + r < M1 and 0 <= y1 - r and y1 + r < N1 and\
           0 <= x2 - r and x2 + r < M2 and 0 <= y2 - r and y2 + r < N2:
            new_img1[x1 - r: x1 + r + 1, y1 - r: y1 + r + 1] =\
                    img2[x2 - r: x2 + r + 1, y2 - r: y2 + r + 1]

    plt.figure()
    plt.imshow(new_img1 / new_img1.max())
    plt.axis("off")
    plt.show()
 def test_read_triangle_mesh(self):
     v, f = igl.read_triangle_mesh(self.test_path + "octopus-low.mesh")
     #print(v.shape, f.shape)
     v, f = igl.read_triangle_mesh(self.test_path + "face.obj")
     #print(v.shape, f.shape)
     v, f = igl.read_triangle_mesh(self.test_path + "bunny.off")
     #print(v.shape, f.shape)
     self.assertTrue(v.flags.c_contiguous)
     self.assertTrue(f.flags.c_contiguous)
Exemple #3
0
def is_manifold(file=None, faces=None):
    if file is not None:
        _, faces = igl.read_triangle_mesh(file, np.float64)
    if faces is None:
        print("Specify at least one of the parameters.")
        assert faces is not None
    return igl.extract_manifold_patches(faces)[0] == 1
def exp1(W, pt_index, mvt, pathes):
    """
    Moving one point with different weights
    ----
    input:
        W: float list of length N -> the different weights
        pt_index: int -> the index of the vertex we want to move
        mvt: float list of length 3 -> the shift we want to apply to the vertex
        pathes: 3-tuple -> path to the surfacic mesh, the volumetric .obj and
            the volunetric .mesh, in this order
    ----
    output:
        times: float array of shape (3, N) -> computation time for each mesh
            and for each weight
    """
    times = [[], [], []]

    v, f = igl.read_triangle_mesh(pathes[0])
    anchors = np.array([v[pt_index] + mvt], dtype=np.double)
    anchors_id = np.array([pt_index], dtype=np.int)

    for w in W:
        print("Experience 1, w = {}".format(w))

        t1 = time()
        v, f = lp_ed.laplacian_editing(pathes[0],
                                       anchors,
                                       anchors_id,
                                       tetra=False,
                                       custom_weight=[w])
        lp_ed.save_mesh("exp1_tri_w={}.obj".format(w), v, f)
        t2 = time()
        v, f = lp_ed.laplacian_editing(pathes[1],
                                       anchors,
                                       anchors_id,
                                       tetra=False,
                                       custom_weight=[w])
        lp_ed.save_mesh("exp1_tet_tri_w={}.obj".format(w), v, f)
        t3 = time()
        v, f = lp_ed.laplacian_editing(pathes[2],
                                       anchors,
                                       anchors_id,
                                       tetra=True,
                                       custom_weight=[w])
        lp_ed.save_mesh("exp1_tet_tet_w={}.obj".format(w), v, f)
        t4 = time()

        times[0].append(t2 - t1)
        times[1].append(t3 - t2)
        times[2].append(t4 - t3)
        dt1, dt2, dt3 = times[0][-1], times[1][-1], times[2][-1]
        print(f"tri: {dt1}s, tet_tri: {dt2}s, tet_tet: {dt3}s")

    print(times)
    print("Total time using tri:", sum(times[0]))
    print("Total time using tet_tri:", sum(times[1]))
    print("Total time using tet_tet:", sum(times[2]))

    return times
    def transform(self, v: np.ndarray, f: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:

        # nv, nf, _, _, _ = igl.offset_surface(v, f, 0, 64, SIGNED_DISTANCE_TYPE_PSEUDONORMAL)

        igl.write_triangle_mesh("/home/zgong8/temp/mc_tmp_in.obj", v, f)
        subprocess.run(["/home/zgong8/libigl/tutorial/build/bin/705_MarchingCubes", "/home/zgong8/temp/mc_tmp_in.obj", "/home/zgong8/temp/mc_tmp_out_1.obj", "/home/zgong8/temp/mc_tmp_out_2.obj"])
        nv, nf = igl.read_triangle_mesh("/home/zgong8/temp/mc_tmp_out_2.obj", np.float64)
        return nv, nf
Exemple #6
0
 def process_shape_file(self, in_file: str, out_file: str):
     assert self.is_full()
     vertices, faces = igl.read_triangle_mesh(in_file, np.float64)
     new_vertices, new_faces = self.process_shape_data(vertices, faces)
     if new_faces is not None:
         if len(new_faces) < max_output_faces:
             igl.write_triangle_mesh(out_file, new_vertices, new_faces)
             return True
         else:
             print("Too large, bad for connection, dropped in the end.")
     return False
Exemple #7
0
def manifold_object(in_path, out_path):
    temp_path = temp_obj
    v, f = igl.read_triangle_mesh(in_path)
    size = len(f)
    multiplier = size * 5
    subprocess.run(["./manifold", in_path, temp_path], cwd=refiner_path)
    subprocess.run([
        "./simplify", "-i", temp_path, "-o", out_path, "-m", "-f",
        str(multiplier)
    ],
                   cwd=refiner_path)
Exemple #8
0
    def __init__(self, meshPath=None, V=None, F=None, doNormalize=True):

        if V is None and F is None:
            if meshPath is not None:
                self.V, self.F = igl.read_triangle_mesh(meshPath)
            else:
                raise UserWarning(
                    "Incorrect usage of Mesh class. Either path to existing mesh (meshPath) must be given, or array of vertices(V) and faces(F)."
                )
        else:
            self.V = V
            self.F = F

        if doNormalize:
            self._normalizeMesh()
Exemple #9
0
def count_shape_net_components():
    total = 0
    counter = 0
    for in_file in iterate_shape_net():
        v, f = igl.read_triangle_mesh(in_file, np.float64)

        tm = trimesh.Trimesh(v, f)

        components = trimesh.graph.connected_components(tm.edges,
                                                        engine='scipy')
        num_of_components = len(components)

        if num_of_components > 1:
            counter += 1
        total += 1
    print(counter, "out of", total)
Exemple #10
0
def inner_surface(in_path, out_path, depth=1, nsteps=1):
    '''compute inner surfaces from mesh at in_path, save results'''
    # load input mesh
    v, f = igl.read_triangle_mesh(in_path)

    v2array = inner_surface_mesh(v, f, depth=depth, nsteps=nsteps)

    if nsteps == 1:
        igl.write_triangle_mesh(out_path, v2array[0], f, force_ascii=False)
    else:
        split = out_path.split(".")
        for step in range(nsteps):
            step_str = "%03i" % (step + 1)
            out_path_step = ".".join([*(split[:-2]), step_str, split[-1]])
            igl.write_triangle_mesh(out_path_step,
                                    v2array[step],
                                    f,
                                    force_ascii=False)
def init(file_name, env, **kwargs):
    def assign_neighbor_matrix(neighbors, v_id1, v_id2, v_id3):
        env.neighbors[v_id1, v_id2] = 1
        env.neighbors[v_id2, v_id1] = 1
        env.neighbors[v_id1, v_id3] = 1
        env.neighbors[v_id3, v_id1] = 1
        env.neighbors[v_id2, v_id3] = 1
        env.neighbors[v_id3, v_id2] = 1
        return neighbors

    if "V" in kwargs and "F" in kwargs:
        pass
    else:
        V, F = igl.read_triangle_mesh(file_name)  #TODO

    env.n = len(V)
    env.vertice = V
    env.vertice_prime = copy.deepcopy(V)
    env.faces = F
    env.neighbors = np.zeros([env.n, env.n])
    env.edge_matrix = np.zeros((env.n, env.n))
    env.cell_rotaion = np.zeros((env.n, env.n, 3))

    for i in range(env.n):
        env.verts_to_face.append([])

    for i, face in enumerate(env.faces):
        env.verts_to_face[env.face[0]].append(i)
        env.verts_to_face[env.face[1]].append(i)
        env.verts_to_face[env.face[2]].append(i)

        env.neighbors = assign_neighbor_matrix(
            env.neighbors, face[0], face[1],
            face[2])  #NxN      neighbor_matrix

    for row in range(env.n):
        env.edge_matrix[row][row] = env.neighbors[row].sum()

    return env
Exemple #12
0
    def poisson_recon(self,
                      cloud,
                      estimate_normals=True,
                      depth=6,
                      fulldepth=4,
                      knn=10):
        pymeshlab = self.mlab
        temp_dir = os.path.expanduser('~/.temp/meshlab/')
        sysutil.mkdirs(temp_dir)
        cloud_path = os.path.join(temp_dir, "cloud.pts")
        recon_path = os.path.join(temp_dir, "recon.ply")

        np.savetxt(cloud_path, cloud)

        ms = pymeshlab.MeshSet()
        ms.load_new_mesh(cloud_path)
        ms.compute_normals_for_point_sets(k=20)
        ms.surface_reconstruction_screened_poisson(depth=depth,
                                                   fulldepth=fulldepth)
        ms.save_current_mesh(recon_path)
        vert, face = igl.read_triangle_mesh(recon_path)
        return vert, face
def features_extractor(classes,DNA_size=50):
    """Extract the features from the samples in the dataset. The type of features is the ShapeDNA.

    :param classes: list
        list of the classes
    :param DNA_size: int
        size of the feature vector
    """
    print("\nFeature extraction")
    
    for c in classes:
        print(c)
        for file in os.listdir(os.path.join('.', 'Dataset', c)):
            if file.endswith(".off"):
                print("\t", file, end=" ... ")
                # Load mesh
                v, f = igl.read_triangle_mesh(os.path.join('.', 'Dataset',c, file))
                M = igl.massmatrix(v, f, igl.MASSMATRIX_TYPE_VORONOI)
                v = v / np.sqrt(M.sum())

                # Compute Laplacian
                L = -igl.cotmatrix(v, f)
                M = igl.massmatrix(v, f, igl.MASSMATRIX_TYPE_VORONOI)
                # Compute EigenDecomposition
                try:
                    evals, evecs = sp.sparse.linalg.eigsh(L, DNA_size+2, M, sigma=0.0, which='LM', maxiter=1e9, tol=1.e-15)
                except:
                    evals, evecs = sp.sparse.linalg.eigsh(L + 1e-8 * sp.sparse.identity(v.shape[0]), DNA_size+2,
                                                          M, sigma=0.0, which='LM', maxiter=1e9, tol=1.e-15)
                # Shape DNA
                descriptors = evals[2:] / evals[1]
                # Save descriptor
                np.save(os.path.join('.', 'Dataset', c, file[:-4] + "_DNA"), descriptors, allow_pickle=False)

                print("done.")
    print("Finished")
Exemple #14
0
# Add the igl library to the modules search path
import sys, os
sys.path.insert(0, os.getcwd() + "/../")

import igl

V = igl.eigen.MatrixXd()
F = igl.eigen.MatrixXi()
igl.read_triangle_mesh("../../tutorial/shared/fertility.off", V, F)

# Alternative discrete mean curvature
HN = igl.eigen.MatrixXd()
L = igl.eigen.SparseMatrixd()
M = igl.eigen.SparseMatrixd()
Minv = igl.eigen.SparseMatrixd()

igl.cotmatrix(V, F, L)
igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M)

igl.invert_diag(M, Minv)

# Laplace-Beltrami of position
HN = -Minv * (L * V)

# Extract magnitude as mean curvature
H = HN.rowwiseNorm()

# Compute curvature directions via quadric fitting
PD1 = igl.eigen.MatrixXd()
PD2 = igl.eigen.MatrixXd()
import igl
import meshplot
meshplot.offline()

import numpy as np

import os
root_folder = os.getcwd()

v, f = igl.read_triangle_mesh(
    os.path.join(root_folder, "data", "armadillo.obj"))

#sample points on a 64x64x64 grid
n = 64
K = np.linspace(-1.0, 1.0, n)
pts = np.array([[x, y, z] for x in K for y in K for z in K])

S, _, _ = igl.signed_distance(
    pts, v, f, sign_type=igl.SIGNED_DISTANCE_TYPE_FAST_WINDING_NUMBER)

nV, nF = igl.marching_cubes(S, pts, n, n, n, 0.0)

meshplot.plot(nV, nF)
import igl

V = igl.eigen.MatrixXd()
U = igl.eigen.MatrixXd()
F = igl.eigen.MatrixXi()

c = 0
bbd = 1.0
twod = False

if not igl.read_triangle_mesh("../tutorial/shared/beetle.off",V,F):
    print("failed to load mesh")

twod = V.col(2).minCoeff() == V.col(2).maxCoeff()
bbd = (V.colwiseMaxCoeff() - V.colwiseMinCoeff()).norm()

L = igl.eigen.SparseMatrixd()
M = igl.eigen.SparseMatrixd()

igl.cotmatrix(V,F,L)
L = -L
igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_DEFAULT,M)
k = 5

D = igl.eigen.MatrixXd()
if not igl.eigs(L,M,k+1,igl.EIGS_TYPE_SM,U,D):
    print("Eigs failed.")

U = (U-U.minCoeff())/(U.maxCoeff()-U.minCoeff());

viewer = igl.viewer.Viewer()
def better_approach(pathes1, pathes2, view_indices, r=4, path_assoc_tri=None):
    """
    A better approach to image warping using the following steps:
    1) Each face is projected on the first image
    2) We associate to each pixel the set of faces it is in
    3) For every pixel having at least one matching face, we compute the ray
        passing through it and find the intersection point to the closest
        matching face. We the compute its barycentric coordinates
    4) We find the point on the other mesh that has the same barycentric
        coordinates in the corresponding faces and project it onto its image
        plane
    5) The color of the projected point will be the one used for the initial
        pixel
    It also saves the mask of the first image as mask.png and the
    associated_triangles matrix as a .npy file
    ----
    input:
        pathes1, pathes2:tuple containing 4 strings corresponding, in this
            order, to the path to the image, the keypoints .txt file, the mesh
            .obj file and the camera calibration folder
        view_indices: two ints -> the indices of the views used
        r: int -> sampling ration on the image we want to tompute
        path_assoc_tri: str tuple of length 2 -> if the pixel-triangle
            association has already been computed for the two images, this is
            the path to the .npy files. If None, it is computed and saved
    ----
    output:
        new_img: a float array with shape image1.shape / r -> The face on
            image2 warped on image1
    """
    path_img1, path_kpt1, path_mesh1, path_cameras1 = pathes1
    path_img2, path_kpt2, path_mesh2, path_cameras2 = pathes2
    db1 = "BEE10" if "BEE10" in path_img1 else "Emily"
    db2 = "BEE10" if "BEE10" in path_img2 else "Emily"

    view_index1, view_index2 = view_indices

    img1 = io.imread(path_img1)[..., :3]
    img2 = io.imread(path_img2)[..., :3]

    M1, N1, _ = img1.shape
    M2, N2, _ = img2.shape

    cams1, _, r_vectors1, t_vectors1, _ = tfm.get_info_cameras(path_cameras1,
                                                               dataset=db1)
    cams2, _, r_vectors2, t_vectors2, _ = tfm.get_info_cameras(path_cameras2,
                                                               dataset=db2)

    cam1 = cams1[view_index1]
    cam2 = cams2[view_index2]

    rvec1, tvec1 = r_vectors1[view_index1], t_vectors1[view_index1]
    rvec2, tvec2 = r_vectors2[view_index2], t_vectors2[view_index2]

    # Step 1: projecting the faces

    v1, f1 = igl.read_triangle_mesh(path_mesh1)
    v2, f2 = igl.read_triangle_mesh(path_mesh2)

    v1_proj, *_ = tfm.project_landmarks(v1, cam1)
    v2_proj, *_ = tfm.project_landmarks(v2, cam2)

    triangles_2d1 = v1_proj[f1]
    triangles_2d2 = v2_proj[f2]

    # Step 2: associating pixels and triangles

    if path_assoc_tri is None:
        assoc_tri1 = compute_association_pixels_triangles(
            triangles_2d1, (M1, N1), r)
        assoc_tri2 = compute_association_pixels_triangles(
            triangles_2d2, (M2, N2), 1)

        print("Saving the file")

        path_save1 = f"assoc_{db1}_view{view_index1}_r={r}.npy"
        path_save2 = f"assoc_{db2}_view{view_index2}_r={1}.npy"
        save_associated_triangles(assoc_tri1, path_save1)
        save_associated_triangles(assoc_tri2, path_save2)
    else:
        assoc_tri1 = get_association_from_file(path_assoc_tri[0])
        assoc_tri2 = get_association_from_file(path_assoc_tri[1])

    save_mask(assoc_tri1)

    # Step 3: intersecting point and local coordinate

    # Some pre-processing

    cam_square1 = np.vstack((cam1, [0, 0, 0, 1]))
    cam_square2 = np.vstack((cam2, [0, 0, 0, 1]))
    cam_square_inv1 = np.linalg.inv(cam_square1)
    cam_square_inv2 = np.linalg.inv(cam_square2)

    R1 = cv2.Rodrigues(rvec1)[0]
    R2 = cv2.Rodrigues(rvec2)[0]
    camera_pos1 = -R1.T @ tvec1
    camera_pos2 = -R2.T @ tvec2

    new_img = np.zeros_like(img1[::r, ::r])

    print("Creating the warped image")

    for i in range(0, M1, r):
        if i % 500 == 0:
            print("Progress : {:.2f}%".format(i / M1 * 100))

        for j in range(0, N1, r):
            tri_indices = assoc_tri1[i // r, j // r]

            if len(tri_indices) > 0:
                projected_point_h = np.array([j, i, 1, 1], dtype=np.double)
                unprojected_h = cam_square_inv1 @ projected_point_h
                unprojected = tfm.from_homogeneous(unprojected_h)
                dir = unprojected - camera_pos1

                # Selecting the right face amongst the possible match

                triangle_index1, inter = find_the_right_face(
                    v1, f1, tri_indices, camera_pos1, dir)

                # Barycentric coordinates
                # See https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates
                p0, p1, p2 = v1[f1[triangle_index1]]
                denom = np.linalg.norm(np.cross(p1 - p0, p2 - p0))
                u = np.linalg.norm(np.cross(inter - p0, inter - p2)) / denom
                v = np.linalg.norm(np.cross(inter - p0, inter - p1)) / denom

                # Step 4: projecting the corresponding point on the other
                #           view/mesh onto its image plane

                p0_2, p1_2, p2_2 = v2[f2[triangle_index1]]
                inter_2 = p0_2 + u * (p1_2 - p0_2) + v * (p2_2 - p0_2)
                proj2 = np.round(tfm.project_point(inter_2, cam2))
                y, x = proj2.astype(np.int)

                projected_point_h = np.array([y, x, 1, 1], dtype=np.double)
                unprojected_h = cam_square_inv2 @ projected_point_h
                unprojected = tfm.from_homogeneous(unprojected_h)
                dir = unprojected - camera_pos2
                tri_indices = assoc_tri2[x, y]
                triangle_index2, _ = find_the_right_face(
                    v2, f2, tri_indices, camera_pos2, dir)

                # Step 5: coloring :)

                if triangle_index1 == triangle_index2 and in_bound(
                        proj2, (N2, M2)):
                    new_img[i // r, j // r] = img2[x, y]

    return new_img
 def load_mesh(self, obj_file):
     v, f = igl.read_triangle_mesh(str(obj_file))
     return v, f
# Add the igl library to the modules search path
import sys, os
sys.path.insert(0, os.getcwd() + "/../")

import igl

V = igl.eigen.MatrixXd()
U = igl.eigen.MatrixXd()
F = igl.eigen.MatrixXi()

c = 0
bbd = 1.0
twod = False

if not igl.read_triangle_mesh("../../tutorial/shared/beetle.off", V, F):
    print("failed to load mesh")

twod = V.col(2).minCoeff() == V.col(2).maxCoeff()
bbd = (V.colwiseMaxCoeff() - V.colwiseMinCoeff()).norm()

L = igl.eigen.SparseMatrixd()
M = igl.eigen.SparseMatrixd()

igl.cotmatrix(V, F, L)
L = -L
igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_DEFAULT, M)
k = 5

D = igl.eigen.MatrixXd()
if not igl.eigs(L, M, k + 1, igl.EIGS_TYPE_SM, U, D):
    print("Eigs failed.")
Exemple #20
0
import spheremesh as sh
import igl
import numpy as np

filename = "data/cell.obj"
l_max = 20

orig_v, faces = igl.read_triangle_mesh(filename)


sphere_verts = sh.conformal_flow(orig_v, faces)
sphere_verts = sh.mobius_center(orig_v,sphere_verts,faces)

orig_v, sphere_verts = sh.canonical_rotation(orig_v, sphere_verts, faces)

weights, Y_mat = sh.IRF(orig_v, sphere_verts, faces, l_max)

reconstruct = Y_mat.dot(weights)

## construct icosphere mesh data
ico_v, ico_f = igl.read_triangle_mesh("spheremesh/icosphere/icosphere.obj")
ico_v = sh.project_sphere(ico_v)
theta = np.arccos(ico_v[:,2])
phi = np.arctan2(ico_v[:,1],ico_v[:,0])

Y_mat2 = []

## make sh matrix
for l in range(0, l_max):
	for m in range(-l,l+1):
		y = sh.sph_real(l, m, phi, theta)
# Add the igl library to the modules search path
import sys, os
sys.path.insert(0, os.getcwd() + "/../")

import igl

V = igl.eigen.MatrixXd();
F = igl.eigen.MatrixXi();
igl.read_triangle_mesh("../../tutorial/shared/fertility.off", V, F);

# Alternative discrete mean curvature
HN = igl.eigen.MatrixXd()
L = igl.eigen.SparseMatrixd()
M = igl.eigen.SparseMatrixd()
Minv = igl.eigen.SparseMatrixd()


igl.cotmatrix(V,F,L)
igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_VORONOI,M)

igl.invert_diag(M,Minv)

# Laplace-Beltrami of position
HN = -Minv*(L*V)

# Extract magnitude as mean curvature
H = HN.rowwiseNorm()

# Compute curvature directions via quadric fitting
PD1 = igl.eigen.MatrixXd()
PD2 = igl.eigen.MatrixXd()
Exemple #22
0
import igl

import solver
import constraint
import transform
import open3d as o3d
import mesh as m

cons = constraint.Constraint()
cons.add_constraint(0, [0, 0, 0])
# slvr = solver.Sovler()

if __name__ == "__main__":
    V, F = igl.read_triangle_mesh("cube.obj")

    mesh = m.Mesh(V, F)

    slvr = solver.Sovler(mesh, cons)
    slvr.precompute()
    V, F = slvr.solve()

    igl.write_obj("cube_remake", V, F)
# 1. Install miniconda (python 3.7 version, windows 64 bits)
# 2. In a miniconda terminal run conda install igl
# 3. Swap to this python compiler in pycharm

import igl
import numpy as np
import os

#Change this to point to your subject folder
root_folder = '.'
subject_id_usr = os.path.join(root_folder, 'subjects folder', 'subject_01')

#Make sure you've at least simplified the mesh of the subject
vertices = np.load(os.path.join(subject_id_usr, 'vertices_simple.npy'))
faces = np.load(os.path.join(subject_id_usr, 'faces_simple.npy'))

ret = igl.write_triangle_mesh(os.path.join(subject_id_usr, "bunny_out.obj"),
                              vertices, faces)

v, f = igl.read_triangle_mesh(os.path.join(subject_id_usr, "bunny_out.obj"))
[pd1, pd2, pv1, pv2] = igl.principal_curvature(v, f, radius=5, use_k_ring=True)
#Mean curvature is (pv1+pv2)/2 and Gaussian curvature is pv1*pv2
# k = igl.gaussian_curvature(v, f)
np.save(os.path.join(subject_id_usr, 'mean_curv_simple.npy'), (pv1 + pv2) / 2)

#Deletes temporary object
os.remove(os.path.join(subject_id_usr, "bunny_out.obj"))
Exemple #24
0
        f_temp += np.ones_like(f_temp) * count_v
        count_v += len(v_temp)
        new_f[count_f:count_f + len(f_temp)] = f_temp
        new_fl[count_f:count_f + len(f_temp)] = np.ones(
            (len(f_temp), 1), dtype=int) * lb
        count_f += len(f_temp)
    return new_v, new_f, new_fl


file_bench = "3/00000008_9b3d6a97e8de4aa193b81000_trimesh_000.obj"
file_yml = "3/00000008_9b3d6a97e8de4aa193b81000_features_000.yml"
file_root = os.path.dirname(file_bench)
# wm.tetrahedralize("2/00000006_d4fe04f0f5f84b52bd4f10e4_trimesh_001.obj", file_root+"/"+"bench.mesh", stop_quality=7)
fl_bench_file = parse_feat(file_yml)
fl_bench = igl.read_dmat(fl_bench_file)
v_bench, f_bench = igl.read_triangle_mesh(file_bench)
v_ini, f_ini = igl.read_triangle_mesh("bench.mesh__sf.obj")
prob_mat_ini, fl_ini_temp = pbc.project_face_labels(v_bench,
                                                    f_bench.astype('int32'),
                                                    fl_bench.astype('int32'),
                                                    v_ini,
                                                    f_ini.astype('int32'))
fl_ini = pbc.refine_labels(v_ini, f_ini.astype('int32'), prob_mat_ini,
                           fl_ini_temp.astype('int32'), 1)
# mp.plot(v_ini, f_ini, fl_ini_temp[:,0])
# mp.plot(v_ini, f_ini, fl_ini[:,0])
eps = 0.1
# v_dict, f_dict =separate_surfaces(v_bench, f_bench, fl_bench)
v_dict, f_dict = separate_surfaces(v_ini, f_ini, fl_ini[:, 0])
v_bad, f_bad, fl_bad = perturb_and_union(v_dict, f_dict, eps)
# mp.plot(v_bad, f_bad, fl_bad[:,0], shading={"wireframe":True})
Exemple #25
0
    V_src_ = V_src/np.linalg.norm(V_src, axis=1)[:, np.newaxis]
    V_dst_ = V_dst/np.linalg.norm(V_dst, axis=1)[:, np.newaxis]
    dis, idx = KDTree(V_src_).query(V_dst_) 
    
    if unique == False: return idx

    unique_idx, inverse_idx = np.unique(idx, return_inverse=True)
    Vs, Ws = np.zeros((len(unique_idx), 3)), np.zeros(len(unique_idx))
    for i in range(len(V_dst)): 
        Vs[inverse_idx[i]] += V_dst[i]/(0.001+dis[i])
        Ws[inverse_idx[i]] += 1/(0.001+dis[i])
    Vs /= Ws[:, np.newaxis]

    return unique_idx.astype(np.int), Vs

sV3, sF3 = igl.read_triangle_mesh(__path__[0]+"/data/sphere3.obj")
sV5, sF5 = igl.read_triangle_mesh(__path__[0]+"/data/sphere5.obj")

def MinimalSurface(V, Nz, Iz, Al, Ar):
    Nz *= 1.05
    V_borders = border_approximate(Nz, Iz, Al, Ar)
    V = np.row_stack([Nz, Iz, Al, Ar, V_borders, V])
    b, bc =  contrl_vertices(sV3, V)
    b, bc =  contrl_vertices(sV5, bc)
    nilr_idx = contrl_vertices(sV5, np.row_stack([Nz, Iz, Al, Ar]), unique=False)

    V = igl.harmonic_weights(sV5, sF5, b, bc, 3)
    return V, sF5, bc, nilr_idx

def calibrate_nilr(Nz, Iz, Al, Ar):
    R = np.eye(3)
Exemple #26
0
print('Iteration: ', args.iteration)
print('The pre-trained weights: ', args.weight)
print('Source object: ', args.src)
print('Target object: ', args.tgt)
if args.if_nonrigid == 0:
    print('The translation is rigid.')
else:
    print('The translation is non-rigid.')

if __name__ == '__main__':
    if args.if_nonrigid == 1:
        rma_net = Net_PointNR_v2().cuda()
        # Load the pre-trained weights of RMA-Net
        rma_net.load_state_dict(torch.load(args.weight), True)
        # The testing samples
        source_points, _ = igl.read_triangle_mesh(args.src)
        target_points, _ = igl.read_triangle_mesh(args.tgt)
        source_points_tensor = torch.from_numpy(
            source_points).float().cuda().view(1, -1, 3)
        target_points_tensor = torch.from_numpy(
            target_points).float().cuda().view(1, -1, 3)
        print('Start to deform ' + args.src + ' to ' + args.tgt)
        with torch.no_grad():
            phi_list, point_weight_list, deform_rigid_points_list, deformation_points_list, rigid_matrix_list = rma_net(
                source_points_tensor,
                target_points_tensor,
                iteration=args.iteration)
        results_path = args.src[:-4] + '_deform_results'
        if not os.path.exists(results_path):
            os.mkdir(results_path)
        for stage in range(args.iteration):
Exemple #27
0
import spheremesh as sh
import igl
import numpy as np
from numpy.linalg import norm

filename = "data/cell.obj"
l_max = 24

orig_v, faces = igl.read_triangle_mesh(filename)

sphere_verts = sh.conformal_flow(orig_v, faces)
sphere_verts = sh.mobius_center(orig_v, sphere_verts, faces)

orig_v, sphere_verts = sh.canonical_rotation(orig_v, sphere_verts, faces)

weights, Y_mat = sh.IRF(orig_v, sphere_verts, faces, l_max)

reconstruct = Y_mat.dot(weights)

p = sh.plot.new()
sh.plot.mesh(p, orig_v, faces)


def set_max(value):
    res = int(value)**2
    res2 = int(value + 1)**2
    ww = np.zeros(weights.shape[0])

    ww[0:res] = 1
    ww[res:res2] = 1
 def test_read_triangle_mesh_type_issue(self):
     v, f = igl.read_triangle_mesh(self.test_path + "face.obj")
     vs = np.array([0], dtype = f.dtype)
     vt = np.arange(v.shape[0], dtype = f.dtype)
     d = igl.exact_geodesic(v, f, vs, vt)
Exemple #29
0
def laplacian_editing(path, anchors, anchors_id, tetra=False,
                      custom_weight=None):
    """
    Applies laplacian mesh editing to a mesh using igl's cotangent weights
    ----
    input:
        path: str -> path to the triangle mesh
        anchors: float array of shape (n, 3) -> position of the anchors
        anchors_id: float array of shape (n,) -> index of each anchor vertex
        tetra: bool -> if the mesh is tetraedral. If False, it should be with
            triangular faces
        custom_weight: float list of length n. If None, every weight is
            considered to be 1
    ----
    output:
        v_res: float array of shape (N, 3) -> the new vertices
        f: float array of shape (P, 3) -> the faces (same as before)
    """
    nb_anchors = len(anchors)
    assert nb_anchors == len(anchors_id), "anchors and anchors_id have \
different size"

    extension = path.split('.')[-1]

    weight_anchors = 1.0

    if extension == "mesh":
        v, vo, f = igl.read_mesh(path)
        f = f - 1
        # When using read_mesh, vertex indices start at 1 instead of 0
        # We could use read_triangle_mesh which returns vertices with indices
        # starting at 0
    elif extension == "obj":
        v, f = igl.read_triangle_mesh(path)
    else:
        raise ValueError("Currently, only .obj and .mesh files are supported")

    if tetra:
        assert extension == "mesh", "Laplacian editing for tetraedral mesh is\
 currently only supported for .mesh files"
        L = igl.cotmatrix(v, vo)
    else:
        L = igl.cotmatrix(v, f)

    M, N = L._shape  # M should be equal to N

    delta = np.array(L.dot(v))

    # The lines that will be appened to L and delta
    anchors_L = sparse.csc_matrix((nb_anchors, N))
    anchors_delta = np.zeros((nb_anchors, 3), dtype=np.double)
    for k in range(nb_anchors):
        if custom_weight is None:
            anchors_L[k, anchors_id[k]] = weight_anchors
            anchors_delta[k] = weight_anchors * anchors[k]
        else:
            anchors_L[k, anchors_id[k]] = custom_weight[k]
            anchors_delta[k] = custom_weight[k] * anchors[k]

    L = sparse.vstack((L, anchors_L), format="coo")
    delta = np.vstack((delta, anchors_delta))

    # Solving for least squares
    v_res = np.zeros((M, 3), dtype=np.double)
    for k in range(3):
        v_res[:, k] = lsqr(L, delta[:, k], x0=v[:, k])[0]

    return v_res, f
Exemple #30
0
               opacity=0.6)


def draw_cpc_wireframe(p: pv.Plotter, V: np.ndarray, n=10):
    for i in np.linspace(0, 100, n + 1, dtype=np.int)[1:-1] - 1:
        p.add_mesh(polyline_from_points(V[i, :]), color=wireframe_color)
    for j in np.linspace(0, 100, n + 1, dtype=np.int)[1:-1] - 1:
        p.add_mesh(polyline_from_points(V[:, j]), color=wireframe_color)


def draw_orient_definition(p: pv.Plotter, V: np.ndarray, N: np.ndarray):
    pass


if __name__ == "__main__":
    V, F = igl.read_triangle_mesh("./data/12034_CPC.obj")
    N = igl.per_vertex_normals(V, F,
                               igl.PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA)
    T, N, B = CPCScalpRecons.TNBFrame.TNB_frame(V, N, cpc_ratio=99)
    scalp = pv.PolyData()
    scalp.points, scalp.faces = V, np.column_stack(
        [np.full((len(F), 1), 3), F])

    p = pv.Plotter()
    # p.add_text("Scalp TBN Frame", font_size=18)
    scalp_ = p.add_mesh(scalp,
                        ambient=0.06,
                        diffuse=0.75,
                        opacity=1,
                        color=(1., 0.8, 0.7))  #, scalars="yz_dot", cmap="jet")
Exemple #31
0
import os
import numpy as np
import igl
from PyQt5.QtWidgets import QApplication
from PyIGL_viewer import Viewer

script_folder = os.path.dirname(__file__)
path_to_obj_file = os.path.join(script_folder, "assets", "cube.obj")
vertices, faces = igl.read_triangle_mesh(path_to_obj_file)

viewer_app = QApplication(["IGL viewer"])
viewer = Viewer()
viewer.show()

# The stretch values give the relative size of the different viewer widgets
# By setting them all to 1, we make sure our widgets all have the same dimensions.
viewer.set_column_stretch(0, 1)
viewer.set_column_stretch(1, 1)
viewer.set_row_stretch(0, 1)
viewer.set_row_stretch(1, 1)


def screenshot_function():
    viewer.save_screenshot(os.path.join("screenshot.png"))


# Linking all cameras means that all widgets will have the same point of view.
def toggle_linking():
    if viewer.linked_cameras:
        viewer.unlink_all_cameras()
    else:
def max_test():
    v, f = igl.read_triangle_mesh(path, np.float64)
    df = SubdivisionDeformer({STEPS: 1})
    for i in range(20):
        print(i, len(f))
        v, f = df.transform(v, f)