I have a 3D numpy.ndarray (think of an image with RGB) like
a = np.arange(12).reshape(2,2,3)
'''array(
[[[ 0, 1, 2], [ 3, 4, 5]],
[[ 6, 7, 8], [ 9, 10, 11]]])'''
and a function that handles a list input;
my_sum = lambda x: x[0] + x[1] + x[2]
What should I do to apply this function to each pixel? (or each 1D element of the 2D array)
This question is the kind of same as mine. So, I first tried it.
np.apply_along_axis(my_sum, 0, a.T).T #EDIT np.apply_along_axis(my_sum, -1, a) is better
at first, I thought this was the solution but this was too slow, because np.apply_along_axis is not for speed
I applied np.vetorize to my_func.
vector_my_func = np.vectorize(my_sum)
However, I have no idea even on how this vectorized function can be called.
vector_my_func(0,1,2)
#=> TypeError: <lambda>() takes 1 positional argument but 3 were given
vector_my_func(np.arange(3))
#=> IndexError: invalid index to scalar variable.
vector_my_func(np.arange(12).reshape(4,3))
#=> IndexError: invalid index to scalar variable.
vector_my_func(np.arange(12).reshape(2,2,3))
#=> IndexError: invalid index to scalar variable.
I am totally at loss on how this should be done.
benchmark results for suggested methods. (used jupyter notebook and restarted kernel for each test)
a = np.ones((1000,1000,3))
my_sum = lambda x: x[0] + x[1] + x[2]
my_sum_ellipsis = lambda x: x[..., 0] + x[..., 1] + x[..., 2]
vector_my_sum = np.vectorize(my_sum, signature='(i)->()')
%timeit np.apply_along_axis(my_sum, -1, a)
#1 loop, best of 3: 3.72 s per loop
%timeit vector_my_sum(a)
#1 loop, best of 3: 2.78 s per loop
%timeit my_sum(a.transpose(2,0,1))
#100 loops, best of 3: 12 ms per loop
%timeit my_sum_ellipsis(a)
#100 loops, best of 3: 12.2 ms per loop
%timeit my_sum(np.moveaxis(a, -1, 0))
#100 loops, best of 3: 12.2 ms per loop
One option is to transpose the numpy array, swap the third axis to the first, and then you can apply the function directly to it:
my_sum(a.transpose(2,0,1))
#array([[ 3, 12],
# [21, 30]])
Or rewrite the sum function as:
my_sum = lambda x: x[..., 0] + x[..., 1] + x[..., 2]
my_sum(a)
#array([[ 3, 12],
# [21, 30]])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With