0

I have two images stored as numpy arrays. I am looking for a function that can replace the parts of array2 that have black pixels ([0, 0, 0]) with the same indices of array1. My code so far is non-numpy:

for y in range(array2.shape[0]):
            for x in range(array2.shape[1]):
                if np.all(array2[y, x]) == False:
                    array2[y, x] = array1[y, x]

The code loops over every pixel in array2 to see if all of the channels are 0 (black), and if so copies the colour of array1 at that index onto array2.

This is obviously very slow because it loops over a lot of pixels that aren't black and has no affect on them. I assume numpy has a function that can do this, but I can't understand what they do. Any guidance (with or without numpy) is appreciated.

1
  • could you please add a minimal example for array2 and array1? at least to have matching .shape Commented Jul 9, 2020 at 12:27

2 Answers 2

2

Is this something like you want? (I assume that there are no negative values.) (Edit: but see comment by Adam.Er8 to lift this limitation)

>>> arr1                                                                                                                                             
array([[[1, 1, 1],
        [2, 2, 2],
        [3, 3, 3]],

       [[4, 4, 4],
        [5, 5, 5],
        [6, 6, 6]],

       [[7, 7, 7],
        [8, 8, 8],
        [9, 9, 9]]])
>>> arr2
array([[[1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]],

       [[1, 0, 0],
        [0, 1, 0],
        [0, 0, 0]],

       [[1, 0, 0],
        [0, 0, 0],
        [0, 0, 0]]])
>>> idx = arr2.sum(axis=2) == 0
>>> idx
array([[False, False, False],
       [False, False,  True],
       [False,  True,  True]])
>>> arr2[idx] = arr1[idx]
>>> arr2
array([[[1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]],

       [[1, 0, 0],
        [0, 1, 0],
        [6, 6, 6]],

       [[1, 0, 0],
        [8, 8, 8],
        [9, 9, 9]]])
Sign up to request clarification or add additional context in comments.

8 Comments

great answer! note: you can use idx = (arr2 == 0).all(axis=1) and not rely on sum and non-negative values.
Close, but I am looking for every zero in arr2 to be replaced with its value in arr1, not just the lines that are only zeros.
@incarnadine you probably have a 3d array, which is a matrix of [R,G,B] pixels, which is exactly what's described in this answer.
@incarnadine that's what you've described in the question: you want black pixels (triples of 0) to be replaced, not every 0. For every 0 it's even simpler, just use idx = arr2 == 0.
@avysk and it gave the same answer! lol! subtle bugs >_<
|
1

You can use np.copyto:

from scipy.misc import face
from PIL import Image
 
img = face()
out = np.random.randint(-1000,256,img.shape).clip(0,255).astype(np.uint8)

Image.fromarray(out).show()

np.copyto(out,img,where=(out==0).all(axis=-1,keepdims=True))

Image.fromarray(out).show()

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.