在许多情况下,我们希望生成密集的 3D 几何图形,即三角形网格。但是,从多视图立体方法或深度传感器中,我们只能获得非结构化点云。要从这个非结构化输入中获得三角形网格,我们需要执行表面重建。在文献中存在几种方法,Open3D 目前实现了以下方法:
Alpha shapes [Edelsbrunner1983]
Ball pivoting [Bernardini1999]
Poisson surface reconstruction [Kazhdan2006]
Alpha 形状 [Edelsbrunner1983] 是凸包的推广。
Open3D实现了涉及权衡参数alpha的方法 create_from_point_cloud_alpha_shape。这个函数包含两种情况
open3d.geometry.TriangleMesh create_from_point_cloud_alpha_shape(pcd, alpha) |
函数功能: Alpha 形状是凸包的概括。随着 alpha 值的降低,形状会收缩并产生空腔。 |
参数: pcd (open3d.geometry.PointCloud):从中重建 TriangleMesh 表面的 PointCloud alpha (float):控制形状的参数。一个非常大的值将给出一个接近凸包的形状 |
返回: open3d.geometry.TriangleMesh |
open3d.geometry.TriangleMesh create_from_point_cloud_alpha_shape(pcd,alpha,tetra_mesh,pt_map) |
函数功能: Alpha 形状是凸包的概括。随着 alpha 值的降低,形状会缩小并产生空洞。 |
参数: pcd (open3d.geometry.PointCloud):从中重建 TriangleMesh 表面的 PointCloud alpha (float):控制形状的参数。一个非常大的值将给出一个接近凸包的形状 tetra_mesh (open3d.geometry.TetraMesh):如果不是 None,则使用它来构造 alpha 形状。否则,从 pcd 计算 TetraMesh pt_map (List[int]):从 tetra_mesh 顶点索引到 pcd 点的可选映射 |
返回: open3d.geometry.TriangleMesh |
该实现基于点云的凸包。如果我们想从给定的点云计算多个 alpha 形状,那么我们可以通过只计算一次凸包并将其传递给 create_from_point_cloud_alpha_shape 来节省一些计算。
球旋转算法 (BPA) [Bernardini1999] 是一种与 alpha 形状相关的表面重建方法。直观地,想象一个具有给定半径的 3D 球,我们将其放在点云上。如果它击中任何 3 个点(并且它没有穿过这 3 个点),它会创建一个三角形。然后,算法从现有三角形的边缘开始旋转,每次它击中球没有落下的 3 个点时,我们都会创建另一个三角形。
Open3D 在 create_from_point_cloud_ball_pivoting 中实现了这个方法。该方法接受半径列表作为参数,该参数对应于在点云上旋转的单个球的半径。(该算法假设PointCloud具有法线)
open3d.geometry.TriangleMesh create_from_point_cloud_ball_pivoting(pcd, radii) |
函数功能: 从定向点云计算三角形网格的函数。表面重建是通过在点云上滚动一个给定半径的球来完成的,每当球接触三个点时,就会创建一个三角形。 |
参数: pcd (open3d.geometry.PointCloud):从中重建 TriangleMesh 表面的 PointCloud。必须包含法线 radii (open3d.utility.DoubleVector):用于表面重建的球的半径 |
返回: open3d.geometry.TriangleMesh |
泊松曲面重建方法 [Kazhdan2006] 解决正则化优化问题以获得光滑曲面。出于这个原因,泊松曲面重建可能比上述方法更可取,因为它们会产生不平滑的结果,因为 PointCloud 的点也是生成的三角形网格的顶点,无需任何修改。
Open3D 实现了 create_from_point_cloud_poisson 方法,它基本上是 Kazhdan 代码的包装器。该函数的一个重要参数是深度,它定义了用于表面重建的八叉树的深度,因此意味着生成的三角形网格的分辨率。高的深度值意味着具有更多细节的网格。(该算法假设PointCloud具有法线)
open3d.geometry.TriangleMesh create_from_point_cloud_poisson(pcd, depth=8, width=0, scale=1.1, linear_fit=False, n_threads=- 1) |
函数功能: 从定向的 PointCloud pcd 计算三角形网格的函数。该函数使用 Kazhdan的原始实现。见 https://github.com/mkazhdan/PoissonRecon |
参数: pcd (open3d.geometry.PointCloud):从中重建 TriangleMesh 表面的 PointCloud。必须包含法线 depth (int, optional, default=8):将用于表面重建的树的最大深度。在深度 d 处运行对应于在分辨率不大于 2^d x 2^d x 2^d 的网格上求解。请注意,由于重建器使八叉树适应采样密度,因此指定的重建深度只是一个上限 width (float, optional, default=0):指定最细级别八叉树单元的目标宽度。如果指定了深度,则忽略此参数 scale (float, optional, default=1.1):指定用于重建的立方体的直径与样本边界立方体的直径之间的比率 linear_fit (bool, optional, default=False):如果为真,重构器将使用线性插值来估计等顶点的位置 n_threads (int, optional, default=-1):用于重建的线程数。设置为 -1 以自动确定它 |
返回: Tuple[open3d.geometry.TriangleMesh,open3d.utility.DoubleVector] |
泊松曲面重建还将在点密度低的区域创建三角形,甚至外推到某些区域。
create_from_point_cloud_poisson 函数具有第二个密度返回值,该值指示每个顶点的密度。低密度值意味着顶点仅由输入点云中的少量点支持。
并不是所有的点云都已经带有相关的法线。Open3D 可用于估计点云法线的estimate_normals(在1.3章节已经做过笔记),它在本地拟合每个 3D 点的平面以导出法线。但是,估计的法线可能不会始终如一地定向。
orient_normals_consistent_tangent_plane 使用最小生成树传播法线方向。
open3d.geometry.PointCloud orient_normals_consistent_tangent_plane(self, k) |
函数功能: 相对于一致切平面定向法线的功能 |
参数: k (int):用于构建用于传播法向方向的黎曼图(Riemannian graph)的 k 最近邻的数量 |
返回: None |