config.yaml
'depth': 10:#深度,设定为10,常用于决定处理或计算的层次或深入程度。
'min_density': 0.1:#最小密度,设置为0.1,用于过滤或选择的密度阈值。
'n_threads': -1:#线程数,设为-1,通常表示使用所有可用的处理器核心。
'downsample': False:#降采样,设为False,表示不进行降采样处理。
'voxel_size': 0.5:#体素大小,设置为0.5,用于定义空间网格的体素的尺寸。
'max_nn': 20:#最大邻居数,设为20,用于某些需要基于最近邻算法的计算。
'pc_range': [-50, -50, -5, 50, 50, 3]:#点云范围,设置为从-50到50在X和Y方向上,从-5到3在Z方向上,用于界定处理或分析的空间区域。
'occ_size': [200, 200, 16]:#占据格大小,设置为200x200x16,表示在三维空间中的格子数量。
'self_range': [3.0, 3.0, 3.0]:#自身范围,设置为3.0x3.0x3.0,可能用于定义某种局部空间的大小。
def run_poisson(pcd, depth, n_threads, min_density=None):
# 使用Poisson表面重建算法从点云创建三角形网格
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
pcd, depth=depth, n_threads=n_threads
)
# 如果提供了最小密度阈值,则移除低于该阈值的顶点
if min_density:
vertices_to_remove = densities < np.quantile(densities, min_density)
mesh.remove_vertices_by_mask(vertices_to_remove)
# 计算网格顶点的法线
mesh.compute_vertex_normals()
return mesh, densities
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],
zoom=0.664,
front=[-0.4761, -0.4698, -0.7434],
lookat=[1.8900, 3.2596, 0.9284],
up=[0.2304, -0.8825, 0.4101])
泊松曲面重建还将在低点密度区域创建三角形,甚至外推到某些区域(请参见上面 eagle 输出的底部)。 create_from_point_cloud_poisson 函数有第二个 densities 返回值,该值指示每个顶点的密度。低密度值意味着顶点仅由输入点云中的少量点支持。
In the code below we visualize the density in 3D using pseudo color. Violet indicates low density and yellow indicates a high density.
在下面的代码中,我们使用伪彩色可视化 3D 密度。紫色表示低密度,黄色表示高密度。
源代码
# 如果提供了最小密度阈值,则移除低于该阈值的顶点
if min_density:
vertices_to_remove = densities < np.quantile(densities, min_density)
mesh.remove_vertices_by_mask(vertices_to_remove)
open3d 效果图
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],
zoom=0.664,
front=[-0.4761, -0.4698, -0.7434],
lookat=[1.8900, 3.2596, 0.9284],
up=[0.2304, -0.8825, 0.4101])
Surface normal estimation
表面法线估计
源码
mesh.compute_vertex_normals()
open3D 可视化
print("Computing normal and rendering it.")
mesh.compute_vertex_normals()
print(np.asarray(mesh.triangle_normals))
o3d.visualization.draw_geometries([mesh])
源码
def preprocess_cloud(pcd, max_nn=20, normals=None):
# 复制点云数据
cloud = deepcopy(pcd)
# 如果需要估算法线
if normals:
params = o3d.geometry.KDTreeSearchParamKNN(max_nn)
cloud.estimate_normals(params)
# 将法线朝向相机位置
cloud.orient_normals_towards_camera_location()
return cloud
open3D
open3d.geometry.KDTreeSearchParamKNN(knn=20) # 计算近邻的20个点
import open3d
import numpy as np
import mayavi.mlab as mlab
# 4. 法向量的计算
def open3d_vector_compute():
pcd_path = r"E:\xxxx\open3d_xxxx\ICP_data\cloud_bin_0.pcd"
pcd = open3d.io.read_point_cloud(pcd_path)
pcd.estimate_normals(
search_param=open3d.geometry.KDTreeSearchParamHybrid(radius=0.01, max_nn=30)
)
normals = np.array(pcd.normals) # 法向量结果与点云维度一致(N, 3)
points = np.array(pcd.points)
print(normals.shape, points.shape)
# 验证法向量模长为1(模长会有一定的偏差,不完全为1)
normals_length = np.sum(normals**2, axis=1)
flag = np.equal(np.ones(normals_length.shape, dtype=float), normals_length).all()
print('all equal 1:', flag)
# 法向量可视化
open3d.visualization.draw_geometries([pcd],
window_name="Open3d",
point_show_normal=True,
width=800, # 窗口宽度
height=600) # 窗口高度
if __name__ == '__main__':
open3d_vector_compute()
参考连接
github :连接
open3D 官网