基于Open3D的点云处理11-三维点云表面重建

news2024/12/24 9:56:02

点云表面重建

(1)显式建模方法:
Explicit reconstruction
例如:Delaunay 三角网、Alpha shapes
(2)隐式建模方法:
Implicit reconstruction
例如:径向基函数法、移动最小二乘法、泊松重建法等

Open3d实现的算法:

  • Alpha shapes
  • Ball pivoting
  • Poisson

显示建模

显示建模可以看作一个根据已知的数据采样点,建立几何拓扑关系的过程;

显示建模- Delaunay三角剖分

前苏联数学家 Delaunay于1934年提出,对于任意给定的平面点集,该方法遵循“ 最小角最大 ” 和“ 空外接圆 ” 准则进行剖分。
Delaunay 三角网是Voronoi图的伴生图形,通过连接具有公共顶点的三个V n多边形的生长中心而生成的, 这个公共顶点就是形成的Delaunay三角形外接圆的圆心。
在这里插入图片描述
算法流程:

  1. 先将点云通过法线投影到某一二维坐标平面内;
  2. 然后对投影得到的点云做平面内的三角化,从而得到各点的拓扑连接关系(基于Delaunay三角剖分 );
  3. 最后根据平面内投影点的拓扑连接关系确定各原始三维点间的拓扑连接,所得三角网格即为重建得到的曲面模型;

PCL中的贪婪三角化算法pcl::GreedyProjectionTriangulation使用的是Delaunay三角剖分;

Delaunay三角剖分适用于地貌分析;在这里插入图片描述

显示建模- alpha-shape

计算几何中,alpha shape(α-shape)是描述欧氏平面有限点集形状的一组分段线性简单曲线
算法流程如下:
(1)点云预处理。计算并减去点云质心坐标,将点云移动至坐标轴中心;计算点云特征值和特征向量,对点云做旋转变换(只有2D点云需要做旋转变换)
(2)计算Delaunay三角网。调用qhull库,通过qh_new_qhull函数计算点云在4D空间的凸包
(3)计算每个单纯形的中心。调用qhull库,通过qh_setvoronoi_all函数计算每个单纯形(四面体/三角形)的球心/圆心
(4)确定Alpha Complexes。3D时,遍历土堡中位于下边界(Delaunay三角网)的四面体,计算四面体外接球半径r,若r<α,则保存该四面体的4个三角形边界;若r>=α,则找出四面体中满足要求的三角形并保存。2D时,遍历Delaunay三角网中的三角形,计算三角形外接圆半径r,若r<α,则保存该三角形的3条边,否则跳过(可能单独留下一条边没有什么意义)
(5)确定alpha shape。3D时,遍历Alpha Complexes中所有三角形,若相邻的三角形中有不属于Alpha Complexes的,则为边界三角形,保存下来。2D时,遍历所有边,若相邻边有不属于Alpha Complexes的,则为边界边,保存下来
(6)将点云旋转回来,并加回质心坐标。
在这里插入图片描述
Open3d实现了该算法,接口为create_from_point_cloud_alpha_shape其中包含了一个权重参数 alpha。

import open3d as o3d
mesh = o3d.io.read_triangle_mesh("BunnyMesh.ply")
mesh.compute_vertex_normals()

pcd = mesh.sample_points_poisson_disk(750)
o3d.visualization.draw_geometries([pcd])

# alpha-shape 算法 
alpha = 0.2
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.01,效果如下图:
在这里插入图片描述
调整权重参数 alpha = 0.01,且 pcd = mesh.sample_points_poisson_disk(3000), 效果如下图:
在这里插入图片描述

显示建模-Ball Pivoting-滚球法

球旋转算法 (BPA) [Bernardini1999] 是一种与 alpha 形状相关的表面重建方法。 直观地,想象一个具有给定半
径的 3D 球,我们将其放在点云上。 如果它击中任何 3 个点(并且它没有穿过这 3 个点),它会创建一个三
角形。 然后,算法从现有三角形的边缘开始旋转,每次它击中球没有落下的 3 个点时,我们都会创建另一个
三角形。主要思想:想象一个半径为R的球在点云上不停滚动,掠过(不漏下去)的地方建立连接关系形成边、面。
在这里插入图片描述
Open3D 在 create_from_point_cloud_ball_pivoting 中实现了这个方法。该方法接受半径列表作为参数,该参数对应于在点云上旋转的单个球的半径。(该算法假设PointCloud具有法线)

在这里插入代码片

在这里插入图片描述

隐式建模

隐式表面建模对应的是一个插值问题,根据已知的有限的数据采样点,求解连续表面上的未知点的函数值。

隐式建模-Poisson reconstruction-泊松重建

泊松曲面重建方法 [Kazhdan2006] 解决正则化优化问题以获得光滑曲面。出于这个原因,泊松曲面重建可能比上述方法更可取,因为它们会产生不平滑的结果,因为 PointCloud 的点也是生成的三角形网格的顶点,无需任何修改。
核心思想:点云代表了物体表面的位置,其法向量代表了内外的方向。通过隐式地拟合一个由物体派生的指示函数,可以给出一个平滑的物体表面的估计。
Open3D 实现了 create_from_point_cloud_poisson 方法,它基本上是 Kazhdan 代码的包装器。该函数的一个重要参数是深度,它定义了用于表面重建的八叉树的深度,因此意味着生成的三角形网格的分辨率。高的深度值意味着具有更多细节的网格。(该算法假设PointCloud具有法线)

import open3d as o3d
import numpy as np
pcd = o3d.io.read_point_cloud("EaglePointCloud.ply")

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

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/758519.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【QT】——Base64加解密

介绍 用 记事本 打开 exe、jpg、pdf 这些文件时&#xff0c;我们都会看到一大堆乱码&#xff0c;因为二进制文件包含很多无法显示和打印的字符。如果要让记事本这样的文本处理软件 能 处理二进制数据&#xff0c;如使用 json 保存二进制信息&#xff0c;需要先把数据先做一个 …

微服务 云原生:搭建 K8S 集群

为节约时间和成本&#xff0c;仅供学习使用&#xff0c;直接在两台虚拟机上模拟 K8S 集群搭建 踩坑之旅 系统环境&#xff1a;CentOS-7-x86_64-Minimal-2009 镜像&#xff0c;为方便起见&#xff0c;直接在 root 账户下操作&#xff0c;现实情况最好不要这样做。 基础准备 关…

数据在内存中的存储1(C语言进阶)

数据在内存中的存储 1.数据类型介绍1.1类型的基本归类&#xff1a;整形家族浮点数家族构造类型指针类型空类型 2.整形在内存中的存储2.1 原码、反码、补码2.2 大小端介绍为什么有大端和小端&#xff1a; 我们今天来学习数据在内存中的存储 1.数据类型介绍 前面我们已经学习了基…

TCP三次握手四次挥手

文章目录 TCP 三次握手和四次挥手1、三次握手过程image-202307100943094972、为什么要三次握手3、第 2 次握手传回了 ACK&#xff0c;为什么还要传回 SYN&#xff1f;4、断开连接-TCP 四次挥手5、为什么要四次挥手6、丢包问题7、为什么不能把服务器发送的 ACK 和 FIN 合并起来&…

qt开发技巧之嵌入式linux qt按钮点击触发两次

1.问题 移植qt5.12.9到嵌入式linux系统&#xff0c;tslib作为触摸输入&#xff0c;开发平台是imx6ull&#xff0c;点击pushbutton按钮会出现触发两次点击的情况。 2.解决 vi /etc/profile&#xff0c;在 /etc/profile里添加环境变量&#xff0c;禁止QT自带输入检测&#xff0…

vue-watch监听器

1. 概述 watch是 vue 中常用的监听器&#xff0c;它主要用于侦听数据的变化&#xff0c;在数据发生变化的时候执行一些操作。 Vue官网很明确的建议我们这样使用watch侦听属性&#xff1a;当需要在数据变化时执行异步或开销较大的操作时&#xff0c;这个方式是最有用的。 2. 用…

【通览一百个大模型】XLNet(Google)

XLNet 欢迎订阅阅读【大模型&NLP&算法】。 作者&#xff1a;王嘉宁本文章内容为转载或整理&#xff1b;仓库链接&#xff1a;https://github.com/wjn1996/LLMs-NLP-Algo 【通览一百个大模型】XLNet&#xff08;Google&#xff09; 作者&#xff1a;王嘉宁&#xff0…

lua脚本语言学习笔记

Lua 是一种轻量小巧的脚本语言&#xff0c;用标准C语言编写并以源代码形式开放&#xff0c; 其设计目的是为了嵌入应用程序中&#xff0c;从而为应用程序提供灵活的扩展和定制功能。 因为我们使用redis的时候一般要写lua脚本&#xff0c;这篇文章就介绍一下lua脚本语言的基础用…

Python 算法基础篇:时间复杂度和空间复杂度简介

Python 算法基础篇&#xff1a;时间复杂度和空间复杂度简介 引言 1. 时间复杂度 a ) 常见的时间复杂度 b ) 时间复杂度示例 2. 空间复杂度 a ) 常见的空间复杂度 b ) 空间复杂度示例 结论 引言 在学习和分析算法时&#xff0c;时间复杂度和空间复杂度是两个关键概念。它们帮助…

【Python】类型注解 ④ ( 函数类型注解 | 函数形参类型注解语法 | 函数返回值类型注解 )

文章目录 一、函数形参类型注解1、函数中由于类型缺省导致的提示问题2、函数形参类型注解语法3、代码示例 - 函数形参类型注解 二、函数返回值类型注解1、函数返回值类型注解语法2、代码示例 - 函数返回值类型注解 一、函数形参类型注解 1、函数中由于类型缺省导致的提示问题 由…

LSTM对比Bi-LSTM的电力负荷时间序列预测(Matlab)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

小程序api的promise化

小程序根目录cmd运行安装命令 npm install --save miniprogram-api-promise1.0.4 安装完成之后先到根目录中删除miniprogram_npm文件夹(不删除构建npm时可能会出现问题) 删除之后再在工具中点击构建npm 构建成功之后会看到根目录中重新出现了miniprogram_npm文件夹 在app.j…

P1747 好奇怪的游戏

好奇怪的游戏 题目背景 《爱与愁的故事第三弹shopping》娱乐章。 调调口味来道水题。 题目描述 爱与愁大神坐在公交车上无聊&#xff0c;于是玩起了手机。一款奇怪的游戏进入了爱与愁大神的眼帘&#xff1a;***&#xff08;游戏名被打上了马赛克&#xff09;。这个游戏类似…

修复漏洞(三)升级Docker里面的镜像(MySQL、Nginx等)

前言 因原版本检测出来存在漏洞&#xff0c;故需升级底层镜像 步骤 先看看自己现在的是什么版本&#xff0c;教你们一个骚操作&#xff0c;查看Docker里面的Mysql或者其他容器版本都不用百度出来的这么麻烦首先docker images&#xff0c;查看镜像ID然后docker inspect 镜像I…

2、Java入门教程【IDEA】

1、下载 IDEA社区版&#xff1a;下载地址 IDEA管理JAVA程序的结构&#xff1a; project 项目、工程module 模块package 包class 类 2、创建工程 创建【project】 点击【create】后&#xff0c;项目结构如下&#xff1a; 创建【package】 我们继续在【src】目录下创建【pack…

Python中的break和continue语句应用举例

Python中的break和continue语句应用举例 在进行Python编程时候&#xff0c;有时需要&#xff0c;对循环中断或跳过某部分语句&#xff0c;此时常会用到break语句或continue语句。本文将通过实际例子阐述这两个语句的用法。 1.break语句 break语句是实现在某个地方中断循环&a…

js逆向补环境-b站志远二期最后8节课笔记

目录 一、基础知识1、什么是纯净V82、什么是BOM和DOM3、node环境/浏览器环境/V8引擎区别4、如何本地调试js补环境5、补环境相对于逆向算法的好处6、vm和vm2介绍 二、8个视频内容笔记概括1、补环境基本知识/头条案例手动插桩补2、Proxy代理/toString函数保护介绍3、补环境框架设…

安卓UI:Switch和ToggleButton

目录 一、Switch和ToggleButton介绍 Switch常用属性&#xff1a; ToggleButton属性&#xff1a; 二、Switch和ToggleButton常用方法 Switch常用方法&#xff1a; ToggleButton常用方法&#xff1a; 三、Switch和ToggleButton的使用 MainActivity: activity_main&#xff1…

【代码随想录 | Leetcode | 第四天】数组 | 螺旋矩阵 | 59

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来螺旋矩阵的分享✨ 目录 前言59. 螺旋矩阵 II总结 59. 螺旋矩阵 II 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 …

【C语言进阶(八)】动态内存管理

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C语言学习分享⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C语言知识   &#x1f51d;&#x1f51d; 动态内存规划 1. 前言2. 为什么要学…