首页 > 编程语言 >三维点云中常用的表面重建算法

三维点云中常用的表面重建算法

时间:2024-07-25 18:25:33浏览次数:13  
标签:__ 三维 凸包 算法 表面 云中 o3d pcd 重建

表面重建算法起源于计算机视觉和计算几何学领域。早期的研究集中在从二维图像中提取三维信息。然而,随着三维扫描技术的进步,越来越多的研究转向了如何从点云数据中重建表面。三维点云表面重建技术的发展,始于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形状。具体实现方法如下:

  1. 计算点集的Delaunay三角剖分。

  2. 删除至少有一条边的长度超过的所有三角形。

  3. 保留剩余的三角形作为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等方法重建了点云的表面。

应用领域和场景

三维点云表面重建算法广泛应用于多个领域:

  1. 文物保护:用于数字化和重建文物表面,方便研究和展示。

  2. 医疗影像:在CT和MRI图像中重建人体器官的三维模型,辅助诊断和手术规划。

  3. 机器人导航:帮助机器人理解环境的三维结构,实现自主导航。

  4. 计算机动画:在电影和游戏中创建逼真的三维模型和场景。

三维点云表面重建算法在多个领域有广泛的应用和重要性。了解这些算法的原理和应用场景,不仅能帮助我们更好地使用这些技术,还能激发我们在更多领域的创新和探索。

以上内容总结自网络,如有帮助欢迎关注与转发,我们下次再见!

标签:__,三维,凸包,算法,表面,云中,o3d,pcd,重建
From: https://blog.csdn.net/Argulo/article/details/140613238

相关文章

  • 从信息论的角度看微博推荐算法
    引言在数字时代,推荐系统已成为社交媒体和其他在线服务平台的核心组成部分。它们通过分析用户行为和偏好,为用户提供个性化的内容,从而提高用户满意度和平台的参与度。推荐系统不仅能够增强用户体验,还能显著提升广告投放的效率和效果。随着技术的不断进步,信息论在推荐系统中的......
  • 文心一言 VS 讯飞星火 VS chatgpt (310)-- 算法导论22.2 8题
    八、我们将一棵树T=(V,E)......
  • Day23 回溯算法Part02
    39.组合总和与216.组合总和III不同,不要求每个数字仅能使用一次。但这样很容易出现重复的结果,剪枝还是要注意。不过这道题让我更认识到把回溯问题看成是一个多叉树的遍历的问题,当遇到一个题目,先画出它的树结构,也就是代码随想录中的这张图,for循环(横向遍历)怎么做,递归(纵向遍历)......
  • 「代码随想录算法训练营」第二十天 | 回溯算法 part2
    39.组合总和题目链接:https://leetcode.cn/problems/combination-sum/题目难度:中等文章讲解:https://programmercarl.com/0039.组合总和.html视频讲解:https://www.bilibili.com/video/BV1KT4y1M7HJ题目状态:久违的通过!思路:使用回溯模板,在单层循环时判断当前数组值是否大于......
  • python cobs协议编解码算法demo
    1.SummaryCOBS(ConsistentOverheadByteStuffing)是一种算法,直译为一致的开销字节填充。简而言之,无论数据包的内容如何,都能通过产生高效可靠明确的数据包帧,从而使接受端能够从损坏的包中恢复。通常使用0x00来作为数据包的分隔符,即切割数据包的片分隔符。当使用0x00作为......
  • 基于生物地理学算法优化的TSP问题求解
    智能优化算法应用:基于生物地理学算法的TSP问题求解-附代码文章目录智能优化算法应用:基于生物地理学算法的TSP问题求解-附代码1.TSP问题3.生物地理学算法4.实验参数设定5.算法结果6.Matlab代码7.Python代码摘要:TSP是数学领域内一道著名的难题之一,如何求解一直是......
  • 基于旗鱼算法优化的TSP问题求解
    智能优化算法应用:基于旗鱼算法的TSP问题求解-附代码文章目录智能优化算法应用:基于旗鱼算法的TSP问题求解-附代码1.TSP问题3.旗鱼算法4.实验参数设定5.算法结果6.Matlab代码7.Python代码摘要:TSP是数学领域内一道著名的难题之一,如何求解一直是学术界研究的热点问......
  • ADC滤波的10种经典算法
    A、方法:根据经验判断,确定两次采样允许的最大偏差值(设为A)每次检测到新值时判断:如果本次值与上次值之差<=A,则本次值有效如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值B、优点:能有效克服因偶然因素引起的脉冲干扰C、缺点无法抑制那种周期性的干扰......
  • 文心一言 VS 讯飞星火 VS chatgpt (309)-- 算法导论22.2 7题
    七、职业摔跤手可以分为两种类型:“娃娃脸”(“好人”)型和“高跟鞋”(“坏人”)型。在任意一对职业摔跤手之间都有可能存在竞争关系。假定有n个职业摔跤手,并且有一个给出竞争关系的r对摔跤手的链表。请给出一个时间为O(n+r)的算法来判断是否可以将某些摔跤手划分为“......
  • 算法力扣刷题记录 五十九【450.删除二叉搜索树中的节点】
    前言记录五十八【701.二叉搜索树中的插入操作】保证插的新节点在叶子节点的位置,如此实现递归。那么【450.删除二叉搜索树中的节点】删除如何实现?还有简单的方法吗?一、题目阅读给定一个二叉搜索树的根节点root和一个值key,删除二叉搜索树中的key对应的节点,并保证二......