1

I have a 3-D array with shape [1080, 1920, 4], the last axis stands for RGBA channels of a picture, and I have a dict mapping from RGBA values to int, I want to use np.vectorize to convert this array to a 2-D array with shape [1080, 1920], how can I pass the array as a 2-D array with last dimension is a list to the vectorized function?

array = [[[112,  25, 235, 255],
        [112,  25, 235, 255],
        [112,  25, 235, 255],
        ...,
        [ 35,  35,  30, 255],
        [ 41,  40,  37, 255],
        [ 39,  41,  37, 255]]
        ...,
        [ 35,  35,  30, 255],
        [ 41,  40,  37, 255],
        [ 39,  41,  37, 255]]]
dic = {(35,  35,  30, 255): 1, (41,  40,  37, 255): 2}
np.vectorize(lambda x: dic.get(tuple(x)))()

what should I pass into the last ()

3
  • Do you mean you need to flatten the 3D list into a 2D list, right, and pass it in the function, right? Commented Dec 17, 2021 at 7:15
  • np.vectorize is a glorified for loop. Are you open to other methods? Commented Dec 17, 2021 at 7:17
  • Sounds like array.reshape(-1, 4). Commented Dec 17, 2021 at 7:17

2 Answers 2

2

One way using numpy.apply_along_axis:

# Data with (3, 3, 4)
array([[[112,  25, 235, 255],
        [112,  25, 235, 255],
        [112,  25, 235, 255]],

       [[ 35,  35,  30, 255],
        [ 41,  40,  37, 255],
        [ 39,  41,  37, 255]],

       [[ 35,  35,  30, 255],
        [ 41,  40,  37, 255],
        [ 39,  41,  37, 255]]])

dic = {(112, 25, 235, 255): 0,
 (35, 35, 30, 255): 1,
 (41, 40, 37, 255): 2,
 (39, 41, 37, 255): 3}

np.apply_along_axis(lambda x: dic.get(tuple(x)), 2, array)

Output:

array([[0, 0, 0],
       [1, 2, 3],
       [1, 2, 3]])
Sign up to request clarification or add additional context in comments.

1 Comment

numpy.apply_along_axis does work, but it seems to be slow, but thanks for your help
0

vectorize normally passes scalar values to the function. But you can specify a signature:

In [55]: f=np.vectorize(lambda x: dic.get(tuple(x)),signature='(n)->()')

Using @Chris example values:

In [56]: f(arr)
Out[56]: 
array([[0, 0, 0],
       [1, 2, 3],
       [1, 2, 3]])

But vectorize warns that signature use is slower:

In [57]: timeit f(arr)
178 µs ± 6.38 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Using apply... as @Chris does:

In [58]: timeit np.apply_along_axis(lambda x: dic.get(tuple(x)),2, arr)
131 µs ± 1.18 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

and a list comprehension on a the 'flattened' array:

In [59]: timeit np.array([dic.get(tuple(x)) for x in arr.reshape(-1,4)]).reshape(ar
    ...: r.shape[:2])
35.3 µs ± 108 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

The speed disadvantage of vectorize disappears with larger arrays, though I don't know if that applies to the signature case or not.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.