目录
一、概述
1.1原理
1.2实现步骤
1.3应用
二、代码实现
2.1关键函数
2.1.1函数代码
2.1.2参数详解
2.1.3名词解释
2.2完整代码
三、实现效果
3.1原始点云
3.2重建后点云
3.3去除低密度点云
Open3D点云算法汇总及实战案例汇总的目录地址:
Open3D点云算法与点云深度学习案例汇总(长期更新)-CSDN博客
一、概述
1.1原理
泊松曲面重建是一种用于从点云数据生成光滑曲面的算法。该方法基于泊松方程,通过最小化法向量场的散度,生成具有光滑特性的三维表面。具体来说,泊松曲面重建将点云的法向量信息视为泊松方程中的源项,通过解泊松方程,得到一个光滑的隐函数。然后,通过提取隐函数的等值面,生成三维网格。
1.2实现步骤
- 加载点云数据:读取点云数据文件。
- 估计法向量:计算点云中每个点的法向量,通常使用KD树进行邻域搜索。
- 泊松曲面重建:使用泊松方程重建三维曲面,生成三角网格。
- 后处理:使用顶点密度信息去除低密度区域。
- 可视化和保存结果:可视化重建结果,并将生成的三角网格保存到文件中。
1.3应用
- 三维重建:从点云数据生成完整的三维表面,用于建筑、文物的数字化。
- 计算机视觉:用于物体识别和场景理解。
- 医学成像:从扫描数据重建器官和组织的三维结构。
二、代码实现
2.1关键函数
2.1.1函数代码
使用 create_from_point_cloud_poisson 函数进行泊松曲面重建,生成三角网格(mesh)和顶点密度(densities)。
def create_from_point_cloud_poisson(self, pcd, depth=8, width=0, scale=1.1, linear_fit=False, n_threads=-1):"""从点云数据进行泊松曲面重建。参数:pcd (open3d.geometry.PointCloud): 输入的点云对象,包含点的位置和法向量信息。depth (int, optional): 八叉树的最大深度,控制重建的细节程度。默认值为8。width (int, optional): 八叉树宽度的参数,通常与 depth 结合使用。默认值为0。scale (float, optional): 设置重建的细节比例,值越大,生成的网格越精细。默认值为1.1。linear_fit (bool, optional): 是否进行线性拟合以改进法向量估计的精度。默认值为False。n_threads (int, optional): 线程数。默认值为-1,表示使用所有可用线程。返回:mesh (open3d.geometry.TriangleMesh): 生成的三角网格。densities (open3d.utility.Vector3dVector): 每个顶点的密度值。"""
2.1.2参数详解
1.pcd (open3d.geometry.PointCloud):
- 输入的点云对象,需要包含点的位置和法向量信息。法向量用于泊松曲面重建中的法向量场。
2.depth (int, optional, default=8):
- 八叉树的最大深度,控制重建的细节程度。较大的深度值会生成更细致的网格,但计算时间也会增加。
- 推荐值范围:5到12。
- 较小的值(如5)会生成较粗糙的网格,适用于大规模的点云数据。
- 较大的值(如12)会生成较精细的网格,适用于高分辨率的点云数据。
3.width (int, optional, default=0):
- 用于指定八叉树宽度的参数,通常与depth结合使用。如果设置为0,将自动计算合适的宽度。
4.scale (float, optional, default=1.1):
- 用于设置重建的细节比例。值越大,生成的网格越精细。
- 影响到八叉树的构建,典型值在1到2之间。
5.linear_fit (bool, optional, default=False):
- 如果设置为True,将进行线性拟合以改进法向量估计的精度。
- 适用于存在噪声或不完整数据的点云。
2.1.3名词解释
1.八叉树(Octree):
- 八叉树是一种用于空间划分的数据结构,将三维空间递归地划分为更小的立方体。深度参数控制了八叉树的递归层数,层数越多,划分越细,生成的网格也越精细。
2.法向量场(Normal Field):
- 法向量场是点云中每个点的法向量的集合。泊松曲面重建通过最小化法向量场的散度,生成一个光滑的隐函数。法向量的估计对重建结果有重要影响,因此在重建之前,需要为点云估计法向量。
3.泊松方程(Poisson Equation):
- 泊松方程是一种偏微分方程,描述了隐函数的行为。泊松曲面重建通过解这个方程,得到一个隐函数,然后通过提取等值面,生成三维网格。
2.2完整代码
import open3d as o3d
import numpy as np
from matplotlib import pyplot as pltpcd = o3d.io.read_point_cloud("hand_trans.pcd")
print(pcd) # 输出点云点的个数
# -----------------------计算法线------------------------
# 搜索半径0.01m,只考虑邻域内的30个点
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.01, max_nn=30))print('run Poisson surface reconstruction')
with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug) as cm:mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=9)
print(mesh)
o3d.visualization.draw_geometries([mesh])# -----------使用伪颜色显示3D中的密度。--------------------
# 紫色代表低密度,黄色代表高密度。
print('visualize densities')
densities = np.asarray(densities)
density_colors = plt.get_cmap('plasma')((densities - densities.min()) / (densities.max() - densities.min()))
density_colors = density_colors[:, :3]
density_mesh = o3d.geometry.TriangleMesh()
density_mesh.vertices = mesh.vertices
density_mesh.triangles = mesh.triangles
density_mesh.triangle_normals = mesh.triangle_normals
density_mesh.vertex_colors = o3d.utility.Vector3dVector(density_colors)
o3d.visualization.draw_geometries([density_mesh])# -------------删除所有密度值低于0.01的区域。---------------
print('remove low density vertices')
vertices_to_remove = densities < np.quantile(densities, 0.01)
mesh.remove_vertices_by_mask(vertices_to_remove)
print(mesh)
o3d.visualization.draw_geometries([mesh])