(12)点云数据处理学习——表面重建

news2024/11/20 8:30:05

1、主要参考

(1)官网的介绍

Surface reconstruction — Open3D 0.16.0 documentation

(2)大佬的blog

三维点云重建 — open3d python_Coding的叶子的博客-CSDN博客_三维点云重建

(3)视频

Surface Reconstruction of Point Clouds - Point Cloud Processing in Open3D with_哔哩哔哩_bilibili

2、表面重建(Surface reconstruction)

在许多情况下,我们想要生成一个密集的3D几何图形,例如,一个三角形网格(triangle mesh)。然而,从多视点立体方法,或深度传感器,我们只能得到一个非结构化的点云。为了从这个非结构化输入中得到一个三角形网格,我们需要执行曲面重构。在文献中有一些方法,Open3D目前实现如下:

  • Alpha shapes [Edelsbrunner1983]

  • Ball pivoting [Bernardini1999]

  • Poisson surface reconstruction [Kazhdan2006]

 2.1 alpha形状(Alpha shapes)

(1)原理

alpha shapes[Edelsbrunner1983]是凸包的一般化。正如这里所描述的,人们可以直观地认为alpha shapes如下:想象一个巨大的冰淇淋质量包含硬巧克力块点S。用这种球形的冰淇淋勺子,我们可以把冰淇淋块上所有我们够得到而不碰到巧克力块的部分都刻出来,甚至在里面也刻出了洞(例如,简单地从外面移动勺子就够不到的部分)。我们最终会得到一个(不一定是凸的)由帽、弧和点组成的对象。如果我们现在把所有的圆面拉直成三角形和线段,我们就有了一个直观的描述,叫做S的alpha shapes。

(2)

Alpha shapes 是一种散点外轮廓的提取方法。open3d中对应的函数为create_from_point_cloud_alpha_shape,其关键参数为alpha。alpha是该方法在搜索外轮廓时的半径大小。alpha值越小,网格的细节就越多,分辨率越高。  

 (3)主要函数

mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd, alpha=2)

(4)测试代码

没错,还是那支兔子

import open3d as o3d
import numpy as np

bunny = o3d.data.BunnyMesh()
mesh = o3d.io.read_triangle_mesh(bunny.path)
mesh.compute_vertex_normals()

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)

1)泊松磁盘采样点750的结果如下

2) alpha = 0.03时的重建结果

 该算法的实现基于点云的凸包。如果我们想从一个给定的点云计算多个alpha形状,那么我们可以通过只计算一次凸包并将其传递给create_from_point_cloud_alpha_shape来节省一些计算量。

 注意:下面不同alpha的测试代码

import open3d as o3d
import numpy as np

bunny = o3d.data.BunnyMesh()
mesh = o3d.io.read_triangle_mesh(bunny.path)
mesh.compute_vertex_normals()

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)

#以下方法节省一些计算量
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)

3)alpha = 0.5时的重建结果

 4)alpha = 0.136时的重建结果

 

5)alpha = 0.037时的重建结果

6)alpha = 0.01时的重建结果

  2.2球旋转( Ball pivoting)

(1)原理

球旋转算法(BPA) [Bernardini1999]是一种与alpha形状相关的曲面重建方法。直观地,想象一个半径给定的3D球,我们把它扔在点云上。如果它击中任何3个点(并且它没有从这3个点掉下去),它就会创建一个三角形。然后,算法开始从现有三角形的边缘旋转,每次它碰到3个球没有掉下去的点,我们就创建另一个三角形。

(2)函数

Open3D在create_from_point_cloud_ball_pivoting中实现了该方法。该方法接受一个半径列表radii作为参数,该参数对应于在点云上旋转的各个球的半径。

注意:该算法假设点云数据有法线。

 (3)输入还是兔子,泊松磁盘采样3000个点

import open3d as o3d
import numpy as np

bunny = o3d.data.BunnyMesh()
gt_mesh = o3d.io.read_triangle_mesh(bunny.path)
gt_mesh.compute_vertex_normals()

pcd = gt_mesh.sample_points_poisson_disk(3000)
o3d.visualization.draw_geometries([pcd])

 注意,列表radii

radii = [0.005, 0.01, 0.02, 0.04]

(4)测试代码

import open3d as o3d
import numpy as np

bunny = o3d.data.BunnyMesh()
gt_mesh = o3d.io.read_triangle_mesh(bunny.path)
gt_mesh.compute_vertex_normals()

pcd = gt_mesh.sample_points_poisson_disk(3000)
o3d.visualization.draw_geometries([pcd])

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

(5)测试结果

   2.3泊松曲面重建( Poisson surface reconstruction)

2.3.1 泊松重建

(1)原理

泊松曲面重构方法[Kazhdan2006]解决正则化优化问题,获得光滑曲面。由于这个原因,泊松曲面重构可能比上面提到的方法更可取,因为它们会产生非光滑的结果,因为点云的点也是没有任何修改的三角形网格的顶点。

(2)函数

Open3D实现了create_from_point_cloud_poisson方法,它基本上是Kazhdan代码的包装器。函数的一个重要参数是depth,它定义了用于曲面重构的八叉树的深度,因此隐含了生成的三角形网格的分辨率。一个更高的深度值意味着一个网格有更多的细节。 

注意:该算法假设点云数据有法线。

 (3)测试的数据如下,比较威猛的老鹰:)

1)文件大小20多M

2)代码 

import open3d as o3d
import numpy as np

eagle = o3d.data.EaglePointCloud()
pcd = o3d.io.read_point_cloud(eagle.path)

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

 3)实物图

 (4)重建测试代码

import open3d as o3d
import numpy as np

eagle = o3d.data.EaglePointCloud()
pcd = o3d.io.read_point_cloud(eagle.path)

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

(5)重建后果然很不错

2.3.2 低密度值

(1)描述 

 泊松曲面重构也会在低密度的区域创建三角形,甚至外推到一些区域(见上图老鹰输出的底部)。create_from_point_cloud_poisson函数有第二个密度返回值,表示每个顶点的密度。低密度值意味着顶点仅由来自输入点云的少量点支持。

(2) 在下面的代码中,我们使用伪颜色在3D中可视化密度。紫色表示低密度,黄色表示高密度。

import open3d as o3d
import numpy as np
from matplotlib import pyplot as plt

##(1)input 
eagle = o3d.data.EaglePointCloud()
pcd = o3d.io.read_point_cloud(eagle.path)

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

##(2)Poisson surface reconstruction
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])

##(3) Violet indicates low density and yellow indicates a high density
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])

(3)测试结果

 (4)我们可以进一步使用密度值来删除支持度低的顶点和三角形。在下面的代码中,我们删除密度值低于所有密度值的0.01分位数的所有顶点(和连接的三角形)。

import open3d as o3d
import numpy as np
from matplotlib import pyplot as plt

##(1)input 
eagle = o3d.data.EaglePointCloud()
pcd = o3d.io.read_point_cloud(eagle.path)

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

##(2)Poisson surface reconstruction
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])

##(3) Violet indicates low density and yellow indicates a high density
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])


##(4) remove low density vertices
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])

(5)移除低密度值后的结果

 2.4 法向估计(Normal estimation)

(1)描述

在上面的例子中,我们假设点云有指向外的法线。然而,并不是所有的点云都有相关的法线。Open3D可以使用estimate_normals来估计点云法线,它在每个3D点的局部拟合一个平面来推导法线。然而,估计的法线可能不是一致的方向。Orient_normals_consistent_tangent_plane使用最小生成树传播法线方向。

PS注意:Orient_normals_consistent_tangent_plane要在estimate_normals来估计点云法线的基础上使用。

(2)estimate_normals获得法向的测试代码

1)代码

import open3d as o3d
import numpy as np
from matplotlib import pyplot as plt

##(1)estimate_normals 
bunny = o3d.data.BunnyMesh()
gt_mesh = o3d.io.read_triangle_mesh(bunny.path)

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)

2)测试结果

 (3)使用orient_normals_consistent_tangent_plane获得法向

1)代码

import open3d as o3d
import numpy as np
from matplotlib import pyplot as plt

##(1)estimate_normals 
bunny = o3d.data.BunnyMesh()
gt_mesh = o3d.io.read_triangle_mesh(bunny.path)

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)

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

2)结果

 

 

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

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

相关文章

一种隐私保护边云协同训练

研究背景 在边缘AI领域&#xff0c;联邦学习概念最先由google提出并在学界和业界得到广泛的讨论和发展。对于边缘AI&#xff0c;数据异构和数据隐私是两个主要的挑战&#xff0c;而将联邦学习应用在边缘计算中&#xff0c;可以协助解决这些挑战。FedAvg通过主动选择每一轮参与训…

Linux MySQL下载安装

介绍 查询当前系统中安装的所有软件 rpm -qa1. mysql的下载 1.1 查询当前系统中安装的名称带mysql的软件 rpm -qa | grep mysql如下所示没有输出说明是没有安装mysql 1.2 查询当前系统中安装的名称带mariadb的软件(如果有则卸载) rpm -qa | grep mariadb如下所示表示有ma…

Flink系列之Flink中StateBackend深入剖析和应用

title: Flink系列 一、Flink StateBackend 深入剖析和应用 ​ StateBackend 定义了状态是如何存储的&#xff0c;不同的 State Backend 会采用不同的方式来存储状态&#xff0c;核心入口是&#xff1a; StateBackend&#xff0c; Flink 提供了三种不同形式的存储后端&#xff…

Antd React UMI 配置优化 - 优化打包体积,提高打包速度

随着项目越来越大&#xff0c;打包后的体积很大&#xff0c;打包时间也很长&#xff0c;部署一次基本上要等十分钟左右。那么如何来优化打包体积和提高打包速度呢&#xff1f;一起来看看吧&#xff5e; 优化前打包体积分析 优化前个模块体积&#xff1a; 通过脚本命令&#x…

年产2万吨山楂酒工厂的设计—原料前处理工段及车间的设计(lunwen+cad图纸)

目 录 1前 言 1 1.1设计背景及目的 1 1.1.1山楂酒的介绍及功效 1 1.1.2目标人群 1 1.1.3发展前景 2 1.2设计依据 2 1.3设计内容 2 1.4原材料的选择 3 2工艺流程设计 5 2.1工艺流程的确定 5 2.2分选 6 2.3清洁消毒 8 2.4去核 9 2.4.1去核机的介绍及选择 9 2.4.2山楂核的处理 10 …

MQ 概念介绍 / 配置以及原理 简书

文章目录 1、什么是MQ 2、MQ的多种产品 3、MQ的工作原理 4、ActiveMQ 的配置 5、ActiveMQ 的数据存储方式 6、ActiveMQ的主从服务 7、ActiveMQ的集群负载均衡 什么是MQ&#xff1f; Message Queue, 就是消息队列&#xff0c;MQ 经常会作为多系统当中的网络消息传输。是…

负载均衡式在线OJ判题系统

文章目录负载均衡式在线OJ1. 演示项目2. 所用技术及开发环境所用技术&#xff1a;开发环境3. 项目宏观设计I. leetcode结构II.宏观结构III.编写思路4. compiler服务1. 编译功能&#xff1a;2. 运行功能3. 编译并运行功能4. 打包成一个网络服务5. 基于MVC结构的oj服务设计1. 用户…

Java IO流(详解)

1. File1. 创建2. 操作1. 获取文件信息2. 目录创建/删除2. IO流1. FileInputStream1. 简单使用2. 读取中文2. FileOutputStream1. 简单使用2. 追加写入3. 文件拷贝4. FileReader1. 简单使用2. 提高读取速度5. FileWriter1. 简单使用6. 节点流和处理流简介7. BufferedReader1. 简…

产品开发需要考虑哪些场景

产品到项目中去&#xff0c;也从项目中来&#xff0c;也就是说产品开发后最终都是会到项目中历练&#xff0c;然后吸取项目中的优点&#xff0c;来补全产品中业务的不足、功能的不足&#xff0c;让产品更加完善&#xff0c;最终成为精品。 每个产品的形成都要多加考虑&#xf…

Github 用户查询案例【基于Vue2全局事件总线通信】

前言&#xff1a; 本次案例是一个基于 Vue2 的全局事件总线通信的仿 Github 用户搜索模块&#xff0c;使用的接口是 Github 官方提供的搜索接口&#xff1a; https://api.github.com/search/users?qxxx&#xff08;发送请求时需要将输入的用户名称绑定替换掉xxx&#xff09;&a…

HTML期末学生大作业-宠物之家网页作业html+css+javascript

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

仪表板支持水印设置,数据集新增脱敏规则支持,DataEase开源数据可视化分析平台v1.17.0发布

12月5日&#xff0c;DataEase开源数据可视化分析平台正式发布v1.17.0版本。 这一版本的功能升级包括&#xff1a;数据集方面&#xff0c;支持将数据集数据按指定条件导出为Excel文件&#xff0c;方便用户对权限范围内的数据进行二次处理。数据集字段支持日期解析格式设置&…

[附源码]计算机毕业设计网约车智能接单规划小程序Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Service层代码单元测试以及单元测试如何Mock

一、背景 接着上一篇文章&#xff1a;单元测试入门篇&#xff0c;本篇文章作为单元测试的进阶篇&#xff0c;主要介绍如何对Springboot Service层代码做单元测试&#xff0c;以及单元测试中涉及外调服务时&#xff0c;如何通过Mock完成测试。 二、Springboot Service层代码单…

[附源码]JAVA毕业设计快递物流管理(系统+LW)

[附源码]JAVA毕业设计快递物流管理&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

华为云低代码技术:让矿区管理“智变”,一览无遗

摘要&#xff1a;基于华为低代码平台&#xff0c;万洲嘉智复用开发了9个数字化管理功能&#xff0c;成功解决了矿区管理的空区和难点&#xff0c;帮助煤矿园区实现了智能化管控。本文分享自华为云社区《【云享伙伴】第10期&#xff1a;华为云低代码技术&#xff1a;让矿区管理“…

[附源码]JAVA毕业设计-旅游产品销售管理-演示录像2020(系统+LW)

[附源码]JAVA毕业设计-旅游产品销售管理-演示录像2020&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff…

660846-99-1, Ac-Arg-Gly-Lys-AMC

Control for the two step histone deacetylase assay with Ac-Arg-Gly-Lys(Ac)-AMC. Ac-RGK-AMC corresponds to the product of the deacetylase reaction, which is subsequently cleaved by trypsin. Ac-精氨酸- gly - lys (Ac)-AMC两步法组蛋白去乙酰化酶测定对照。Ac-RGK…

直击家居建材采购痛点,数商云采购协同系统招投标功能助力企业招采透明高效

在后疫情时代&#xff0c;各类企业的采购与供应链数字化转型已是大势所趋&#xff0c;家居建材企业也不例外。用数字化技术助力建材产业转型&#xff0c;为供采双方提供线上精准对接服务&#xff0c;才能赋能新时代建材供应链。 建设采购平台已是大势所趋。作为企业价值链管理…

[附源码]Python计算机毕业设计Django南通大学福利发放管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…