Mesh smoothing

Smooth mesh with various filters

Smoothing in libigl

We implement Laplacian and Taubin smoothing for vertex positions using libigl’s Laplacian operator.


source

get_uniform_laplacian

 get_uniform_laplacian (tris, normalize=True)

*Get uniform Laplacian (purely connectivity-based) as a sparse matrix.

If normalize, the diagonal = -1. Else, the diagonal equals the number of neighbors.*


source

smooth_laplacian

 smooth_laplacian (mesh:blender_tissue_cartography.mesh.ObjMesh, lamb=0.5,
                   n_iter=10, method='explicit', boundary='fixed')

*Smooth mesh vertex positions using Laplacian filter.

Assumes mesh is triangular.*

Type Default Details
mesh ObjMesh Initial mesh.
lamb float 0.5 Filter strength. Higher = more smoothing.
n_iter int 10 Filter iterations
method str explicit Can use “explicit” (fast, simple) or “implicit” (slow, more accurate) methods.
boundary str fixed Whether to allow mesh boundaries to move
Returns ObjMesh Smoothed mesh.
# Load a test mesh
mesh_registered = tcmesh.ObjMesh.read_obj(f"datasets/wrapping_example/Drosophila_reference_registered.obj")
Warning: readOBJ() ignored non-comment line 1:
  o Drosophila_reference_preregistered
mesh_smoothed = smooth_laplacian(mesh_registered, lamb=0.5, n_iter=10, method="explicit")
mesh_smoothed.write_obj("datasets/wrapping_example/Drosophila_reference_smoothed_uniform_igl.obj")
boundary_vertices = igl.boundary_facets(mesh_registered.texture_tris)[:, 0]
np.allclose(mesh_smoothed.texture_vertices[boundary_vertices],
            mesh_registered.texture_vertices[boundary_vertices])
True

source

smooth_taubin

 smooth_taubin (mesh:blender_tissue_cartography.mesh.ObjMesh, lamb=0.5,
                nu=0.53, n_iter=10)

*Smooth using Taubin filter (like Laplacian, but avoids shrinkage).

Assumes mesh is triangular. See “Improved Laplacian Smoothing of Noisy Surface Meshes” J. Vollmer, R. Mencl, and H. Muller.*

Type Default Details
mesh ObjMesh Initial mesh.
lamb float 0.5 Filter strength. Higher = more smoothing.
nu float 0.53 Counteract shrinkage. Higher = more dilation.
n_iter int 10 Filter iterations
Returns ObjMesh Smoothed mesh.
mesh_smoothed_taubin = smooth_taubin(mesh_registered, lamb=0.5, nu=0.53, n_iter=10)
mesh_smoothed_taubin.write_obj("datasets/wrapping_example/Drosophila_reference_smoothed_taubin_igl.obj")

Texture smoothing

Sometimes, UV maps can become very deformed, or even display self-intersection. Smoothing can fix this.


source

smooth_laplacian_texture

 smooth_laplacian_texture (mesh:blender_tissue_cartography.mesh.ObjMesh,
                           lamb=0.5, n_iter=10, boundary='fixed')

*Smooth mesh texture positions using Laplacian filter.

This function is very helpful in fixing UV maps with flipped triangles, as detected by igl.flipped_triangles. Assumes mesh is triangular.*

Type Default Details
mesh ObjMesh Initial mesh.
lamb float 0.5 Filter strength. Higher = more smoothing.
n_iter int 10 Filter iterations
boundary str fixed Whether to allow UV “island” boundary to move
Returns ObjMesh Smoothed mesh.
mesh_texture_smoothed = smooth_laplacian_texture(mesh_registered, lamb=0.5, n_iter=10,)

On-surface smoothing

Smooth, but project at each step so the mesh vertices are back on the surface. This is very useful to smooth out surface-surface maps.


source

smooth_laplacian_on_surface

 smooth_laplacian_on_surface
                              (mesh:blender_tissue_cartography.mesh.ObjMes
                              h, n_iter=10, lamb=0.5, n_iter_laplace=10,
                              boundary='fixed')

*Smooth mesh vertex positions using Laplacian filter and project vertices back to the original surface.

Alternates between Laplacian smoothing and projecting back to the original surface. Uses explicit method for Laplacian smoothing*

Type Default Details
mesh ObjMesh Initial mesh.
n_iter int 10 Number of iterations at each step
lamb float 0.5 Filter strength. Higher = more smoothing.
n_iter_laplace int 10 Laplace filter iterations. If reprojection messes up your mesh, decrease this number.
boundary str fixed Whether to allow mesh boundaries to move
Returns ObjMesh Smoothed mesh.
mesh_test = tcmesh.ObjMesh.read_obj(f"datasets/movie_example/meshes_wrapped_reverse/mesh_01_wrapped_reverse.obj")
mesh_smoothed = smooth_laplacian_on_surface(mesh_test, n_iter=20, lamb=0.5, n_iter_laplace=5)
mesh_smoothed.write_obj(f"datasets/movie_example/on_surface_smooth.obj")