带自定义标签的Tensor点云执行voxel_down_sample报错求解
问题
尝试对带有uint8类型物体类别标注的点云执行voxel_down_sample操作,移除自定义属性时下采样可正常运行,添加标签后则报错。
示例代码:
import open3d as o3d device = o3d.core.Device("CPU:0") pcd = o3d.t.geometry.PointCloud(device) pcd.point.positions = o3d.core.Tensor([[0,0,0],[1,1,1],[2,2,2]], device=device) pcd.point.labels = o3d.core.Tensor([0,1,2], o3d.core.uint8, device=device) pcd_ds = pcd.voxel_down_sample(voxel_size=3)
注释掉pcd.point.labels = ...行时下采样正常,保留则触发错误:
RuntimeError Traceback (most recent call last) Cell In[10], line 6 3 pcd.point.positions = o3d.core.Tensor([[0,0,0],[1,1,1],[2,2,2]], device=device) 4 pcd.point.labels = o3d.core.Tensor([0,1,2], o3d.core.uint8, device=device) ----> 6 pcd_ds = pcd.voxel_down_sample(voxel_size=3) RuntimeError: [Open3D Error] (void open3d::core::kernel::BinaryEW(const open3d::core::Tensor&, const open3d::core::Tensor&, open3d::core::Tensor&, open3d::core::kernel::BinaryEWOpCode)) /root/Open3D/cpp/open3d/core/kernel/BinaryEW.cpp:49: The broadcasted input shape [1, 1] does not match the output shape [1].
版本信息:Python 3.11,Open3D 0.18
能否实现带有自定义属性的点云体素下采样?
解决方案
可以实现带自定义属性的点云体素下采样,问题根源在于Open3D默认对自定义属性采用均值聚合,而uint8类型的均值计算会触发类型不兼容或广播错误。以下是两种可行的解决方式:
方法1:用voxel_down_sample_and_trace手动处理标签
该方法能获取每个体素对应的原始点索引,可根据业务需求(如取众数、第一个点的标签等)手动聚合标签:
import open3d as o3d import numpy as np device = o3d.core.Device("CPU:0") pcd = o3d.t.geometry.PointCloud(device) pcd.point.positions = o3d.core.Tensor([[0,0,0],[1,1,1],[2,2,2]], device=device) pcd.point.labels = o3d.core.Tensor([0,1,2], o3d.core.uint8, device=device) voxel_size = 3 # 执行下采样并获取体素-原始点的索引映射 downpcd, indices, inv_indices = pcd.voxel_down_sample_and_trace(voxel_size, pcd.get_min_bound(), pcd.get_max_bound()) # 手动聚合标签:以每个体素内出现次数最多的标签为例 labels_np = pcd.point.labels.numpy() down_labels = [] for idx_group in indices: if not idx_group.size: down_labels.append(0) else: count = np.bincount(labels_np[idx_group]) down_labels.append(np.argmax(count)) # 将聚合后的标签赋值给下采样点云 downpcd.point.labels = o3d.core.Tensor(down_labels, dtype=o3d.core.uint8, device=device)
方法2:转换标签类型后执行下采样
若标签允许用浮点型临时表示,可先将uint8转为float32,下采样后再转回uint8:
import open3d as o3d device = o3d.core.Device("CPU:0") pcd = o3d.t.geometry.PointCloud(device) pcd.point.positions = o3d.core.Tensor([[0,0,0],[1,1,1],[2,2,2]], device=device) # 将标签转为float32规避类型问题 pcd.point.labels = o3d.core.Tensor([0,1,2], o3d.core.float32, device=device) # 执行下采样 pcd_ds = pcd.voxel_down_sample(voxel_size=3) # 转回uint8(均值可能产生小数,需取整) pcd_ds.point.labels = pcd_ds.point.labels.to(o3d.core.uint8)
补充说明
Open3D的voxel_down_sample对自定义属性默认执行均值聚合,但uint8类型的均值计算会因内部类型转换和广播逻辑触发错误。上述两种方法分别通过手动聚合或类型转换规避了问题,可根据标签的业务逻辑选择合适的聚合规则(众数、中位数、首个点标签等)。
内容的提问来源于stack exchange,提问作者tdpu
相关产品推荐
相关产品推荐

