Open3d之表面重建

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

Alpha shapes

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

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

# -*- coding: UTF-8 -*-

import numpy as np
import open3d as o3d
import Open3D.examples.python.open3d_tutorial as o3dtut

# 加载网格
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.010.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.

在这里插入图片描述

法线估计

在上面的示例中,我们假设点云的法线朝外。但是,并非所有的点云都已经具有关联的法线。Open3D可用于使用带有Estimate_Normals的点云法线来估计点云法线,该局部法线适合每个3D点的平面以导出法线。但是,估计的法线可能未始终一致。 orient_normals_consistent_tangent_plane使用最小生成树传播法线方向。

gt_mesh = o3dtut.get_bunny_mesh()
pcd = gt_mesh.sample_points_poisson_disk(5000)
pcd.normals = o3d.utility.Vector3dVector(np.zeros(
    (1, 3)))  # invalidate existing normals

pcd.estimate_normals()
o3d.visualization.draw_geometries([pcd], point_show_normal=True)
pcd.orient_normals_consistent_tangent_plane(100)
o3d.visualization.draw_geometries([pcd], point_show_normal=True)

 

  • 13
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Python中的Open3D是一个开源的库,用于处理和可视化3D几何数据。Open3D提供了一系列用于三维重建的功能和工具。 首先,我们需要将3D场景中的物体或场景转化为点云数据。可以通过Open3D的函数从不同的数据源(如RGB-D相机、激光扫描仪或三角测量仪)中提取点云数据。 接下来,可以使用Open3D的函数对点云数据进行预处理。例如,可以对点云进行滤波和降采样,以去除噪声和减小点云数据的数量。 然后,可以使用Open3D的函数将点云数据转化为网格数据。通过将点云数据转化为网格,可以更方便地进行后续操作,如曲面重建和模型修补。 在进行三维重建时,可以使用Open3D的函数进行表面重建Open3D提供了不同的算法,如法线重建、有向距离函数(SDF)重建和三角剖分等,用于生成平滑的表面模型。 在重建完成后,可以使用Open3D的可视化工具对重建的模型进行可视化。可以从不同的视角查看和旋转模型,以及应用材质和纹理来增强模型的真实感。 最后,在进行3D重建时,还可以使用Open3D的其他功能,如点云配准(ICP、全局配准)、曲线拟合、点云分割和对象检测等,以进一步完善重建过程。 总结来说,通过使用Open3D库,可以方便地进行3D重建。从采集点云数据到预处理、重建和可视化,Open3D提供了一系列功能和工具,使得三维重建变得更加简单和高效。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值