1

So I have two PIL images of RGBA. What I want to do is find all locations where the RGB values are the same and alpha is 255. It looks like this:

from PIL import Image
import numpy as np
img1 = np.array(Image.open(/path/to/img1).convert('RGBA'), float).reshape(32,32,4)
img2 = np.array(Image.open(/path/to/img2).convert('RGBA'), float).reshape(32,32,4)

# Checks to see if RGB of img1 == RGB of img2 in all locations that A=255
np.where((img1[:,:,:-1] == img2[:,:,:-1]) &\ # RGB check
         (img1[:,:,3] == 255)) # Alpha check

But this results in operands could not be broadcast together with shapes (32,32,3) (32,32).
I didn't think I was trying to broadcast them together, I just wanted to find the indeces, which I guess in turn broadcasts them in this statement. Is there another way to do this, or a way to not broadcast unequal shapes?

3
  • 1
    img1[:, :, :-1] results in an array of shape 32, 32, 3. img1[:, :, 3] results in an array of shape 32, 32. Commented May 20, 2016 at 19:12
  • @mgilson yes I know. But is what I'm trying to accomplish clear? I thought the above would work because I thought np.where would allow for multiple "where" statements, not broadcast them together Commented May 20, 2016 at 19:14
  • And, to point out a bit of style, the \ for line continuation is unnecessary here. Python concatenates lines that are in unenclosed braces, brackets or parenthesis (as is the case here). In fact, PEP 8 (the "official" style guide) recommends using parenthesis to continue lines and never using the \ for line continuation. Commented May 20, 2016 at 19:33

1 Answer 1

3

Use .all(axis=-1) to find locations where all three RGB values are equal:

np.where((img1[..., :-1] == img2[..., :-1]).all(axis=-1) 
         & (img1[..., 3] == 255)) 

As mgilson points out, (img1[..., :-1] == img2[..., :-1]) has shape (32, 32, 3). Calling .all(axis-1) reduces the last axis to a scalar boolean value, so

(img1[..., :-1] == img2[..., :-1]).all(axis=-1) 

has shape (32, 32). This matches the shape of (img1[..., 3] == 255), so these boolean arrays can be combined with the bitwise-and operator, &.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 I think the reduction along the last axis is what OP is asking for. I wonder if OP wants to make sure that the alpha values are the same too ... (In which case it simplifies to (img1 == img2).all(axis=-1) without the ellipsis)
Awesome! This is exactly what I wanted. And yes @mgilson I was able to add yours too to get the alpha check. Thanks!
I'll also point out that & is not the logical-and operator (though it's frequently used as such). It's the binary & operator which is special cased to return an array of logicals if both the right-hand and left-hand sides are logical arrays. For logical and, I've always recommended using np.logical_and (which doesn't have the precedence issues that the & operator has that sometimes bite people trying to use it)...

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.