Say I have a 3D (dimension order = zyx) numpy array of objects where each z dimension represents a set of 2D objects and the first z position is all zeros (reason for this will be explained soon):
objects = np.array([[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 3, 3, 0, 0],
[0, 1, 1, 0, 0, 0, 3, 3, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 4, 4, 0, 0, 0, 0, 0, 0, 0],
[0, 4, 4, 4, 0, 0, 0, 0, 0, 0],
[0, 4, 4, 4, 0, 0, 6, 0, 0, 0],
[0, 4, 4, 0, 0, 0, 6, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 5, 5, 0, 0, 0, 0, 0],
[0, 0, 5, 5, 5, 0, 0, 0, 0, 0],
[0, 0, 5, 5, 5, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]])
I also have another 3D array of the same shape where each value is related to the probability of each pixel belonging to the corresponding object at the same coordinates. For simplicity I used values of 1 and 2 (2 is higher probability than 1):
probs = np.array([[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
[0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 2, 2, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 0, 0, 2, 0, 0, 0],
[0, 2, 2, 0, 0, 0, 2, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]])
From the probs
array, I can calculate the z position with the highest probability value for each xy position using:
max_chs = np.argmax(probs, axis=0)
array([[0, 2, 2, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 0, 0, 2, 1, 0, 0],
[0, 2, 2, 0, 0, 0, 2, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
(The reason objects[0]
and probs[0]
are all zeros is so when this calculation is done we're able to distinguish between the background coordinates which have value 0 and the coordinates where the first z position has the maximum value which would also be zero otherwise).
What I want is a 2D array where each value is pulled from the objects
array where the z coordinate is chosen based on the max_chs
array value. So for example, max_chs[0, 1] = 2
so the [0, 1] coordinate of the result should equal objects[2, 0, 1]
and in general result[x, y] = objects[max_chs[x, y], x, y]
This should be the final result:
result = np.array([[0, 4, 4, 0, 0, 0, 0, 0, 0, 0],
[0, 4, 4, 4, 0, 0, 0, 0, 0, 0],
[0, 4, 4, 4, 0, 0, 6, 3, 0, 0],
[0, 4, 4, 0, 0, 0, 6, 3, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 5, 5, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
Is there a fast/efficient numpy method that could be used to accomplish this? The real data is much larger.
You can use argmax()
, arange()
and meshgrid()
:
import numpy as np
def _modify(objects, probs):
max_chs = np.argmax(probs, axis=0)
x, y = np.arange(max_chs.shape[0]), np.arange(max_chs.shape[1])
xx, yy = np.meshgrid(x, y, indexing='ij')
return objects[max_chs, xx, yy]
objects = np.array([[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 3, 3, 0, 0],
[0, 1, 1, 0, 0, 0, 3, 3, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 4, 4, 0, 0, 0, 0, 0, 0, 0],
[0, 4, 4, 4, 0, 0, 0, 0, 0, 0],
[0, 4, 4, 4, 0, 0, 6, 0, 0, 0],
[0, 4, 4, 0, 0, 0, 6, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 5, 5, 0, 0, 0, 0, 0],
[0, 0, 5, 5, 5, 0, 0, 0, 0, 0],
[0, 0, 5, 5, 5, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]])
probs = np.array([[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
[0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 2, 2, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 0, 0, 0, 0, 0, 0],
[0, 2, 2, 2, 0, 0, 2, 0, 0, 0],
[0, 2, 2, 0, 0, 0, 2, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]])
print(_modify(objects, probs))
[[0 4 4 0 0 0 0 0 0 0]
[0 4 4 4 0 0 0 0 0 0]
[0 4 4 4 0 0 6 3 0 0]
[0 4 4 0 0 0 6 3 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 5 5 0 0 0 0 0]
[0 0 2 2 2 0 0 0 0 0]
[0 0 2 2 2 0 0 0 0 0]
[0 0 0 2 2 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]
np.aranges
+ meshgrid
, there is conveniently xx, yy = np.indices(max_chs.shape, sparse=True)
! – Chrysophylaxsimport numpy as np
def _modify(objects, probs):
max_chs = np.argmax(probs, axis=0)
xx, yy = np.indices(max_chs.shape, sparse=True)
return objects[max_chs, xx, yy]