In open3D, we can create point cloud by something like this
import open3d as o3d
import numpy as np
pcl = o3d.geometry.PointCloud()
pcl.points = o3d.utility.Vector3dVector(np.random.randn(500,3))
o3d.visualization.draw_geometries([pcl])
But for binary numpy array, e.g. voxel
, if I want to visualize the voxel, I need to convert it to point cloud and then use o3d.geometry.VoxelGrid.create_from_point_cloud
to convert the point cloud back to the open3D VoxelGrid
voxel = np.zeros((32, 32, 32), np.uint8)
voxel[16, 16, 16] = 1
# normalize
pcl = o3d.geometry.PointCloud()
pc = np.stack(np.where(voxel == 1)).transpose((1, 0)) / (voxel.shape[0] - 1)
pcl.points = o3d.utility.Vector3dVector(pc)
voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcl, voxel_size=0.04)
o3d.visualization.draw_geometries([voxel_grid])
Is there any way to create o3d.geometry.VoxelGrid
directly from voxel like
### this doesn't work
voxel = np.zeros((32, 32, 32), np.uint8)
voxel[16, 16, 16] = 1
voxel_grid = o3d.geometry.VoxelGrid()
voxel_grid.voxels = o3d.utility.Vector3dVector(voxel)
o3d.visualization.draw_geometries([voxel_grid])
As of right now, the answer looks to be a firm no, you can't.
VoxelGrid isn't actually storing the data the way you have it. The underlying datastructure is actually an unordered_map
of 3d indices and Voxel
objects. I would describe it as a sparse representation, and you have a dense representation of the data (which would cover the entire domain with white and black pixels). You introduce the sparseness when you do: np.where(voxel == 1)
.
It's also missing voxel_size, origin and of course the voxel colors.
It's not impossible to add some method like create_from_dense_array
, but there is nothing of the sort today from what I can see browsing the code.
They could also add a pybind wrapper to the AddVoxel
/add_voxel
method easily, but that is also currently overlooked. Even then, it would still require you to compute the sparse voxel yourself and construct the o3d.geometry.Voxel
object(s), probably requiring some additional utility helper method like Vector3dVector but for voxels.
Currently it seems to me that the best route is to go via the PointCloud
like you already have done.