示例#1
0
文件: mapping.py 项目: gauzias/slam
def disk_conformal_mapping(mesh,
                           lap_type='conformal',
                           boundary=None,
                           boundary_coords=None):
    """
    Computes comformal mapping of a mesh to a disk, see the following references:
    Ulrich Pinkall and Konrad Polthier, “Computing Discrete Minimal Surfaces and
    Their Conjugates,” Experimental Mathematics, 1993, 1–33.
    and
    Mathieu Desbrun, Mark Meyer, and Pierre Alliez, “Intrinsic Parameterizations
    of Surface Meshes,” Computer Graphics Forum 21, no. 3 (2002): 209–18,
    https://doi.org/10.1111/1467-8659.00580.
    :param mesh: a trimesh object
    :param lap_type: type of mesh Laplacian to be used,
    see the function differential_geometry/compute_mesh_weights for more
    informations
    :param boundary: boundary of the mesh, resulting from the function
    topology/mesh_boundary
    :param boundary_coords: coordindates of the boundary vertices on the
    output disk, if None then uniform sampling
    :return: a trimesh object, planar disk representation of the input mesh
    """
    if boundary is None:
        boundary_t = stop.mesh_boundary(mesh)
        boundary = boundary_t[0]
    boundary = np.array(boundary)
    if boundary_coords is None:
        p = boundary.size
        t = np.arange(0, 2 * np.math.pi, (2 * np.math.pi / p))
        boundary_coords = np.array([np.cos(t), np.sin(t)])
    L, LB = sdg.compute_mesh_laplacian(mesh, lap_type=lap_type)
    Nv = len(mesh.vertices)  # np.array(mesh.vertex()).shape[0]
    print('Boundary Size:', boundary.shape)
    print('Laplacian Size:', L.shape)
    for i in boundary:
        L[i, :] = 0
        L[i, i] = 1
    L = L.tocsr()

    Rx = np.zeros(Nv)
    Ry = np.zeros(Nv)
    Rx[boundary] = boundary_coords[0, :]
    Ry[boundary] = boundary_coords[1, :]

    x, info = lgmres(L, Rx, tol=solver_tolerance)
    y, info = lgmres(L, Ry, tol=solver_tolerance)
    z = np.zeros(Nv)

    return trimesh.Trimesh(faces=mesh.faces,
                           vertices=np.array([x, y, z]).T,
                           metadata=mesh.metadata,
                           process=False)
示例#2
0
def disk_conformal_mapping(mesh,
                           lap_type='conformal',
                           boundary=None,
                           boundary_coords=None):
    """
    compute comformal mapping of a mesh to a disk
    ADD ref
    :param mesh: a trimesh object
    :param lap_type: type of mesh Laplacian to be used,
    see the function differential_geometry/compute_mesh_weights for more
    informations
    :param boundary: boundary of the mesh, resulting from the function
    topology/mesh_boundary
    :param boundary_coords: coordindates of the boundary vertices on the
    output disk, if None then uniform sampling
    :return: a trimesh object, planar disk representation of the input mesh
    """
    if boundary is None:
        boundary_t = stop.mesh_boundary(mesh)
        boundary = boundary_t[0]
    boundary = np.array(boundary)
    if boundary_coords is None:
        p = boundary.size
        t = np.arange(0, 2 * np.math.pi, (2 * np.math.pi / p))
        boundary_coords = np.array([np.cos(t), np.sin(t)])
    L, LB = sdg.compute_mesh_laplacian(mesh, lap_type=lap_type)
    Nv = len(mesh.vertices)  # np.array(mesh.vertex()).shape[0]
    print('Boundary Size:', boundary.shape)
    print('Laplacian Size:', L.shape)
    for i in boundary:
        L[i, :] = 0
        L[i, i] = 1
    L = L.tocsr()

    Rx = np.zeros(Nv)
    Ry = np.zeros(Nv)
    Rx[boundary] = boundary_coords[0, :]
    Ry[boundary] = boundary_coords[1, :]

    x, info = lgmres(L, Rx, tol=solver_tolerance)
    y, info = lgmres(L, Ry, tol=solver_tolerance)
    z = np.zeros(Nv)

    return trimesh.Trimesh(faces=mesh.faces,
                           vertices=np.array([x, y, z]).T,
                           metadata=mesh.metadata,
                           process=False)
import slam.io as sio
import slam.differential_geometry as sdg
import slam.plot as splt

if __name__ == '__main__':
    # load example data
    mesh = sio.load_mesh('data/example_mesh.gii')
    tex = sio.load_texture('data/example_texture.gii')

    # compute various types of Laplacian of the mesh
    lap, lap_b = sdg.compute_mesh_laplacian(mesh, lap_type='fem')
    print(mesh.vertices.shape)
    print(lap.shape)
    lap, lap_b = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')
    lap, lap_b = sdg.compute_mesh_laplacian(mesh, lap_type='meanvalue')
    lap, lap_b = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')

    # smooth the mesh using Laplacian
    s_mesh = sdg.laplacian_mesh_smoothing(mesh, nb_iter=100, dt=0.1)

    # compute the gradient of texture tex
    triangle_grad = sdg.triangle_gradient(mesh, tex.darray[0])
    print(triangle_grad)
    grad = sdg.gradient(mesh, tex.darray[0])
    print(grad.values)
    norm_grad = sdg.norm_gradient(mesh, tex.darray[0])
    print(norm_grad)

    # compute the depth potential function
    dpf = sdg.depth_potential_function(mesh, tex.darray[0], [0.3])
示例#4
0
def spherical_mapping(mesh,
                      mapping_type='laplacian_eigenvectors',
                      conformal_w=1,
                      authalic_w=1,
                      dt=0.01,
                      nb_it=10):
    """
    ADD REF
    :param mesh:
    :param mapping_type:
    :param conformal_w:
    :param authalic_w:
    :param dt:
    :param nb_it:
    :return:
    """
    # computing spherical mapping based on laplacian eigenvectors
    sph_vert = sdg.mesh_laplacian_eigenvectors(mesh, nb_vectors=3)
    norm_sph_vert = np.sqrt(np.sum(sph_vert * sph_vert, 1))
    sphere_vertices = sph_vert / np.tile(norm_sph_vert, (3, 1)).T
    if mapping_type == 'laplacian_eigenvectors':
        return trimesh.Trimesh(faces=mesh.faces,
                               vertices=sphere_vertices,
                               metadata=mesh.metadata,
                               process=False)

    if mapping_type == 'conformal':
        """
        Desbrun, M., Meyer, M., & Alliez, P. (2002).
        Intrinsic parameterizations of surface meshes.
        Computer Graphics Forum, 21(3), 209–218.
        https://doi.org/10.1111/1467-8659.00580
        """

        # options.symmetrize = 0;
        # options.normalize = 1;
        L, B = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')

    if mapping_type == 'authalic':
        # options.symmetrize = 0;
        # options.normalize = 1;
        L, B = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')

    if mapping_type == 'combined':
        # options.symmetrize = 0;
        # options.normalize = 1;
        Lconf, Bconf = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')
        Laut, Baut = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')
        L = conformal_w * Lconf + authalic_w * Laut
    # continue the spherical mappig by minimizig the energy
    evol = list()
    for it in range(nb_it):
        sphere_vertices = sphere_vertices - dt * L.dot(sphere_vertices)
        # sphere_vertices * L
        norm_sph_vert = np.sqrt(np.sum(sphere_vertices * sphere_vertices, 1))
        sphere_vertices = sphere_vertices / np.tile(norm_sph_vert, (3, 1)).T
        if it % 10 == 0:
            sph = trimesh.Trimesh(faces=mesh.faces,
                                  vertices=sphere_vertices,
                                  process=False)
            angle_diff = sdst.angle_difference(sph, mesh)
            area_diff = sdst.area_difference(sph, mesh)
            edge_diff = sdst.edge_length_difference(sph, mesh)
            evol.append([
                np.sum(np.abs(angle_diff.flatten())),
                np.sum(np.abs(area_diff.flatten())),
                np.sum(np.abs(edge_diff.flatten()))
            ])

    # ind = 0;
    # for it=1:nb_it
    # % it = 1;
    # % while sum(I(: ) < 0)
    # % it = it + 1;
    # % vertex1 = vertex1 * L;
    # vertex1 = vertex1 - eta * vertex1 * L;
    # vertex1 = vertex1. / repmat(sqrt(sum(vertex1. ^ 2, 1)), [3 1]);
    # if mod(it, 100) == 0
    #     ind = ind + 1;
    #     NFV.vertices = vertex1
    #     ';
    #     [nb_inward, inward] = reversed_faces(NFV, 'sphere');
    #     bil_inward(ind) = nb_inward;
    #     w = zeros(1, m);
    #     E = zeros(1, m);
    #     for i=1:3
    #     i1 = mod(i, 3) + 1;
    #     % directed
    #     edge
    #     u = vertex1(:, faces(i,:)) - vertex1(:, faces(i1,:));
    #     % norm
    #     squared
    #     u = sum(u. ^ 2);
    #     % weights
    #     between
    #     the
    #     vertices
    #     for j=1:m
    #     w(j) = L(faces(i, j), faces(i1, j));
    # end
    # % w = W(faces(i,:) + (faces(i1,:) - 1)*n);
    # E = E + w. * u;
    #
    #
    # end
    #
    # bil_E(ind) = sum(E);
    # if ind > 2
    #     disp(['Ratio of inverted triangles:' num2str(100 * nb_inward / m, 3)
    #           '% energy decrease:' num2str(bil_E(end - 1) - bil_E(end), 3)]);
    # end
    # end
    # end

    return trimesh.Trimesh(faces=mesh.faces,
                           vertices=sphere_vertices,
                           metadata=mesh.metadata,
                           process=False), evol
示例#5
0
文件: mapping.py 项目: gauzias/slam
def spherical_mapping(mesh,
                      mapping_type='laplacian_eigenvectors',
                      conformal_w=1,
                      authalic_w=1,
                      dt=0.01,
                      nb_it=10):
    """
    Computes the mapping between the input mesh and a sphere centered on 0 and of radius=1
    Several methods are implemented:
    -for laplacian eigenvectors, see:
    J. Lefèvre and G. Auzias, "Spherical Parameterization for Genus Zero Surfaces Using
    Laplace-Beltrami Eigenfunctions," in 2nd Conference on Geometric Science of
    Information, GSI, 2015, 121–29, https://doi.org/10.1007/978-3-319-25040-3_14.
    -for conformal mapping, see:
    Desbrun, M., Meyer, M., & Alliez, P., "Intrinsic parameterizations of surface meshes",
    Computer Graphics Forum, 21(3), 2002, 209–218. https://doi.org/10.1111/1467-8659.00580
    -for authalic and combined methods, see:
    Rachel a Yotter, Paul M. Thompson, and Christian Gaser, “Algorithms to Improve the
    Reparameterization of Spherical Mappings of Brain Surface Meshes.,” Journal of
    Neuroimaging 21, no. 2 (April 2011): e134-47, https://doi.org/10.1111/j.1552-6569.2010.00484.x.
    or
    Ilja Friedel, Peter Schröder, and Mathieu Desbrun, “Unconstrained Spherical Parameterization”,
    Journal of Graphics, GPU, and Game Tools 12, no. 1 (2007): 17–26.
    :param mesh: Trimesh object, input mesh to be mapped onto a sphere
    :param mapping_type: string, type of mapping method, possible options are:
    'laplacian_eigenvectors', 'conformal', 'authalic' or 'combined'
    :param conformal_w: Float, weight of the conformal constraint for the 'combined' method
    :param authalic_w: Float, weight of the authalic constraint for the 'combined' method
    :param dt: Float, discrtization step
    :param nb_it: Int, number of iterations
    :return: Trimesh object: the spherical representation of the input mesh, having the same
    adjacency (faces, edges, vertex indexing) as the input mesh.
    """
    # computing spherical mapping based on laplacian eigenvectors
    sph_vert = sdg.mesh_laplacian_eigenvectors(mesh, nb_vectors=3)
    norm_sph_vert = np.sqrt(np.sum(sph_vert * sph_vert, 1))
    sphere_vertices = sph_vert / np.tile(norm_sph_vert, (3, 1)).T
    if mapping_type == 'laplacian_eigenvectors':
        return trimesh.Trimesh(faces=mesh.faces,
                               vertices=sphere_vertices,
                               metadata=mesh.metadata,
                               process=False)

    if mapping_type == 'conformal':
        L, B = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')

    if mapping_type == 'authalic':
        L, B = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')

    if mapping_type == 'combined':
        Lconf, Bconf = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')
        Laut, Baut = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')
        L = conformal_w * Lconf + authalic_w * Laut
    # continue the spherical mappig by minimizig the energy
    evol = list()
    for it in range(nb_it):
        sphere_vertices = sphere_vertices - dt * L.dot(sphere_vertices)
        # sphere_vertices * L
        norm_sph_vert = np.sqrt(np.sum(sphere_vertices * sphere_vertices, 1))
        sphere_vertices = sphere_vertices / np.tile(norm_sph_vert, (3, 1)).T
        if it % 10 == 0:
            sph = trimesh.Trimesh(faces=mesh.faces,
                                  vertices=sphere_vertices,
                                  process=False)
            angle_diff = sdst.angle_difference(sph, mesh)
            area_diff = sdst.area_difference(sph, mesh)
            edge_diff = sdst.edge_length_difference(sph, mesh)
            evol.append([
                np.sum(np.abs(angle_diff.flatten())),
                np.sum(np.abs(area_diff.flatten())),
                np.sum(np.abs(edge_diff.flatten()))
            ])

    return trimesh.Trimesh(faces=mesh.faces,
                           vertices=sphere_vertices,
                           metadata=mesh.metadata,
                           process=False), evol