表面重建算法起源于计算机视觉和计算几何学领域。早期的研究集中在从二维图像中提取三维信息。然而,随着三维扫描技术的进步,越来越多的研究转向了如何从点云数据中重建表面。三维点云表面重建技术的发展,始于20世纪90年代,主要推动力是激光扫描和结构光扫描的广泛应用。
Result of 3D reconstruction with inputs from drone video footage. Figure from Neuralangelo paper (Li et.al. 2023),IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2023
凸包Convex Hull
ConvexHull3D:https://mathworld.wolfram.com/ConvexHull.html
在了解点云表面重建算法前,我们需要知道什么是凸包。凸包是包含所有点的最小凸多边形或多面体,而表面重建则是从点云数据中重建出原始物体的表面。并且凸包是包覆这群点的所有外壳当中,表面积和体积最小的一个外壳,而最小的外壳一定是凸的。虽然凸包是最简单的表面重建形式,适用于点云分布在物体外表面的情况,但对于复杂几何形状需要更复杂的表面重建算法,如Delaunay三角剖分、Poisson表面重建等。这些方法能够处理具有凹陷或洞的物体,通过插值和拟合技术生成满足一定平滑性和几何特征的表面。
凸包(Convex Hull)背后的主要思想来自凸多边形的定义。提醒一下,凸多边形是所有内角都小于 180° 的多边形。通过这个定义,我们发现每个正多边形都是凸的。如果一个角度大于 180°,则该多边形被认为是凹的。凸包使用与凸多边形应用于点集相同的原理。例如,凸包是包含集合中所有点的最小凸多边形。
凸包的目的之一是修剪平面上的特定区域。它主用于计算机图形学、几何和导航。Jarvis March
是查找凸包的最流行和最简单的算法之一。它的简单的原理是探索一个集合中的 n 个点并返回围绕该集合的点的列表,这些点具有凸包的属性。这种方法在较好的情况下需要 O(nm) 的时间复杂度,其中 n 是探索的点数,m 是形成凸包形状的点数。在最坏的情况下,即 n = m,时间复杂度变为 O(n^2)。对于大数据集来说,这很容易变得非常大。要使用 Gift Warping 算法计算一组点的凸包,我们从已知位于凸包中的最左边的点 (对于 i = 0)开始。然后,我们选择另一个点 ,例如所有剩余的点都在点 和 之间绘制的线的右侧,然后我们循环重复,直到到达第一个点 。
Jarvis March:https://alphasldiallo.github.io/convex-hull-delaunay-triangulation-and-alpha-shapes/
常用的表面重建方法
表面重建算法的数学原理通常涉及几何和拓扑学。以下是常用的表面重建方法:
Alpha形状构建
给定一组任意分布的数据点,有许多方法可以将它们组织成三角形网格。但并非所有可能的三角形网格都能很好地表示点之间的空间关系。右边的图像是 Delaunay 三角剖分的示例。除了美观之外,Delaunay 还具有许多有利的特性,这些特性由 Boris Delaunay 于 1934 年和其他研究人员证明。https://gwlucastrig.github.io/TinfourDocs/DelaunayIntro/index.html
通过Delaunay三角剖分,我们可以找到一组点的Alpha形状。具体实现方法如下:
-
计算点集的Delaunay三角剖分。
-
删除至少有一条边的长度超过的所有三角形。
-
保留剩余的三角形作为Alpha形状的一部分。
Alpha Shapes算法基于Delaunay三角剖分,它通过一个参数来控制形状的细节程度。
若足够小则包含点对的圆不会包含其他点则是一个边
这种强大的方法用于概括包含一组点的边界多边形。下图中作者根据收集的运动轨迹生成了楼层平面图。如下图所示,与凸包不同,alpha 形状可以更精确地找到一组点的准确轮廓。该算法主要用于计算几何,尤其是在处理 3D 形状时。
用凸包和 alpha 形状构建平面图的图示
import open3d as o3d
from copy import deepcopy
if __name__ == '__main__':
file_path = 'rabbit.pcd'
pcd = o3d.io.read_point_cloud(file_path)
pcd = pcd.uniform_down_sample(50) # 每50个点采样一次
pcd.paint_uniform_color([0.5, 0.5, 0.5]) # 指定显示为灰色
print(pcd)
pcd1 = deepcopy(pcd)
pcd1.translate((20, 0, 0)) # 整体进行x轴方向平移20
mesh1 = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd1, alpha=2)
mesh1.paint_uniform_color([1.0, 0.6667, 0.0039]) # 指定颜色
print(mesh1)
o3d.visualization.draw_geometries([pcd, mesh1], # 点云列表
window_name="Alpha Shape 重建",
point_show_normal=False,
width=800, # 窗口宽度
height=600,
mesh_show_wireframe=True,
mesh_show_back_face=True,
) # 窗口高度
Ball Pivoting滚球算法
Ball Pivoting算法通过在点云上滚动一个球来构建表面。该算法依赖于球的半径,在滚动过程中连接球接触的点。
球半径确定了表面的细节和连接
import open3d as o3d
from copy import deepcopy
if __name__ == '__main__':
file_path = 'rabbit.pcd'
pcd = o3d.io.read_point_cloud(file_path)
pcd = pcd.uniform_down_sample(50) # 每50个点采样一次
pcd.paint_uniform_color([0.5, 0.5, 0.5]) # 指定显示为灰色
print(pcd)
pcd2 = deepcopy(pcd)
pcd2.translate((-20, 0, 0)) # 整体进行x轴方向平移-20
radius = 0.01 # 搜索半径
max_nn = 10 # 邻域内用于估算法线的最大点数
pcd2.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius, max_nn))
radii = [1, 2] # 半径列表
mesh2 = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(pcd2, o3d.utility.DoubleVector(radii))
mesh2.paint_uniform_color([0, 0, 1])
o3d.visualization.draw_geometries([pcd, mesh2], # 点云列表
window_name="Ball Pivoting 重建",
point_show_normal=False,
width=800, # 窗口宽度
height=600,
mesh_show_wireframe=True,
mesh_show_back_face=True,
) # 窗口高度
Poisson Surface Reconstruction
Poisson Surface Reconstruction算法通过解Poisson方程,从点云中重建表面。它将点云视为一个连续的标量场,利用梯度场的散度来重建表面。
其中, 是向量场, 是散度。
import open3d as o3d
import numpy as np
from copy import deepcopy
if __name__ == '__main__':
file_path = 'rabbit.pcd'
pcd = o3d.io.read_point_cloud(file_path)
pcd = pcd.uniform_down_sample(50) # 每50个点采样一次
pcd.paint_uniform_color([0.5, 0.5, 0.5]) # 指定显示为灰色
print(pcd)
pcd3 = deepcopy(pcd)
pcd3.translate((0, 20, 0)) # 整体进行y轴方向平移20
radius = 0.01 # 搜索半径
max_nn = 10 # 邻域内用于估算法线的最大点数
pcd3.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius, max_nn))
mesh3, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd3, depth=9)
vertices_to_remove = densities < np.quantile(densities, 0.35)
mesh3.remove_vertices_by_mask(vertices_to_remove)
mesh3.paint_uniform_color([1, 0, 0])
o3d.visualization.draw_geometries([pcd, mesh3], # 点云列表
window_name="Poisson 重建",
point_show_normal=False,
width=800, # 窗口宽度
height=600,
mesh_show_wireframe=True,
mesh_show_back_face=True,
) # 窗口高度
Voxel Grid
Voxel Grid方法通过将点云划分为规则的三维网格(体素),并在每个体素中估计表面法线和曲率来重建表面。
体素尺寸决定了重建的分辨率
import open3d as o3d
from copy import deepcopy
if __name__ == '__main__':
file_path = 'rabbit.pcd'
pcd = o3d.io.read_point_cloud(file_path)
pcd = pcd.uniform_down_sample(50) # 每50个点采样一次
pcd.paint_uniform_color([0.5, 0.5, 0.5]) # 指定显示为灰色
print(pcd)
pcd4 = deepcopy(pcd)
pcd4.translate((0, -20, 0)) # 整体进行y轴方向平移-20
pcd4.paint_uniform_color([0, 1, 1])
mesh4 = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd4, voxel_size=1)
o3d.visualization.draw_geometries([pcd, mesh4], # 点云列表
window_name="Voxel Grid 重建",
point_show_normal=False,
width=800, # 窗口宽度
height=600,
mesh_show_wireframe=True,
mesh_show_back_face=True,
) # 窗口高度
上述代码使用Alpha Shapes、Ball Pivoting、Poisson Surface Reconstruction和Voxel Grid等方法重建了点云的表面。
应用领域和场景
三维点云表面重建算法广泛应用于多个领域:
-
文物保护:用于数字化和重建文物表面,方便研究和展示。
-
医疗影像:在CT和MRI图像中重建人体器官的三维模型,辅助诊断和手术规划。
-
机器人导航:帮助机器人理解环境的三维结构,实现自主导航。
-
计算机动画:在电影和游戏中创建逼真的三维模型和场景。
三维点云表面重建算法在多个领域有广泛的应用和重要性。了解这些算法的原理和应用场景,不仅能帮助我们更好地使用这些技术,还能激发我们在更多领域的创新和探索。
以上内容总结自网络,如有帮助欢迎关注与转发,我们下次再见!
标签:__,三维,凸包,算法,表面,云中,o3d,pcd,重建 From: https://blog.csdn.net/Argulo/article/details/140613238