Open3d学习计划——高级篇 9(表面重建)

Open3d学习计划——高级篇 9(表面重建)

在许多场景下我们希望生成密集的3D几何形状,比如三角网格。然而从多视图立体算法和深度传感器中我们只能够获得非结构化的点云数据。我们需要使用表面重建算法来从非结构化的输入中得到三角网格。Open3d实现了文献中已有的算法:

Alpha shapes

alpha shape [Edelsbrunner1983]是凸包的概括。如这里所介绍的,可以直观地将Alpha shapes理解为以下内容:想象有一个包含有巧克力硬块的巨大冰淇凌,巧克力硬块是点 S S S。用一种球形的冰淇淋勺,可以在不碰到巧克力块的情况下挖出冰淇淋的所有部分,甚至可以在内部挖出一些孔(比如一些在外部移动勺子无法触及的部分。)我们最终得到一个以帽盖,弧线和点为边界的对象(不一定是凸的)。如果我们将所有的圆面都拉成三角形和线段,则可以直观的描述点 S S S的alpha shape。

Open3d实现了该算法,接口为create_from_point_cloud_alpha_shape其中包含了一个权重参数 alpha

mesh = o3dtut.get_bunny_mesh()
pcd = mesh.sample_points_poisson_disk(750)
o3d.visualization.draw_geometries([pcd])
alpha = 0.03
print(f"alpha={alpha:.3f}")
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(
    pcd, alpha)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh], mesh_show_back_face=True)

在这里插入图片描述

alpha-0.030

在这里插入图片描述
这个算法是基于点云的凸包算法实现的。如果我们想从给定的点云中计算多个alpha shapes,我们只需要计算一次凸包并将其传递给create_from_point_cloud_alpha_shape,这样可以节省一些计算。

tetra_mesh, pt_map = o3d.geometry.TetraMesh.create_from_point_cloud(pcd)
for alpha in np.logspace(np.log10(0.5), np.log10(0.01), num=4):
    print(f"alpha={alpha:.3f}")
    mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(
        pcd, alpha, tetra_mesh, pt_map)
    mesh.compute_vertex_normals()
    o3d.visualization.draw_geometries([mesh], mesh_show_back_face=True)

alpha=0.500

在这里插入图片描述

alpha=0.136

在这里插入图片描述

alpha=0.037

在这里插入图片描述

alpha=0.010

在这里插入图片描述

滚球法

与alpha shape相关的一种表面重建算法是滚球法(ball pivoting algorithm,BPA)。直观的讲,我们想象有一个给定半径的3D球,将其放到点云数据上。如果这个球碰到了三个点(并且不会在回到这三个点),那我们就创造一个三角形。之后呢,我们的球开始沿着已有三角形的边开始滚动,每次碰到不重复的三个点时就会创造一个三角形。
Open3d在接口create_from_point_cloud_ball_pivoting中实现了该算法。这个算法有一个接受的列表参数radii,这个列表会创建若干个不同半径的独立的球,之后开始在点云上滚动。

注意:这个算法需要点云包含法线参数。


gt_mesh = o3dtut.get_bunny_mesh()
gt_mesh.compute_vertex_normals()
pcd = gt_mesh.sample_points_poisson_disk(3000)
o3d.visualization.draw_geometries([pcd], point_show_normal=True)

radii = [0.005, 0.01, 0.02, 0.04]
rec_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(
               pcd, o3d.utility.DoubleVector(radii))
o3d.visualization.draw_geometries([pcd, rec_mesh])

在这里插入图片描述在这里插入图片描述

泊松表面重建

表面重建算法会产生不平滑的结果,这是因为点云的点也是三件网格的顶点。无需进行任何修改。泊松表面重建算法 [Kazhdan2006]
解决了正规优化的问题,这样就可以产生光滑的表面。

Open3d实现了算法接口create_from_point_cloud_poisson,该接口基本上是Kazhdan实现的代码接口的封装。这个接口有一个重要的参数就是depthdepth定义了用于重建的八叉树的深度。较高的depth值意味着网格有着较高的细节。

Note:
这个算法要求点云包含法线信息。

pcd = o3dtut.get_eagle_pcd()
print(pcd)
o3d.visualization.draw_geometries([pcd], zoom=0.664,
                                  front=[-0.4761, -0.4698, -0.7434],
                                  lookat=[1.8900, 3.2596, 0.9284],
                                  up=[0.2304, -0.8825, 0.4101])

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])

downloading eagle pcl
geometry::PointCloud with 796825 points.

在这里插入图片描述

run Poisson surface reconstruction
geometry::TriangleMesh with 563112 points and 1126072 triangles.

在这里插入图片描述
泊松表面重建还将在低密度的点云中创建三角形,甚至可以推断出一些区域(比如上面输出的底座的边缘)。函数create_from_point_cloud_poisson还有第二个返回的值densities来表示每个顶点的密度。低密度值意味着这个顶点只从输入的点云中收到少量点的支持。

下面的代码我们通过伪彩可视化了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], zoom=0.664,
                                  front=[-0.4761, -0.4698, -0.7434],
                                  lookat=[1.8900, 3.2596, 0.9284],
                                  up=[0.2304, -0.8825, 0.4101])

visualize densities

在这里插入图片描述
我们可以通过密度值来筛选掉那些具有比较低的支持率的顶点和三角形。
下面的代码中我们移除了所有密度值低于 0.01 0.01 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], zoom=0.664,
                                  front=[-0.4761, -0.4698, -0.7434],
                                  lookat=[1.8900, 3.2596, 0.9284],
                                  up=[0.2304, -0.8825, 0.4101])

remove low density vertices
geometry::TriangleMesh with 557480 points and 1113214 triangles.

在这里插入图片描述

关于翻译大家有更好的意见欢迎评论一起学习!!!

欢迎大家加入知识星球一起学习。

在这里插入图片描述

  • 12
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
open3d是一个用于处理三维数据(点云、三维模型等)的开源库。点云配准是将两个或多个点云数据进行对齐的过程,以便在一个全局坐标系下进行比较、分析或重建。其中,四元数法是一种常用的点云配准方法。 四元数是一种用四个实数表示的扩充复数,可以用于描述旋转变换。在点云配准中,使用四元数法是因为其具有以下优势: 第一,四元数具有紧凑的表示形式,只需要四个实数即可表示旋转变换,相较于旋转矩阵的九个实数表示方式节省了存储空间,降低了计算复杂度。 第二,四元数法能够有效地避免了“万向锁”问题。万向锁是指在使用欧拉角进行坐标变换时,由于旋转过程中会出现奇点,导致旋转角度无法精确表示的问题。而四元数法不会出现这个问题,具有更好的数值稳定性。 在open3d中,点云配准的四元数法通常有以下几个步骤: 首先,计算两个点云之间的特征描述子,例如FPFH(Fast Point Feature Histograms)或SHOT(Signature of Histograms of Orientations)。这些描述子能够表示点云的局部几何信息。 然后,根据特征描述子的相似性,寻找初始的点对应关系。 接下来,通过最小化点云之间的误差指标,例如最小化点到平面的距离或最小化点到点的距离,来优化点对应关系,并计算出旋转矩阵。 将旋转矩阵转换为四元数表示,即可完成点云的配准过程。 四元数法是open3d中常用的点云配准方法之一,其能够高效地实现点云的准确对齐。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值