Open3d(三)——网格数据操作

亲测代码程序可运行使用,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])

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
simplify_quadric_decimation是一种用于简化网格模型的方法。简化维模型通常在计算机图形学和计算机辅助设计领域使用,在保持模型形状和细节的同时减少模型的面片数量,以提高计算和渲染效率。 simplify_quadric_decimation的核心思想是通过不断合并模型的面片来减少其数量。这个方法使用了二次误差度量的概念来评估面片的“重要性”。其中,每个面片都与相邻的面片共享顶点,而共享的顶点会根据相邻面片的平均法线、位置和面积计算一个二次误差度量值。该值的大小用于衡量面片在模型中的重要性。低重要性的面片在简化过程中更容易被合并,而高重要性的面片保持不变,以保留模型的细节。 在simplify_quadric_decimation的算法中,首先需要计算每个面片的二次误差度量值。然后,从中选择一个重要性较低的面片进行合并,即将该面片与相邻面片合并为一个更大的面片,并更新相邻面片的二次误差度量值。重复这个过程,直到达到所需的面片数量或者满足其他约束条件。 simplify_quadric_decimation的优点是能够在减少面片数量的同时,保持模型的整体形状和细节。它还可以通过调整二次误差度量值的权重来控制简化过程中保留的细节程度。然而,这个方法也有一些缺点,例如对于一些复杂的模型,合并面片可能会导致形状的变形或损失细节。 总之,simplify_quadric_decimation是一种有效的方法来简化网格模型,它在计算机图形学和计算机辅助设计领域具有广泛的应用前景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值