如何用Open3D中已着色的Voxel对象构建VoxelGrid
问题:Open3D中如何用已着色的Voxel对象组装新VoxelGrid?
问题描述
我用Open3D处理两个点云,先完成体素化,再根据每个体素内的点数量差异为体素着色。已经通过o3d.geometry.VoxelGrid.create_from_point_cloud()创建了两个VoxelGrid对象,计算后得到一批已分配颜色的Voxel对象,但不知道如何将这些Voxel组装成新的VoxelGrid,卡在了这一步。
翻遍Open3D文档也没找到直接实现的函数,我考虑过一种思路:获取目标体素的中心坐标,用这些坐标和对应颜色创建o3d.geometry.PointCloud,再通过o3d.geometry.VoxelGrid.create_from_point_cloud()生成新网格,但不确定有没有更便捷的方式,比如未知的运算符重载。我用Open3D的经验不多。
当前代码片段
common_voxels = [] vox = self.pc_source.voxel_grid.get_voxels() cmap = LinearSegmentedColormap.from_list('custom_colormap', [(0, 'green'), (0.5, 'yellow'), (1, 'red')]) norm = plt.Normalize(vmin=delta_min, vmax=delta_max) sm = ScalarMappable(cmap=cmap, norm=norm) colors = sm.to_rgba(point_count_delta) for i, (voxel_idx, source_idx, target_idx, source_point_count, target_point_count) in enumerate(self.common_voxel_point_count_idx_map): vox[source_idx].color = colors[i][[0, 1, 2]] common_voxels.append(vox[source_idx]) # vox_center = self.pc_source.voxel_grid.get_center_coordinate print(i) vox_grid = o3d.geometry.VoxelGrid() for i in range(len(common_voxels)): vox_grid += common_voxels[i]
解决方案
Open3D的VoxelGrid没有直接添加单个Voxel的API,代码中使用的+=运算符也无效。这里提供两种实用的实现方式:
方法1:基于现有VoxelGrid修改颜色(推荐)
既然你的common_voxels来自源VoxelGrid,直接在源网格基础上修改对应体素的颜色,再复制出新网格即可,无需重新组装:
# 复制源VoxelGrid以保留原参数(体素大小、原点等) new_vox_grid = self.pc_source.voxel_grid.clone() # 获取可修改的体素列表 voxels = new_vox_grid.get_voxels() for i, (voxel_idx, source_idx, target_idx, source_point_count, target_point_count) in enumerate(self.common_voxel_point_count_idx_map): voxels[source_idx].color = colors[i][[0, 1, 2]] # 将修改后的体素列表重新绑定到新网格 new_vox_grid.voxels = voxels
这种方法无需重新计算体素化,效率最高,且能完整保留原网格的所有配置。
方法2:通过点云重建VoxelGrid
如果需要完全从零构建,可以用体素中心坐标创建带颜色的点云,再用与原网格相同的参数重新体素化:
import open3d as o3d import numpy as np centers = [] colors_list = [] # 提取原网格的关键参数,保证体素对齐 voxel_size = self.pc_source.voxel_grid.voxel_size origin = self.pc_source.voxel_grid.origin for voxel in common_voxels: # 计算体素中心坐标:原点 + (体素索引 + 0.5) * 体素大小 center = origin + (np.array(voxel.grid_index) + 0.5) * voxel_size centers.append(center) colors_list.append(voxel.color) # 创建带颜色的点云 color_pc = o3d.geometry.PointCloud() color_pc.points = o3d.utility.Vector3dVector(np.array(centers)) color_pc.colors = o3d.utility.Vector3dVector(np.array(colors_list)) # 用原参数重建VoxelGrid new_vox_grid = o3d.geometry.VoxelGrid.create_from_point_cloud( color_pc, voxel_size=voxel_size, origin=origin )
这种方法需要重新体素化,效率稍低,但适合完全从零构建的场景。
内容的提问来源于stack exchange,提问作者Máté Kosztricz
相关产品推荐
相关产品推荐

