Open3D Voxelization 体素化

简介: Open3D Voxelization 体素化

Voxelization 体素化

点云和三角形网格是非常灵活但不规则的几何类型。体素网格(voxel grid)是在 3D 网格上定义的 3D 中的另一种几何类型,体素可以被视为 2D 中像素(pixel)的 3D 对应物。Open3D 具有可用于处理体素网格的几何类型VoxelGrid。

From triangle mesh 从三角形网格

Open3D 提供了从三角形网格创建体素网格的方法create_from_triangle_mesh。它返回一个体素网格,其中所有与三角形相交的体素都设置为1 ,所有其他体素都设置为 0。参数voxel_size定义体素网格的分辨率。

print('input')
bunny = o3d.data.BunnyMesh()
mesh = o3d.io.read_triangle_mesh(bunny.path)

# fit to unit cube
mesh.scale(1 / np.max(mesh.get_max_bound() - mesh.get_min_bound()),
           center=mesh.get_center())
o3d.visualization.draw_geometries([mesh])

print('voxelization')
voxel_grid = o3d.geometry.VoxelGrid.create_from_triangle_mesh(mesh,
                                                              voxel_size=0.05)
o3d.visualization.draw_geometries([voxel_grid])

From point cloud 从点云

体素网格也可以使用create_from_point_cloud方法从点云创建。如果点云的至少一个点在体素内,则体素被占用。体素的颜色是体素内所有点的平均值。参数voxel_size定义体素网格的分辨率。

print('input')
armadillo = o3d.data.ArmadilloMesh()
mesh = o3d.io.read_triangle_mesh(armadillo.path)

N = 2000
pcd = mesh.sample_points_poisson_disk(N)
# fit to unit cube
pcd.scale(1 / np.max(pcd.get_max_bound() - pcd.get_min_bound()),
          center=pcd.get_center())
pcd.colors = o3d.utility.Vector3dVector(np.random.uniform(0, 1, size=(N, 3)))
o3d.visualization.draw_geometries([pcd])

print('voxelization')
voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd,
                                                            voxel_size=0.05)
o3d.visualization.draw_geometries([voxel_grid])

Inclusion test 包含测试

体素网格还可用于测试点是否在占用的体素内。check_if_included方法将(n,3)数组作为输入并输出bool数组。

queries = np.asarray(pcd.points)
output = voxel_grid.check_if_included(o3d.utility.Vector3dVector(queries))
print(output[:10])

Voxel carving 体素雕刻

方法create_from_point_cloud和create_from_triangle_mesh创建占用的体素仅在几何体的表面上。但是,可以从许多深度图(depth maps)或剪影(sihouettes)中雕刻体素网格。Open3D提供了体素雕刻的carve_depth_map方法和carve_silhouette方法。

下面的代码演示了首先从几何图形渲染深度图并使用这些深度图雕刻密集体素网格的用法。结果是给定形状的填充体素网格。

import open3d as o3d
import  numpy as np


def xyz_spherical(xyz):
   x = xyz[0]
   y = xyz[1]
   z = xyz[2]
   r = np.sqrt(x * x + y * y + z * z)
   r_x = np.arccos(y / r)
   r_y = np.arctan2(z, x)
   return [r, r_x, r_y]


def get_rotation_matrix(r_x, r_y):
   rot_x = np.asarray([[1, 0, 0], [0, np.cos(r_x), -np.sin(r_x)],
                       [0, np.sin(r_x), np.cos(r_x)]])
   rot_y = np.asarray([[np.cos(r_y), 0, np.sin(r_y)], [0, 1, 0],
                       [-np.sin(r_y), 0, np.cos(r_y)]])
   return rot_y.dot(rot_x)


def get_extrinsic(xyz):
   rvec = xyz_spherical(xyz)
   r = get_rotation_matrix(rvec[1], rvec[2])
   t = np.asarray([0, 0, 2]).transpose()
   trans = np.eye(4)
   trans[:3, :3] = r
   trans[:3, 3] = t
   return trans


def preprocess(model):
   min_bound = model.get_min_bound()
   max_bound = model.get_max_bound()
   center = min_bound + (max_bound - min_bound) / 2.0
   scale = np.linalg.norm(max_bound - min_bound) / 2.0
   vertices = np.asarray(model.vertices)
   vertices -= center
   model.vertices = o3d.utility.Vector3dVector(vertices / scale)
   return model


def voxel_carving(mesh,
                 cubic_size,
                 voxel_resolution,
                 w=300,
                 h=300,
                 use_depth=True,
                 surface_method='pointcloud'):
   mesh.compute_vertex_normals()
   camera_sphere = o3d.geometry.TriangleMesh.create_sphere()

   # setup dense voxel grid
   voxel_carving = o3d.geometry.VoxelGrid.create_dense(
       width=cubic_size,
       height=cubic_size,
       depth=cubic_size,
       voxel_size=cubic_size / voxel_resolution,
       origin=[-cubic_size / 2.0, -cubic_size / 2.0, -cubic_size / 2.0],
       color=[1.0, 0.7, 0.0])

   # rescale geometry
   camera_sphere = preprocess(camera_sphere)
   mesh = preprocess(mesh)

   # setup visualizer to render depthmaps
   vis = o3d.visualization.Visualizer()
   vis.create_window(width=w, height=h, visible=False)
   vis.add_geometry(mesh)
   vis.get_render_option().mesh_show_back_face = True
   ctr = vis.get_view_control()
   param = ctr.convert_to_pinhole_camera_parameters()

   # carve voxel grid
   pcd_agg = o3d.geometry.PointCloud()
   centers_pts = np.zeros((len(camera_sphere.vertices), 3))
   for cid, xyz in enumerate(camera_sphere.vertices):
       # get new camera pose
       trans = get_extrinsic(xyz)
       param.extrinsic = trans
       c = np.linalg.inv(trans).dot(np.asarray([0, 0, 0, 1]).transpose())
       centers_pts[cid, :] = c[:3]
       ctr.convert_from_pinhole_camera_parameters(param)

       # capture depth image and make a point cloud
       vis.poll_events()
       vis.update_renderer()
       depth = vis.capture_depth_float_buffer(False)
       pcd_agg += o3d.geometry.PointCloud.create_from_depth_image(
           o3d.geometry.Image(depth),
           param.intrinsic,
           param.extrinsic,
           depth_scale=1)

       # depth map carving method
       if use_depth:
           voxel_carving.carve_depth_map(o3d.geometry.Image(depth), param)
       else:
           voxel_carving.carve_silhouette(o3d.geometry.Image(depth), param)
       print("Carve view %03d/%03d" % (cid + 1, len(camera_sphere.vertices)))
   vis.destroy_window()

   # add voxel grid survace
   print('Surface voxel grid from %s' % surface_method)
   if surface_method == 'pointcloud':
       voxel_surface = o3d.geometry.VoxelGrid.create_from_point_cloud_within_bounds(
           pcd_agg,
           voxel_size=cubic_size / voxel_resolution,
           min_bound=(-cubic_size / 2, -cubic_size / 2, -cubic_size / 2),
           max_bound=(cubic_size / 2, cubic_size / 2, cubic_size / 2))
   elif surface_method == 'mesh':
       voxel_surface = o3d.geometry.VoxelGrid.create_from_triangle_mesh_within_bounds(
           mesh,
           voxel_size=cubic_size / voxel_resolution,
           min_bound=(-cubic_size / 2, -cubic_size / 2, -cubic_size / 2),
           max_bound=(cubic_size / 2, cubic_size / 2, cubic_size / 2))
   else:
       raise Exception('invalid surface method')
   voxel_carving_surface = voxel_surface + voxel_carving

   return voxel_carving_surface, voxel_carving, voxel_surface

armadillo_path = r'../data/ArmadilloMesh.ply'
mesh = o3d.io.read_triangle_mesh(armadillo_path)

visualization = True
cubic_size = 2.0
voxel_resolution = 128.0

voxel_grid, voxel_carving, voxel_surface = voxel_carving(
   mesh, cubic_size, voxel_resolution)

print("surface voxels")
print(voxel_surface)
o3d.visualization.draw_geometries([voxel_surface])

print("carved voxels")
print(voxel_carving)
o3d.visualization.draw_geometries([voxel_carving])

print("combined voxels (carved + surface)")
print(voxel_grid)
o3d.visualization.draw_geometries([voxel_grid])
相关文章
|
机器学习/深度学习 存储 编解码
Open3d系列 | 3. Open3d实现点云上采样、点云聚类、点云分割以及点云重建
Open3d系列 | 3. Open3d实现点云上采样、点云聚类、点云分割以及点云重建
15055 1
Open3d系列 | 3. Open3d实现点云上采样、点云聚类、点云分割以及点云重建
|
存储 数据采集 数据可视化
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
17882 1
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
|
3月前
|
机器学习/深度学习 人工智能 编解码
大模型应用:CLIP 模型全维度解析:理解理论基础强化基础范例.16
CLIP是OpenAI提出的跨模态模型,通过对比学习将图像与文本映射至统一语义空间,实现零样本图文对齐。无需微调即可完成图像分类、图文检索等任务,显著降低标注成本,成为多模态AI的核心基础。
2113 21
|
机器学习/深度学习 传感器 编解码
史上最全 | 基于深度学习的3D分割综述(RGB-D/点云/体素/多目)(上)
3D目标分割是计算机视觉中的一个基本且具有挑战性的问题,在自动驾驶、机器人、增强现实和医学图像分析等领域有着广泛的应用。它受到了计算机视觉、图形和机器学习社区的极大关注。传统上,3D分割是用人工设计的特征和工程方法进行的,这些方法精度较差,也无法推广到大规模数据上。在2D计算机视觉巨大成功的推动下,深度学习技术最近也成为3D分割任务的首选。近年来已涌现出大量相关工作,并且已经在不同的基准数据集上进行了评估。本文全面调研了基于深度学习的3D分割的最新进展,涵盖了150多篇论文。论文总结了最常用的范式,讨论了它们的优缺点,并分析了这些分割方法的对比结果。并在此基础上,提出了未来的研究方向。
史上最全 | 基于深度学习的3D分割综述(RGB-D/点云/体素/多目)(上)
conda常用操作和配置镜像源
conda常用操作和配置镜像源
33810 0
|
机器学习/深度学习 算法 数据可视化
Open3D Mesh 网格
Open3D Mesh 网格
850 2
|
传感器 机器学习/深度学习 人工智能
史上最全综述 | 3D目标检测算法汇总!(单目/双目/LiDAR/多模态/时序/半弱自监督)(下)
近年来,自动驾驶因其减轻驾驶员负担、提高行车安全的潜力而受到越来越多的关注。在现代自动驾驶系统中,感知系统是不可或缺的组成部分,旨在准确估计周围环境的状态,并为预测和规划提供可靠的观察结果。3D目标检测可以智能地预测自动驾驶车辆附近关键3D目标的位置、大小和类别,是感知系统的重要组成部分。本文回顾了应用于自动驾驶领域的3D目标检测的进展。
史上最全综述 | 3D目标检测算法汇总!(单目/双目/LiDAR/多模态/时序/半弱自监督)(下)
|
机器学习/深度学习 数据可视化 自动驾驶
YOLO11-seg分割如何训练自己的数据集(道路缺陷)
本文介绍了如何使用自己的道路缺陷数据集训练YOLOv11-seg模型,涵盖数据集准备、模型配置、训练过程及结果可视化。数据集包含4029张图像,分为训练、验证和测试集。训练后,模型在Mask mAP50指标上达到0.673,展示了良好的分割性能。
6753 4
|
监控 Devops 测试技术
DevOps实践: 持续集成和持续部署(CI/CD)的入门指南
【9月更文挑战第10天】在快速迭代的软件开发世界中,DevOps已经成为加速产品交付、提升软件质量和团队协作的关键策略。本文将深入浅出地介绍DevOps的核心组成部分——持续集成(Continuous Integration, CI)与持续部署(Continuous Deployment, CD)的基本概念、实施步骤以及它们如何革新传统的软件开发流程。你将学习到如何通过自动化工具简化开发流程,并理解为什么CI/CD是现代软件开发不可或缺的一环。
|
算法 vr&ar 计算机视觉
数据结构之洪水填充算法(DFS)
洪水填充算法是一种基于深度优先搜索(DFS)的图像处理技术,主要用于区域填充和图像分割。通过递归或栈的方式探索图像中的连通区域并进行颜色替换。本文介绍了算法的基本原理、数据结构设计(如链表和栈)、核心代码实现及应用实例,展示了算法在图像编辑等领域的高效性和灵活性。同时,文中也讨论了算法的优缺点,如实现简单但可能存在堆栈溢出的风险等。
914 0