Open3D 三维重建-Marching Cubes (行进立方体)

news2025/1/10 21:15:41

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1步骤

2.1.2函数代码

2.2完整代码

三、实现效果

3.1原始点云

3.2重建后点云


Open3D点云算法汇总及实战案例汇总的目录地址:

Open3D点云算法与点云深度学习案例汇总(长期更新)-CSDN博客


一、概述

        行进立方体算法(Marching Cubes)是一种用于从三维标量场数据(如体素网格)生成等值面(isosurface)的算法。其基本原理是通过遍历三维标量场中的每个体素单元,根据每个体素的顶点值,构建出相应的三角网格。

        Open3D目前并没有直接的行进立方体算法实现,需要结合其他库来完成,例如scikit-image中的marching_cubes方法。结合 Open3D 和 scikit-image编写行进立方体算法,可以实现从点云数据生成高质量的等值面

1.1原理

  1. 遍历三维标量场中的每个体素单元。
  2. 根据体素单元的八个顶点值,确定该单元内部是否包含等值面。
  3. 使用预定义的查找表,根据顶点值的组合生成对应的三角形面片。
  4. 将所有生成的三角形面片合并,构成完整的等值面。

1.2实现步骤

  1. 加载点云数据:读取点云数据文件。
  2. 估计法向量:计算点云中每个点的法向量。
  3. 生成体素网格:从点云数据生成体素网格。
  4. 使用行进立方体算法:从体素网格生成等值面。
  5. 可视化和保存结果:可视化生成的等值面,并将其保存到文件中。

1.3应用场景

  • 医学成像:如CT、MRI数据的三维重建。
  • 计算机图形学:生成多边形网格模型。
  • 科学可视化:如气象数据、地质数据的三维可视化

二、代码实现

2.1关键函数

  • 这段代码使用行进立方体算法(Marching Cubes)从体素网格生成三维等值面。具体来说,它将输入的体素网格转换为三维体积数据,并利用
  • scikit-image 库的 marching_cubes 方法生成等值面。生成的等值面被转换为 Open3D 的三角网格对象 TriangleMesh,可以用于可视化和进一步处理。

2.1.1步骤

  1. 获取体素索引:从体素网格中提取所有体素的索引,并将其转换为 NumPy 数组。
  2. 获取边界和体素大小:获取体素网格的最小和最大边界,以及体素的大小。
  3. 计算体素网格形状:根据边界和体素大小计算体素网格的形状。
  4. 创建体素数组:创建一个空的体素数组,用于存储体积数据。
  5. 填充体素数组:将体素网格中的每个体素标记为1,生成体积数据。
  6. 行进立方体算法:使用 scikit-image 的 marching_cubes 方法生成等值面
  7. 转换为三角网格:将生成的顶点、面片和法向量转换为 Open3D 的 TriangleMesh 对象。
  8. 返回生成的三角网格:返回生成的 TriangleMesh 对象,可以用于可视化和进一步处理。

2.1.2函数代码

def marching_cubes_from_voxel_grid(voxel_grid, level):
    """
    使用行进立方体算法从体素网格生成等值面。

    参数:
    voxel_grid (open3d.geometry.VoxelGrid): 输入的体素网格。
    level (float): 等值面的阈值。

    返回:
    open3d.geometry.TriangleMesh: 生成的三角网格。
    """
    # 获取体素网格中的所有体素索引
    voxel_indices = np.asarray([v.grid_index for v in voxel_grid.get_voxels()])
    # 获取体素网格的最小和最大边界
    min_bound = voxel_grid.get_min_bound()
    max_bound = voxel_grid.get_max_bound()
    # 获取体素大小
    voxel_size = voxel_grid.voxel_size
    # 计算体素网格的形状
    volume_shape = ((max_bound - min_bound) / voxel_size).astype(int) + 1
    # 创建一个空的体素数组
    volume = np.zeros(volume_shape, dtype=np.float32)

    # 将体素网格中的每个体素标记为1
    for voxel in voxel_indices:
        # 计算体素在体素数组中的索引
        grid_index = ((voxel * voxel_size - min_bound) / voxel_size).astype(int)
        # 确保索引在有效范围内
        if np.all(grid_index >= 0) and np.all(grid_index < volume_shape):
            volume[tuple(grid_index)] = 1

    # 使用 scikit-image 的 marching_cubes 方法生成等值面
    verts, faces, normals, _ = measure.marching_cubes(volume, level=level)

    # 将结果转换为 Open3D 的 TriangleMesh
    mesh = o3d.geometry.TriangleMesh()
    mesh.vertices = o3d.utility.Vector3dVector(verts * voxel_size + min_bound)
    mesh.triangles = o3d.utility.Vector3iVector(faces)
    mesh.vertex_normals = o3d.utility.Vector3dVector(normals)
    return mesh

2.2完整代码

import open3d as o3d
import numpy as np
from skimage import measure

def create_voxel_grid_from_point_cloud(pcd, voxel_size):
    """
    将点云转换为体素网格。

    参数:
    pcd (open3d.geometry.PointCloud): 输入的点云数据。
    voxel_size (float): 体素的大小。

    返回:
    open3d.geometry.VoxelGrid: 生成的体素网格。
    """
    voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd, voxel_size=voxel_size)
    return voxel_grid

def marching_cubes_from_voxel_grid(voxel_grid, level):
    """
    使用行进立方体算法从体素网格生成等值面。

    参数:
    voxel_grid (open3d.geometry.VoxelGrid): 输入的体素网格。
    level (float): 等值面的阈值。

    返回:
    open3d.geometry.TriangleMesh: 生成的三角网格。
    """
    # 将体素网格转换为3D numpy数组
    voxel_indices = np.asarray([v.grid_index for v in voxel_grid.get_voxels()])
    min_bound = voxel_grid.get_min_bound()
    max_bound = voxel_grid.get_max_bound()
    voxel_size = voxel_grid.voxel_size
    volume_shape = ((max_bound - min_bound) / voxel_size).astype(int) + 1
    volume = np.zeros(volume_shape, dtype=np.float32)

    for voxel in voxel_indices:
        grid_index = ((voxel * voxel_size - min_bound) / voxel_size).astype(int)
        if np.all(grid_index >= 0) and np.all(grid_index < volume_shape):
            volume[tuple(grid_index)] = 1

    # 使用scikit-image的marching_cubes方法生成等值面
    verts, faces, normals, _ = measure.marching_cubes(volume, level=level)

    # 将结果转换为Open3D的TriangleMesh
    mesh = o3d.geometry.TriangleMesh()
    mesh.vertices = o3d.utility.Vector3dVector(verts * voxel_size + min_bound)
    mesh.triangles = o3d.utility.Vector3iVector(faces)
    mesh.vertex_normals = o3d.utility.Vector3dVector(normals)
    return mesh

# 加载点云数据
pcd = o3d.io.read_point_cloud("hand.pcd")
o3d.visualization.draw_geometries([pcd], window_name="Cloud", width=800, height=600)
# 估计法向量
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))

# 生成体素网格
voxel_size = 0.05
voxel_grid = create_voxel_grid_from_point_cloud(pcd, voxel_size)

# 定义等值面阈值
isosurface_level = 0.5

# 使用行进立方体算法从体素网格生成等值面
mesh = marching_cubes_from_voxel_grid(voxel_grid, isosurface_level)

# 可视化生成的等值面
o3d.visualization.draw_geometries([mesh], window_name="Marching Cubes", width=800, height=600)

# 保存生成的等值面
# o3d.io.write_triangle_mesh("marching_cubes_mesh.ply", mesh)

三、实现效果

3.1原始点云

3.2重建后点云

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

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

相关文章

基于Flask框架的豆瓣电影实时数据分析可视化系统【自动爬虫、数据库、Pyecharts】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍数据抓取数据存储可视化前后端交互登陆界面注册界面数据更新后展示每文一语 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 项目介绍 本项目基于Py…

JavaEE: 线程安全问题的解决方案(synchronized)

发生原因 要想解决线程安全问题,那么我们首先得知道线程安全问题为什么会发生. 发生原因: 线程在操作系统中是"随机调度,抢占式执行的"[根本原因].多个线程,同时修改同一个变量修改操作不是"原子"的内存可见性问题指令重排序 解决方案 原因1和2,我们很…

基于YOLOv8的茶叶病变检测系统

基于YOLOv8的茶叶病变检测系统 (价格85) 包含 [Algal Leaf Spot, Brown Blight, Gray Blight, Healthy, Helopeltis, Red Leaf Spot] 6个类 翻译&#xff1a; [藻类叶斑病&#xff0c;褐疫病&#xff0c;灰疫病&#xff0c;健康&#xff0c;茶角盲蝽&#xff0c; 红叶斑…

08.SQL注入-下(超详细!!!)

1、Access注入 1.1 判断是否存在注入漏洞 ?id10 and 11 //不报错 ?id10 and 12 //报错1.2 判断字段数 ?id10 order by 1 ... ?id10 order by 7 //不报错 ?id10 order by 8 //报错 说明有7个字段1.3 猜表名 ?id10 and exists(select * from administrator) …

IP协议解析

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

C语言宏定义的使用

文章目录 &#x1f34a;自我介绍&#x1f34a;宏定义&#x1f34a;宏函数&#x1f34a;嵌入式开发常用do...while(0)&#x1f34a;字符串化运算符 ‘ # ’&#x1f34a;不定参数宏 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&#xf…

SQL报错注入之floor

目录 1.简述 2.关键函数说明 1.rand函数 2.floor&#xff08;rand&#xff08;0&#xff09;*2&#xff09;函数 3.group by 函数 4.count&#xff08;*&#xff09;函数 3.报错分析 4.报错流程 4.1寻找注入点 4.2爆数据库名 4.3爆表名 4.4爆字段名 4.5查询数据 1.…

32、Python之面向对象:对象的表示,再论Python是dict包括语法糖

引言 在前面介绍Python容器的时候&#xff0c;我们曾经用过这种夸张的表述&#xff0c;“Python就是包裹在一堆语法糖中的字典”。虽然夸张&#xff0c;其实更多的是为了突出Python中dict的强大之处。今天这篇文章&#xff0c;打算看下Python中类对象、实例对象的表示及内存管理…

甄选范文“论负载均衡技术在Web系统中的应用”软考高级论文系统架构设计师论文

论文真题 负载均衡技术是提升Web系统性能的重要方法。利用负载均衡技术, 可将负载(工作任务) 进行平衡、分摊到多个操作单元上执行, 从而协同完成工作任务, 达到提升Web系统性能的目的。 请围绕“负载均衡技术在Web系统中的应用”论题, 依次从以下三个方面进行论述。 1.…

自动化测试 — selenium + Java

什么是自动化测试 将人为驱动的测试行为转化为机器执行的过程。 自动化测试包括UI 自动化&#xff0c;接口自动化&#xff0c;单元测试自动化。按照这个金字塔模型来进行自动化测试规划&#xff0c;可以产生最佳的自贡话测试产出投入比&#xff08;ROI &#xff09;&#xff0c…

智能氮气柜如何为存储应用提供稳定和安全的环境?

智能氮气柜在保持内部环境的严格控制下&#xff0c;如何为各类高要求的存储应用提供一个稳定和安全的环境&#xff1f; 智能氮气柜内部安装高精度温湿度传感器&#xff0c;持续监测内部环境状况。通过外部连接的氮气供应源&#xff0c;向柜内注入高纯度氮气&#xff0c;当检测到…

k8s—ingress应用

一、ingress和ingress-controller ingress对象&#xff1a; 指的是k8s中的⼀个api对象/资源对象&#xff0c;⼀般⽤yaml配置。作⽤是定义请求如何转发到service的规则&#xff0c;可以理解为配置模板。 ingress-controller&#xff1a; 具体实现反向代理及负载均衡的程序&…

IO-Link通信笔记(十七)——可任意MCU平台移植的面向对象程序设计的IO-Link从站协议栈与接口代码生成和监控上位机与便携式通信主站

一、可任意MCU平台移植的面向对象程序设计的IO-Link从站协议栈 图形化界面与驱动代码库生成功能&#xff0c;是现如今几大半导体芯片供应商选择向广大开发人员推荐的主流开发方式&#xff0c;例如意法的cube-mx。开发人员可以通过这些软件针对所使用芯片的相关外设资源&#xf…

缺失值处理方法:代数/统计/机器学习算法补全数据(附Python-sklearn代码精美可视化绘图)

注&#xff1a;本期的删除或插补方法主要针对连续数据&#xff0c;时间序列数据的插补在后续关于时间序列的博客中讲明。参考鸢尾花丛书&#xff0c;链接如下&#xff1a; 参考书籍及源代码链接https://github.com/Visualize-ML 博客是选出自己感觉用的到的精炼部分加自己的理…

春秋云境 | 文件上传 | CVE-2022-30887

目录 靶标介绍 开启靶场 上传一句话木马 蚁剑连接 找到 flag 靶标介绍 多语言药房管理系统 (MPMS) 是用 PHP 和 MySQL 开发的, 该软件的主要目的是在药房和客户之间提供一套接口&#xff0c;客户是该软件的主要用户。该软件有助于为药房业务创建一个综合数据库&#xff0…

eclipse无法使用jdk1.6编译老项目

主要修改两个地方的配置&#xff1a; 1、eclipse中配置的maven版本不能过高&#xff0c;亲测3.2.5版本是好使的。 2、修改eclipse安装目录下的eclipse.ini文件&#xff0c;将其中的-Dosgi.requiredJavaVersion更改为1.6即可&#xff0c;我得默认是1.7 最后附上maven安装包&…

AGV一体式ARM智能控制主机如何替代传统PLC、工控机等方案

工业自动化的不断发展&#xff0c;AGV&#xff08;自动导引车&#xff09;作为一种重要的物流搬运设备&#xff0c;在各个领域得到了广泛的应用。而 AGV 的控制主机是其核心部件之一&#xff0c;直接影响着 AGV 的性能和稳定性。传统的 AGV 控制主机通常采用 x86 工控机交换机i…

【密码学】密码协议的分类:②认证协议

密码协议的分类有很多种方式&#xff0c;这里我采取的是基于协议实现的目的来分类。可以将密码协议分成三类&#xff1a;认证协议、密钥建立协议、认证密钥建立协议。 一、认证协议是什么&#xff1f; 认证协议都在认证些什么东西呢&#xff1f;认证一般要认证三个东西&#x…

防止老年痴呆的小学题

直角三角形的周长为16,斜边长为7,求三角形的面积(不使用勾股定理) 答案为(9*9-7*7)/4

aria2下载器在windows端的使用

一、下载aria2 aria2aria2 is a lightweight multi-protocol & multi-source command-linedownload utility. It supports HTTP/HTTPS, FTP, SFTP,BitTorrent and Metalink. …https://aria2.github.io/打开链接&#xff0c;点击要下载的版本&#xff0c;注意windows版本跟…