0

I was am trying to find more efficent and faster way of unpacking a list of objects into its component parts. The approach i have currently working is this:

points_fill_v2 = o3d.geometry.VoxelGrid.create_from_point_cloud(points,
                                                            voxel_size=vox)
scrap = points_fill_v2 .get_voxels()
resize3d = np.ones((3, 64, 64, 64))

for idx in range(len(scrap)):
    resize3d[0, scrap[idx].grid_index[0], scrap[idx].grid_index[1], scrap[idx].grid_index[2]] = scrap[idx].color[0]
    resize3d[1, scrap[idx].grid_index[0], scrap[idx].grid_index[1], scrap[idx].grid_index[2]] = scrap[idx].color[1]
    resize3d[2, scrap[idx].grid_index[0], scrap[idx].grid_index[1], scrap[idx].grid_index[2]] = scrap[idx].color[2]

scrap is a list and looks like this:

[Voxel with grid_index: (7, 27, 30), color: (0, 0, 1), Voxel with grid_index: (32, 9, 8), color: (0, 0, 0), ......] 

It has 2 properties; grid index and color, both are numpy 1,3 arrays.

The above code converts a point cloud into a voxel dataset using open3d (I have to use open3d), and then converts that into a RGB 3d numpy array.

I can split out the main list into 2 other lists (and then arrays) using:

grid = [scrap[idx].grid_index for idx in range(len(scrap))]
colour = [scrap[idx].color for idx in range(len(scrap))]

How do I transfer the data in colour into resize_3d efficiently using the index stored in grid?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • Easiest way is to convert scrap into a numpy 2-d array as well and insert it in one go. I am not really sure what the structure is, but if you supply an example of how scrap looks like, I or someone else might be able to help – C Hecht Aug 02 '21 at 09:14
  • scrap looks like this: [Voxel with grid_index: (7, 27, 30), color: (0, 0, 1), Voxel with grid_index: (32, 9, 8), color: (0, 0, 0)......] It has 2 properties grid index and color both a numpy 1,3 arrays – chaslie2222 Aug 02 '21 at 09:16
  • Hi, if you have data to add you should edit the question and add it there. also format it using code snippet format – Almog-at-Nailo Aug 02 '21 at 09:24

1 Answers1

0

This refactoring should give you a slight speed increase, and makes your code a lot cleaner:

from itertools import product
 
points_fill_v2 = o3d.geometry.VoxelGrid.create_from_point_cloud(points, voxel_size=vox)
scrap = points_fill_v2.get_voxels()
resize3d = np.ones((3, 64, 64, 64))

for (idx, scrap_elem), j in product(enumerate(scrap), range(3)):
    resize3d[(j, *scrap_elem.grid_index[:3])] = scrap_elem.color[j]

Things I've done here:

Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
  • 1
    Hi Alex, thanks for the reponse. have a look at http://www.open3d.org/docs/release/python_api/open3d.geometry.VoxelGrid.html for the documentation on the create from point cloud. I have had a look at the code and i get: resize3d[j, *scrap_elem.grid_index[:2]] = scrap_elem.color[j] ^ SyntaxError: invalid syntax – chaslie2222 Aug 02 '21 at 14:44
  • Hmm, okay — try replacing that line with two lines. 1st line: `a,b,c = scrap_elem.grid_index[:2]`. 2nd line: `resize3d[j, a, b, c] = scrap_elem.color[j]`. If it works I'll edit it into my answer. – Alex Waygood Aug 02 '21 at 14:50
  • Actually, it looks like the original line is fine as it is if you just add a set of brackets around the expression: `resize3d[(j, *scrap_elem.grid_index[:2])] = scrap_elem.color[j]` – Alex Waygood Aug 02 '21 at 15:04
  • 1
    hi alex, that works, but i had to make the following changes: for (idx, scrap_elem), j in product(enumerate(scrap), range(3)): # print(j) a, b, c = scrap_elem.grid_index[:3] resize3d[j, a, b, c] = scrap_elem.color[j] – chaslie2222 Aug 02 '21 at 15:09
  • Stupid mistake on my part, apologies. I have edited my answer — hopefully it's correct now. – Alex Waygood Aug 02 '21 at 15:13