亲测代码程序可运行使用,open3d版本0.13.0。
open3d数据资源下载:GitHub - Cobotic/Open3D: Open3D: A Modern Library for 3D Data Processing
代码执行功能有:读取三角网格打印顶点和三角形、表面法线估计、裁剪网格、网格上色、网格滤波、采样、网格细分、网格简化、网格抽取,详情请见代码。
'''
Author: dongcidaci
Date: 2021-09-10 08:34:37
LastEditTime: 2021-09-10 14:35:22
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \open3d_code\mesh.py
'''
from numpy.core.defchararray import asarray
import open3d as o3d
import numpy as np
import copy
#从一个ply文件读取三角网格数据并且打印它的顶点和三角形
mesh = o3d.io.read_triangle_mesh("test_data/knot.ply")
print(np.asarray(mesh.vertices))
print(np.asarray(mesh.triangles))
#可视化网格
print("Try to render a mesh with normals (exist: " +
str(mesh.has_vertex_normals()) + ") and colors (exist: " +
str(mesh.has_vertex_colors()) + ")")
o3d.visualization.draw_geometries([mesh])
#表面法线估计
#用曲面法线来绘制网格
mesh.compute_vertex_normals()
print(np.asarray(mesh.triangle_normals))
o3d.visualization.draw_geometries([mesh])
#裁剪网格
#通过直接操作网格的triangle和triangle_normals字段,我们删除了一半的数据
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, :])
print(mesh1.triangles)
o3d.visualization.draw_geometries([mesh1])
#网格上色
#网格的上色和点云的上色是一致的
mesh1.paint_uniform_color([1, 0.706, 0])
o3d.visualization.draw_geometries([mesh1])
#网格滤波
#均值滤波
#filter_smooth_simple函数的参数number_of_iterations用来定义应用于网格的滤波器的频率
print('create noisy mesh')
#mesh_in = o3dtut.get_knot_mesh()
mesh_in = copy.deepcopy(mesh)
vertices = np.asarray(mesh_in.vertices)
noise = 5
vertices += np.random.uniform(0, noise, size=vertices.shape)
mesh_in.vertices = o3d.utility.Vector3dVector(vertices)
mesh_in.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_in])
print('filter with average with 1 iteration')
mesh_out = mesh_in.filter_smooth_simple(number_of_iterations=1)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])
print('filter with average with 5 iterations')
mesh_out = mesh_in.filter_smooth_simple(number_of_iterations=5)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])
#拉普拉斯算子
print('filter with Laplacian with 10 iterations')
mesh_out = mesh_in.filter_smooth_laplacian(number_of_iterations=10)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])
print('filter with Laplacian with 50 iterations')
mesh_out = mesh_in.filter_smooth_laplacian(number_of_iterations=50)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])
#均值滤波和Laplacian滤波有一个问题是他们会使三角网格收缩
#Taubin滤波
#这个滤波器实现的接口是filter_smooth_taubin
print('filter with Taubin with 10 iterations')
mesh_out = mesh_in.filter_smooth_taubin(number_of_iterations=10)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])
print('filter with Taubin with 100 iterations')
mesh_out = mesh_in.filter_smooth_taubin(number_of_iterations=100)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])
#采样
#网格中采样点云,使用sample_points_uniformly函数从三角网格的三维表面均匀采样
#参数number_of_points表示从网格中采样的点云的点数
mesh = o3d.geometry.TriangleMesh.create_sphere()
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh])
pcd = mesh.sample_points_uniformly(number_of_points=500)
o3d.visualization.draw_geometries([pcd])
#mesh = o3dtut.get_bunny_mesh()
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh])
pcd = mesh.sample_points_uniformly(number_of_points=500)
o3d.visualization.draw_geometries([pcd])
#泊松盘采样能够使采样点均匀的分布。sample_points_poisson_disk实现了该功能
#1.默认通过参数init_factor:首先通过init_factor x number_of_points来从网格中均匀采样点云,之后进行消除。
#2.可以直接提供一个点云数据给sample_points_poisson_disk函数,之后会进行点云的消除。
mesh = o3d.geometry.TriangleMesh.create_sphere()
pcd = mesh.sample_points_poisson_disk(number_of_points=500, init_factor=5)
o3d.visualization.draw_geometries([pcd])
pcd = mesh.sample_points_uniformly(number_of_points=2500)
pcd = mesh.sample_points_poisson_disk(number_of_points=500, pcl=pcd)
o3d.visualization.draw_geometries([pcd])
#网格细分
#网格细分就是把每个三角形划分为更小的三角形
#最简单的方式就是,计算三角形每个边的中点,将其划分为四个较小的三角形。
#通过subdivide_midpoint函数实现。number_of_iterations参数定义了重复细分多少次。
mesh = o3d.geometry.TriangleMesh.create_box()
mesh.compute_vertex_normals()
print(f'The mesh has {len(mesh.vertices)} vertices and {len(mesh.triangles)} triangles')
o3d.visualization.draw_geometries([mesh], mesh_show_wireframe=True)
mesh = mesh.subdivide_midpoint(number_of_iterations=1)
print(f'After subdivision it has {len(mesh.vertices)} vertices and {len(mesh.triangles)} triangles')
o3d.visualization.draw_geometries([mesh], mesh_show_wireframe=True)
#网格简化
#顶点聚类的方法是将所有落入给定大小的体素的顶点聚集到单个顶点
#函数接口为simplify_vertex_clustering,参数voxel_size设置体素网格大小
#mesh_in = o3dtut.get_bunny_mesh()
print(f'Input mesh has {len(mesh_in.vertices)} vertices and {len(mesh_in.triangles)} triangles')
o3d.visualization.draw_geometries([mesh_in])
voxel_size = max(mesh_in.get_max_bound() - mesh_in.get_min_bound()) / 32
print(f'voxel_size = {voxel_size:e}')
mesh_smp = mesh_in.simplify_vertex_clustering(
voxel_size=voxel_size,
contraction=o3d.geometry.SimplificationContraction.Average)
print(f'Simplified mesh has {len(mesh_smp.vertices)} vertices and {len(mesh_smp.triangles)} triangles')
o3d.visualization.draw_geometries([mesh_smp])
voxel_size = max(mesh_in.get_max_bound() - mesh_in.get_min_bound()) / 16
print(f'voxel_size = {voxel_size:e}')
mesh_smp = mesh_in.simplify_vertex_clustering(
voxel_size=voxel_size,
contraction=o3d.geometry.SimplificationContraction.Average)
print(f'Simplified mesh has {len(mesh_smp.vertices)} vertices and {len(mesh_smp.triangles)} triangles')
o3d.visualization.draw_geometries([mesh_smp])
#网格抽取
#网格细分的另一种方式是逐步执行的网格抽取。我们选取一个最小化误差指标的三角形移除
#参数target_number_of_triangles定义了停止抽取停止的规则。
mesh_smp = mesh_in.simplify_quadric_decimation(
target_number_of_triangles=6500)
print(f'Simplified mesh has {len(mesh_smp.vertices)} vertices and {len(mesh_smp.triangles)} triangles')
o3d.visualization.draw_geometries([mesh_smp])
mesh_smp = mesh_in.simplify_quadric_decimation(
target_number_of_triangles=1700)
print(f'Simplified mesh has {len(mesh_smp.vertices)} vertices and {len(mesh_smp.triangles)} triangles')
o3d.visualization.draw_geometries([mesh_smp])