Given an Array of Points
points = np.array([[1,1,1], [0,1,1], [1,0,0], [1,1,1]])
create an array that counts the coordinates, meaning:
r = [[0,0], [[1,0],
[0,1]], [0,2]]
meaning the coordinate [1,1,1]
exists twice so a the position [1,1,1]
there is a 2
in the resulting array.
In plain python this would be:
for p in points:
r[p[0]][p[1]][p[2]] = 1
I need this in the context of an realtime application, there are up to 300k points given per frame and a resulting matrix shape of up to 400x400x400, so speed is important. the amount of points and shape of the resulting matrix change dynamically.
I am new to numpy and have not found an efficient way to do this, doing it with a plain python for loop is too slow taking up to a second per frame.
CodePudding user response:
Consider the following.
points = np.array([[1,1,1], [0,1,1], [1,0,0], [1,1,1]])
unique, counts = np.unique(points, return_counts = True, axis = 0)
n = 1 np.max(unique)
r = np.zeros([n,n,n], dtype = int)
r[tuple(unique.T)] = counts
(Note: the final line above is equivalent to r[unique[:,0],unique[:,1],unique[:,2]] = counts
).
Resulting array r:
[[[0 0]
[0 1]]
[[1 0]
[0 2]]]
CodePudding user response:
You can ravel the 3D coordinates to 1D offsets with np.ravel_multi_index
and count these using np.bincount
.
import numpy as np
points = np.array([[1,1,1], [0,1,1], [1,0,0], [1,1,1]])
m = points.max(0) 1
np.bincount(np.ravel_multi_index(points.T, m), minlength=np.prod(m)).reshape(m)
Output
array([[[0, 0],
[0, 1]],
[[1, 0],
[0, 2]]])