open3d-网格及其操作

open3d提供了一个三角网格数据结构 TriangleMesh

class TriangleMesh(MeshBase):
    adjacency_list          # 每个顶点相邻顶点集合
    textures                # 纹理
    triangles               # 三角形
    triangle_material_ids   # 材质索引
    triangle_normals        # 三角形法向量
    triangle_uvs            # uv坐标
    vertex_colors           # 顶点颜色
    vertex_normals          # 顶点法向量
    vertices                # 顶点
    def __init__(self, *args, **kwargs):
        """
        __init__(*args, **kwargs)
        Overloaded function.
        1. __init__(self: open3d.cpu.pybind.geometry.TriangleMesh) -> None
        Default constructor
        2. __init__(self: open3d.cpu.pybind.geometry.TriangleMesh, arg0: open3d.cpu.pybind.geometry.TriangleMesh) -> None
        Copy constructor
        3. __init__(self: open3d.cpu.pybind.geometry.TriangleMesh, vertices: open3d.cpu.pybind.utility.Vector3dVector, triangles: open3d.cpu.pybind.utility.Vector3iVector) -> None
        Create a triangle mesh from vertices and triangle indices
        """
    # 三角形连通簇。 返回每个簇中三角形索引,簇中三角形个数,簇面积。
    def cluster_connected_triangles(self):
    # 计算每个顶点的相邻顶点集合。
    def compute_adjacency_list(self):
    # 计算凸包
    def compute_convex_hull(self): 
    # 计算三角形法向量
    def compute_triangle_normals(self, normalized=True):
    # 计算表面法向量
    def compute_vertex_normals(self, normalized=True):
    def create_arrow(self, cylinder_radius=1.0, cone_radius=1.5, cylinder_height=5.0, cone_height=4.0, resolution=20, cylinder_split=4, cone_split=1): 
    def create_box(self, width=1.0, height=1.0, depth=1.0, create_uv_map=False, map_texture_to_each_face=False): 
    def create_cone(self, radius=1.0, height=2.0, resolution=20, split=1, create_uv_map=False): 
    def create_coordinate_frame(self, size=1.0, origin=None, *args, **kwargs): 
    def create_cylinder(self, radius=1.0, height=2.0, resolution=20, split=4, create_uv_map=False): 
    def create_from_point_cloud_alpha_shape(self, *args, **kwargs): 
    def create_from_point_cloud_ball_pivoting(self, pcd, radii): 
    def create_from_point_cloud_poisson(self, pcd, depth=8, width=0, scale=1.1, linear_fit=False, n_threads=-1): 
    def create_icosahedron(self, radius=1.0, create_uv_map=False): 
    def create_moebius(self, length_split=70, width_split=15, twists=1, raidus=1, flatness=1, width=1, scale=1): 
    def create_octahedron(self, radius=1.0, create_uv_map=False): 
    def create_sphere(self, radius=1.0, resolution=20, create_uv_map=False):
    def create_tetrahedron(self, radius=1.0, create_uv_map=False):
    def create_torus(self, torus_radius=1.0, tube_radius=0.5, radial_resolution=30, tubular_resolution=20): 
    # 裁剪。 输入aabb 或 obb
    def crop(self, *args, **kwargs): 
    def deform_as_rigid_as_possible(self, constraint_vertex_indices, constraint_vertex_positions, max_iter, energy=None, smoothed_alpha=0.01):
    def euler_poincare_characteristic(self): 
    def filter_sharpen(self, number_of_iterations=1, strength=1, filter_scope=None): 
    # 拉普拉斯算子
    def filter_smooth_laplacian(self, number_of_iterations=1, lambda=0.5, filter_scope=None): 
    # 简单邻域平均值 三角形平滑
    def filter_smooth_simple(self, number_of_iterations=1, filter_scope=None): 
    # Taubin 三角形平滑
    def filter_smooth_taubin(self, number_of_iterations=1, lambda=0.5, mu=-0.53, filter_scope=None): 
    def get_non_manifold_edges(self, allow_boundary_edges=True): 
    def get_non_manifold_vertices(self): 
    def get_self_intersecting_triangles(self): 
    def get_surface_area(self): 
    def get_volume(self): 
    def has_adjacency_list(self): 
    def has_textures(self): 
    def has_triangles(self): 
    def has_triangle_material_ids(self): 
    def has_triangle_normals(self): 
    def has_triangle_uvs(self): 
    def has_vertex_colors(self): 
    def has_vertex_normals(self): 
    def has_vertices(self):
    # 是否是边流形
    def is_edge_manifold(self, allow_boundary_edges=True):
    # 判断当前三角网是否与给定三角网相交
    def is_intersecting(self, arg0):
    # 是否可定向。 三角网是否可以以所有法向量指向外部的方式定向
    def is_orientable(self): 
    # 判断是否自相交
    def is_self_intersecting(self):
    # 是否是顶点流形
    def is_vertex_manifold(self): 
    # 是否是水密网格
    def is_watertight(self): 
    # 合并顶点。 输入顶点间距离
    def merge_close_vertices(self, eps): 
    # 归一化法向量
    def normalize_normals(self): 
    # 法向量方向一致。 如果法向量可以定向,使所有法向量指向同一方向
    def orient_triangles(self): 
    # 上色。 颜色rgb, 范围0~1
    def paint_uniform_color(self, arg0): 
    # 删除多余的三角形。 这个问题一般是由于合并顶点造成的。
    def remove_degenerate_triangles(self): 
    # 删除重复的三角形。
    def remove_duplicated_triangles(self): 
    # 删除重复的顶点。
    def remove_duplicated_vertices(self): 
    # 删除非流形边。
    def remove_non_manifold_edges(self): 
    # 通过索引删除三角形。
    def remove_triangles_by_index(self, triangle_indices): 
    # 通过掩码删除三角形。
    def remove_triangles_by_mask(self, triangle_mask):
    # 删除为引用的顶点。
    def remove_unreferenced_vertices(self): 
    # 通过索引删除顶点。
    def remove_vertices_by_index(self, vertex_indices): 
    # 通过掩码删除顶点。
    def remove_vertices_by_mask(self, vertex_mask): 
    # 
    def sample_points_poisson_disk(self, number_of_points, init_factor=5, pcl=None, use_triangle_normal=False, seed=-1): 
    # 采样点。 从平面均匀采样点。
    def sample_points_uniformly(self, number_of_points=100, use_triangle_normal=False, seed=-1): 
    # 通过索引筛选
    def select_by_index(self, indices, cleanup=True): 
    # 网格抽取。 用于简化网格
    def simplify_quadric_decimation(self, target_number_of_triangles, maximum_error=None, boundary_weight=1.0): 
    # 顶点聚类。 用于简化网格
    def simplify_vertex_clustering(self, voxel_size, contraction=None): 
    # 循环算法。 用于细分网格
    def subdivide_loop(self, number_of_iterations=1): 
    # 中点算法。 用于细分网格
    def subdivide_midpoint(self, number_of_iterations=1): 
import open3d as o3d
import numpy as np
from open3d.web_visualizer import draw
from open3d.visualization import draw_geometries
import copy
mesh = o3d.io.read_triangle_mesh('datas/knot.ply')

1.表面法向量估计

mesh.compute_vertex_normals()

2.裁剪三角网

# 这里通过numpy进行裁剪操作。需要注意的是,裁剪后需要转换数据格式。
mesh1 = copy.deepcopy(mesh)
mesh1.triangles = o3d.utility.Vector3iVector(
    np.asarray(mesh1.triangles)[:len(mesh1.triangles) // 2, :])

mesh1.triangle_normals = o3d.utility.Vector3dVector(
    np.asarray(mesh1.triangle_normals)[:len(mesh1.triangle_normals)//2, :]
)
draw(mesh1)

3. 三角网上色

mesh1.paint_uniform_color([1,0,0])

4. 合并三角网顶点

print(mesh)
->TriangleMesh with 1440 points and 2880 triangles.
mesh1 = mesh.merge_close_vertices(5)
print(mesh1)
->TriangleMesh with 1316 points and 2880 triangles.
mesh1 = mesh1.remove_degenerate_triangles()
print(mesh1)
->TriangleMesh with 1316 points and 2632 triangles.

5. 平均平滑

mesh1 = mesh1.filter_smooth_simple(5)
print(mesh1)
-> TriangleMesh with 1316 points and 2632 triangles.

6. 采样

pcd = mesh.sample_points_uniformly(number_of_points=1000)
print(pcd)
-> PointCloud with 1000 points.

7. 网格细分

print(mesh1)
-> TriangleMesh with 1316 points and 2632 triangles.
mesh1 = mesh.subdivide_midpoint(2)
print(mesh1)
-> TriangleMesh with 21056 points and 42112 triangles.

8. 网格简化

print(mesh1)
-> TriangleMesh with 21056 points and 42112 triangles.
mesh1 = mesh.simplify_quadric_decimation(1000)
print(mesh1)
-> TriangleMesh with 500 points and 1000 triangles.