isl-org / Open3D

Open3D: A Modern Library for 3D Data Processing
http://www.open3d.org
Other
11.32k stars 2.29k forks source link

Creating VoxelGrid from NumPy array #3133

Open supriya-gdptl opened 3 years ago

supriya-gdptl commented 3 years ago

I have 64^3 voxel saved as the NumPy array. I want to create an Open3D VoxelGrid object from it and use it for offscreen rendering. I followed the suggestion given in issue #1101, but got the same error as mentioned in #2660 : AttributeError: 'open3d.cpu.pybind.geometry.VoxelGrid' object has no attribute 'voxels'

Any suggestion on how to create VoxelGrid from NumPy array?

sbharadwajj commented 3 years ago

@griegler can we fix this by adding a pybind for the class AddVoxel() here?

elevenjiang1 commented 2 years ago

I also want this function. Now I use another method to achieve this. By change it into pointcloud,then use VoxelGrid.create_from_point_cloud() to get the voxel. All code are below,hoping can help you~


import numpy as np
import open3d as o3d
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

def voxel2array(grid_index_array,voxel_size=64):
    """
    convert a voxel_grid_index array to a fixed size array
    (N*3)->(voxel_size*voxel_size*voxel_size)

    :input grid_index_array: get from o3d.voxel_grid.get_voxels()
    :return array_voxel: array with shape(voxel_size*voxel_size*voxel_size),the grid_index in 
    """
    array_voxel=np.zeros((voxel_size,voxel_size,voxel_size))
    array_voxel[grid_index_array[:,0],grid_index_array[:,1],grid_index_array[:,2]]=1
    return array_voxel

def array2voxel(voxel_array):
    """
    convert a to a fixed size array to voxel_grid_index array
    (voxel_size*voxel_size*voxel_size)->(N*3)

    :input voxel_array: array with shape(voxel_size*voxel_size*voxel_size),the grid_index in 
    :return grid_index_array: get from o3d.voxel_grid.get_voxels()
    """
    x,y,z=np.where(voxel_array==1)
    index_voxel=np.vstack((x,y,z))
    grid_index_array=index_voxel.T
    return grid_index_array

#################Main convert here#################
#1: load o3d_voxel and get grid_index_array
#load o3d_voxel
data_path="chair_0001.ply"
o3d_voxel=o3d.io.read_voxel_grid(data_path)
frame = o3d.geometry.TriangleMesh.create_coordinate_frame(1)
o3d.visualization.draw_geometries([o3d_voxel,frame])

#get grid_index_array
voxel_list=o3d_voxel.get_voxels()
grid_index_array=list(map(lambda x:x.grid_index,voxel_list))
grid_index_array=np.array(grid_index_array)

#2: change to full voxel array
voxel_array=voxel2array(grid_index_array)

#3: show voxel in matplab.But this is slow
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.voxels(voxel_array,edgecolor="red")
plt.show()

#4: change back to o3d format
#change to open3d format pointcloud,then change to voxelgrid through create_from_point_cloud
grid_index_array=array2voxel(voxel_array)
pointcloud_array=grid_index_array*0.03125#0.03125 is voxel_size
pc=o3d.geometry.PointCloud()
pc.points=o3d.utility.Vector3dVector(pointcloud_array)
o3d_voxel=o3d.geometry.VoxelGrid.create_from_point_cloud(pc, voxel_size=0.03125)
o3d.visualization.draw_geometries([o3d_voxel,frame])
ohkwon718 commented 1 year ago

How is it going on the issue? I cannot find a way to control voxels manually. Even deleting a voxel seems unallowed too.

rtviii commented 8 months ago

Discovered the same thing after a bit of fiddling with this lib. There is a bunch of methods on VoxelGrid if you dir() it:

['HalfEdgeTriangleMesh',
 'Image',
 'LineSet',
 'PointCloud',
 'RGBDImage',
 'TetraMesh',
 'TriangleMesh',
 'Type',
 'Unspecified',
 'VoxelGrid',
 '__add__',
 '__class__',
 '__copy__',
 '__deepcopy__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getstate__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'add_voxel',
 'carve_depth_map',
 'carve_silhouette',
 'check_if_included',
 'clear',
 'create_dense',
 'create_from_octree',
 'create_from_point_cloud',
 'create_from_point_cloud_within_bounds',
 'create_from_triangle_mesh',
 'create_from_triangle_mesh_within_bounds',
 'dimension',
 'get_axis_aligned_bounding_box',
 'get_center',
 'get_geometry_type',
 'get_max_bound',
 'get_min_bound',
 'get_minimal_oriented_bounding_box',
 'get_oriented_bounding_box',
 'get_rotation_matrix_from_axis_angle',
 'get_rotation_matrix_from_quaternion',
 'get_rotation_matrix_from_xyz',
 'get_rotation_matrix_from_xzy',
 'get_rotation_matrix_from_yxz',
 'get_rotation_matrix_from_yzx',
 'get_rotation_matrix_from_zxy',
 'get_rotation_matrix_from_zyx',
 'get_voxel',
 'get_voxel_bounding_points',
 'get_voxel_center_coordinate',
 'get_voxels',
 'has_colors',
 'has_voxels',
 'is_empty',
 'origin',
 'remove_voxel',
 'rotate',
 'scale',
 'to_octree',
 'transform',
 'translate',
 'voxel_size']

, but in general i suppose because it's a wrapper around Cpp we don't get either the typehints nor the args right. There's "add voxel" but really, it's not the best library to do fine manipulations on voxel grid. Try something else like pyvista or do everything in numpy.