I want to extract the bottom layer voxels. For example, extract the part from the armadillo. Does anyone know how to do that?
This is how I find the lowest voxel.
#Get voxels center coordinate
def get_voxel_center_coordinate(voxel_grid):
voxels = voxel_grid.get_voxels()
voxel_center = []
for voxel in voxels:
voxel_center.append(voxel_grid.get_voxel_center_coordinate(voxel.grid_index))
return voxel_center
#Find lowest voxels index
def find_lowest_voxel_index(voxel_grid):
voxels = voxel_grid.get_voxels()
voxel_center = get_voxel_center_coordinate(voxel_grid)
for i in range(0, len(voxel_center)):
if i == 0:
min_z = voxel_center[i, 2]
else:
if min_z > voxel_center[i, 2]:
min_z = voxel_center[i, 2]
ind = 0
lowest_voxel_index = []
for center in voxel_center:
if center[2] == min_z:
print(center[2])
lowest_voxel_index.append(voxels[ind].grid_index)
ind += 1
return lowest_voxel_index
Your solution is almost correct. I'll point out a few things that you should change and then a way to verify the solution.
Things that should change in the given solution:
voxel_center[i, 2]
since voxel_center
is a list, not a numpy array. You should instead access them as voxel_center[i][2]
.ind
at each loop, not only when the condition is true. Alternatively, you can use enumerate
which overcomes this cleanly.Therefore, the correct implementation would be the following:
#Get voxels center coordinate
def get_voxel_center_coordinate(voxel_grid):
voxels = voxel_grid.get_voxels()
voxel_center = []
for voxel in voxels:
voxel_center.append(voxel_grid.get_voxel_center_coordinate(voxel.grid_index))
return voxel_center
#Find lowest voxels index
def find_lowest_voxel_index(voxel_grid):
voxels = voxel_grid.get_voxels()
voxel_center = get_voxel_center_coordinate(voxel_grid)
for i in range(0, len(voxel_center)):
if i == 0:
min_z = voxel_center[i][2]
else:
if min_z > voxel_center[i][2]:
min_z = voxel_center[i][2]
ind = 0
lowest_voxel_index = []
for center in voxel_center:
if center[2] == min_z:
print(center[2])
lowest_voxel_index.append(voxels[ind].grid_index)
ind += 1
return lowest_voxel_index
To verify the solution, you might want to visualize the results. However, VoxelGrid
does not have any method that allows the user to e.g., change the color of a particular voxel. Therefore, you can think of creating extra meshes to visualize the filtered voxels. Since VoxelGrid
provides get_voxel_bounding_points
, you can make use of these points to create an AxisAlignedBoundingBox
.
lowest_index = find_lowest_voxel_index(voxel_grid) # this uses your solution after modifications
bounding_box = []
for i in lowest_index:
bb = o3d.geometry.AxisAlignedBoundingBox.create_from_points(voxel_grid.get_voxel_bounding_points(i))
bb.color = np.array([1,0,1]) # feel free to choose any other color
bounding_box.append(bb)
axes = o3d.geometry.TriangleMesh.create_coordinate_frame(origin=np.array([100,100,100]), size=100) # in order to be sure of the direction
o3d.visualization.draw_geometries([voxel_grid, *bounding_box, axes])
This is how running this code on an armadillo mesh looks like. Note that I added the coordinate frame to make sure of the direction. Blue arrow points toward +z. The voxel with the lowest z value has purple edges.