6

I have a big RGB image as a numpy array,i want to set all pixel that has R=0,G=0,B=0 to R=255,G=0,B=0. what is the fastest way? i tried:

for pix in result:
    if np.all(np.logical_and(pix[0]==pix[1],pix[2]==0,pix[2]==pix[1])):
        pix [0] = 255

but in this way i don't have a single pixel. there is a similar way that it is not to iterate the index?

1
  • What is the .shape of your image? Commented Nov 18, 2017 at 13:36

2 Answers 2

7

Here is a vectorized solution. Your image is basically an w by h by 3(colors) array. We can make use of the broadcasting rules that are not easy to grasp but are very powerful.

Basically, we compare the whole array to a 3 vector with the values that you are looking for. Due to the broadcasting rules Numpy will then compare each pixel to that three vector and tell you if it matched (so in this specific case, if the red, green and blue matched). You will end up with an boolean array of trues and falses of the same size as the image.

now we only want to find the pixels where all three colors matched. For that we use the "all" method, which is true, if all values of an array are true. If we apply that to a certain axis -- in this case the color axis -- we get an w by h array that is true, wherever all the colors matched.

Now we can apply this 2D boolean mask back to our original w by h by 3 array and get the pixels that match our color. we can now reassign them -- again with broadcasting.

Here is the example code

import numpy as np

#create a 2x2x3 image with ones
img = np.ones( (2,2,3) )

#make the off diagonal pixels into zeros
img[0,1] = [0,0,0]
img[1,0] = [0,0,0]

#find the only zeros pixels with the mask 
#(of course any other color combination would work just as well)
#... and apply "all" along the color axis
mask = (img == [0.,0.,0.]).all(axis=2)

#apply the mask to overwrite the pixels
img[ mask ] = [255,0,0]
Sign up to request clarification or add additional context in comments.

Comments

1

Since all values are positive or null, a simple and efficient way is:

img[img.sum(axis=2)==0,0]=255

img.sum(axis=2)==0 select good pixels in the two first dimensions, 0 the red canal in the third.

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.