jado
jado

Reputation: 21

Mask 3d numpy array

Consider the following array as an image with three layers (red, green, blue). For each position in the image i want to test whether there is a specific value in one of the layers (e.g. 99). If that is true the values at the same position in the other layers shall be replaced by this specific value.

img = np.array([[[0, 99],
                 [2, 3]],
                     
                 [[4, 5],
                  [6, 7]],
                     
                 [[8, 9],
                  [10, 11]]])

The desired result would be:

img = [[[0, 99],
        [2, 3]],

       [[4, 99],
        [6, 7]],

       [[8, 99],
        [10, 11]]]

I am currently using the following code to fulfill the task.

c= []
for i in range(img.shape[1]):
    for j in range(img.shape[2]):
        if np.any(img[:, i, j]==99):
            c.append([99 for x in img[:, i, j]])
        else: c.append(img[:, i, j])

new_img = [np.array([row[i] for row in c]).reshape((2,2)).tolist() for i in range(len(c))]

However, this seems somewhat complicated. Can you recommend a better approach? Thank you for your help.

Upvotes: 1

Views: 199

Answers (2)

Ali_Sh
Ali_Sh

Reputation: 2816

You can do this by:

ind = np.argwhere(img == 99)[0, 1:]   # [0, 1]
img[:, ind[0], ind[1]] = 99
# [[[ 0 99]
#   [ 2  3]]
#  [[ 4 99]
#   [ 6  7]]
#  [[ 8 99]
#   [10 11]]]

which will work just on the first occurrence of 99. So, if you have more than one layer contain 99 or more than one count of 99 in each layer, do as @Mad solution.

Upvotes: 0

Mad Physicist
Mad Physicist

Reputation: 114310

The mask of pixels that are 99 in any channel is

mask = (img == 99).any(0)

You can apply this mask directly:

img[:, mask] = 99

Or as a one-liner:

img[:, (img == 99).any(0)] = 99

Upvotes: 2

Related Questions