|
import numpy as np |
|
import pymeshlab as pml |
|
|
|
|
|
def poisson_mesh_reconstruction(points, normals=None): |
|
|
|
|
|
import open3d as o3d |
|
|
|
pcd = o3d.geometry.PointCloud() |
|
pcd.points = o3d.utility.Vector3dVector(points) |
|
|
|
|
|
pcd, ind = pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=10) |
|
|
|
|
|
if normals is None: |
|
pcd.estimate_normals() |
|
else: |
|
pcd.normals = o3d.utility.Vector3dVector(normals[ind]) |
|
|
|
|
|
o3d.visualization.draw_geometries([pcd], point_show_normal=False) |
|
|
|
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( |
|
pcd, depth=9 |
|
) |
|
vertices_to_remove = densities < np.quantile(densities, 0.1) |
|
mesh.remove_vertices_by_mask(vertices_to_remove) |
|
|
|
|
|
o3d.visualization.draw_geometries([mesh]) |
|
|
|
vertices = np.asarray(mesh.vertices) |
|
triangles = np.asarray(mesh.triangles) |
|
|
|
print( |
|
f"[INFO] poisson mesh reconstruction: {points.shape} --> {vertices.shape} / {triangles.shape}" |
|
) |
|
|
|
return vertices, triangles |
|
|
|
|
|
def decimate_mesh( |
|
verts, faces, target, backend="pymeshlab", remesh=False, optimalplacement=True |
|
): |
|
|
|
|
|
_ori_vert_shape = verts.shape |
|
_ori_face_shape = faces.shape |
|
|
|
if backend == "pyfqmr": |
|
import pyfqmr |
|
|
|
solver = pyfqmr.Simplify() |
|
solver.setMesh(verts, faces) |
|
solver.simplify_mesh(target_count=target, preserve_border=False, verbose=False) |
|
verts, faces, normals = solver.getMesh() |
|
else: |
|
m = pml.Mesh(verts, faces) |
|
ms = pml.MeshSet() |
|
ms.add_mesh(m, "mesh") |
|
|
|
|
|
|
|
ms.meshing_decimation_quadric_edge_collapse( |
|
targetfacenum=int(target), optimalplacement=optimalplacement |
|
) |
|
|
|
if remesh: |
|
|
|
ms.meshing_isotropic_explicit_remeshing( |
|
iterations=3, targetlen=pml.Percentage(1) |
|
) |
|
|
|
|
|
m = ms.current_mesh() |
|
verts = m.vertex_matrix() |
|
faces = m.face_matrix() |
|
|
|
print( |
|
f"[INFO] mesh decimation: {_ori_vert_shape} --> {verts.shape}, {_ori_face_shape} --> {faces.shape}" |
|
) |
|
|
|
return verts, faces |
|
|
|
|
|
def clean_mesh( |
|
verts, |
|
faces, |
|
v_pct=1, |
|
min_f=64, |
|
min_d=20, |
|
repair=True, |
|
remesh=True, |
|
remesh_size=0.01, |
|
): |
|
|
|
|
|
|
|
_ori_vert_shape = verts.shape |
|
_ori_face_shape = faces.shape |
|
|
|
m = pml.Mesh(verts, faces) |
|
ms = pml.MeshSet() |
|
ms.add_mesh(m, "mesh") |
|
|
|
|
|
ms.meshing_remove_unreferenced_vertices() |
|
|
|
if v_pct > 0: |
|
ms.meshing_merge_close_vertices( |
|
threshold=pml.Percentage(v_pct) |
|
) |
|
|
|
ms.meshing_remove_duplicate_faces() |
|
ms.meshing_remove_null_faces() |
|
|
|
if min_d > 0: |
|
ms.meshing_remove_connected_component_by_diameter( |
|
mincomponentdiag=pml.Percentage(min_d) |
|
) |
|
|
|
if min_f > 0: |
|
ms.meshing_remove_connected_component_by_face_number(mincomponentsize=min_f) |
|
|
|
if repair: |
|
|
|
ms.meshing_repair_non_manifold_edges(method=0) |
|
ms.meshing_repair_non_manifold_vertices(vertdispratio=0) |
|
|
|
if remesh: |
|
|
|
ms.meshing_isotropic_explicit_remeshing( |
|
iterations=3, targetlen=pml.AbsoluteValue(remesh_size) |
|
) |
|
|
|
|
|
m = ms.current_mesh() |
|
verts = m.vertex_matrix() |
|
faces = m.face_matrix() |
|
|
|
print( |
|
f"[INFO] mesh cleaning: {_ori_vert_shape} --> {verts.shape}, {_ori_face_shape} --> {faces.shape}" |
|
) |
|
|
|
return verts, faces |
|
|