zoukankan      html  css  js  c++  java
  • CG——Laplacian Surface Editing

    参考文献:https://igl.ethz.ch/projects/Laplacian-mesh-processing/Laplacian-mesh-editing/laplacian-mesh-editing.pdf

    https://people.eecs.berkeley.edu/~jrs/meshpapers/Sorkine.pdf

    原理:这篇博客写的很好,通俗易懂:https://blog.csdn.net/qq_31804159/article/details/103409465

    代码:

    import numpy as np
    import networkx as nx
    import trimesh
    import scipy.sparse
    
    #function collection
    def mesh_to_graph(mesh):
        edges = mesh.edges_unique
        verts = mesh.vertices
        g = nx.Graph()
        for i, pos in enumerate(verts):
            g.add_node(i, pos=pos)
        for edge in edges:
            g.add_edge(*edge)
        return g
    
    def get_boundary(g, ctrl_points):
        boundary = []
        for i in range(len(ctrl_points)):
            p1 = ctrl_points[i]
            p2 = ctrl_points[(i+1)%len(ctrl_points)]
            path = nx.shortest_path(g, p1, p2)
            boundary += path[0:-1]
        return boundary
    
    def rw_laplacian_matrix(g):
        lap = nx.laplacian_matrix(g)
        adj = nx.adjacency_matrix(g)
        inv_deg = scipy.sparse.diags(1/adj.dot(np.ones([adj.shape[0]])))
        return inv_deg.dot(lap)
    
    def get_editable_vertices(g, boundary, manip_handle):
        g_part = g.copy()
        g_part.remove_nodes_from(boundary)
        return list(nx.node_connected_component(g_part, manip_handle))
    
    def get_mesh_scene(mesh, boundary=None, editable_vertices=None):
        scene = [mesh]
    #     if boundary:
    #         scene.append(trimesh.load_path(mesh.vertices[boundary+[boundary[0]]]))
        if editable_vertices:
            scene.append(trimesh.points.PointCloud(mesh.vertices[editable_vertices + boundary]))
        return trimesh.Scene(scene)
    
    #load mesh
    
    mesh = trimesh.load('bunny.ply', process=False)
    g = mesh_to_graph(mesh)
    handles = {
        24092 : [-0.01134  ,  0.151374 , -0.0242688]
    }
    boundary_ctrl_points = [15617, 24120, 30216, 11236, 6973]
    boundary = get_boundary(g, boundary_ctrl_points)
    editable_verts = get_editable_vertices(g, boundary, list(handles.keys())[0])
    trimesh.points.PointCloud(mesh.vertices[editable_verts + boundary])
    get_mesh_scene(mesh, boundary, editable_verts).show(viewer='gl',smooth=False)
    
    # laplacian
    subgraph = g.subgraph(boundary + editable_verts)
    old_id = list(subgraph)
    grp_idx = {}
    for node in subgraph.nodes:
        grp_idx[node] = len(grp_idx)
    g2 = list(subgraph.nodes)
    L = rw_laplacian_matrix(subgraph).todense()   #最初的L
    V = np.matrix([subgraph.nodes[i]['pos'] for i in subgraph.nodes])
    Delta = L.dot(V)
    boundary_idx = [grp_idx[i] for i in boundary_ctrl_points]
    for x in handles.keys():
        t = grp_idx[int(x)]
        boundary_idx.append(t)
    N = L.shape[0]       
    H = np.zeros((len(boundary_idx), N))
    h = [] 
    for i in range(len(boundary_idx)):
        idx = boundary_idx[i]
        H[i][idx] = 1
    for x in boundary_ctrl_points:
        h.append( np.array(subgraph.nodes[x]['pos']) )
    for x in handles.values():
        h.append( x )
    h = np.matrix(h)
    newL = np.vstack((L, H))
    newDelta = np.vstack((Delta, h))
    n, m = newL.shape[1], newL.shape[0]
    transL = np.zeros((m*3, n*3))
    newL = newL.tolist()
    for i in range(m):
        for j in range(n):
            transL[i*3][j*3] = transL[i*3+1][j*3+1] = transL[i*3+2][j*3+2] = newL[i][j]
    transL = scipy.sparse.coo_matrix(transL)
    newDelta = newDelta.tolist()
    transDelta = []
    for item in newDelta:
        for x in item:
            transDelta.append(x)
    transDelta=np.array(transDelta)
    X = scipy.sparse.linalg.lsqr(transL, transDelta)[0]
    
    # display
    newmesh = mesh.copy()
    for i in range(n):
        newmesh.vertices[old_id[i]] = [X[i*3],X[i*3+1],X[i*3+2]]
    scene2 = [newmesh]
    trimesh.Scene(scene2).show(viewer='gl',smooth=False)
    
        
    View Code

    成果:

                       

  • 相关阅读:
    初步认识三层架构
    机器学习技法总结(六)Decision Tree Hypothesis
    spring 事件模式 源代码导读
    Missing 'name' key attribute on element activity at AndroidMan
    【iOS】KVC 与 KVO
    可用谷歌ip地址
    android menu事件
    #103. 子串查找
    P2590 [ZJOI2008]树的统计
    带修改莫队算法
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/15190408.html
Copyright © 2011-2022 走看看