Search code examples
pythonimagexor

XOR-ing and Summing Two Black and White Images


Starting with two images im1 and im2 created with the PIL module, we have the corresponding black and white images,

bw_im1 = im1.convert('1')      

and

bw_im2 = im2.convert('1')    

Each pixel of bw_im2 and bw_im2 is either 0 or 256.

Suppose both bw_im2 and bw_im2 have the same size.

How do you XOR all the corresponding entries and then sum them up?

My Work

I wrote the following stub / proof of concept Python program, but worried that using the code (unpacking/translating over) would be complicated. There might be a more direct and efficient way to process the pixels in the two images.

import numpy as np

M = np.zeros((2, 3))
M[0,2] = 255
M[1,0] = 255
M[1,1] = 255    
print(M)

N = np.zeros((2, 3))
N = np.zeros((2, 3))
N[0,2] = 255
N[1,1] = 255  
N[1,2] = 255
print(N)

list_M = list(M)
list_N = list(N)
xor_signal = 0
for row in range(0, len(list_M)):
    for col in range(0,len(list_M[row])):
        xor_signal = xor_signal + int(bool(list_M[row][col]) !=  bool(list_N[row][col]))

print(xor_signal)

OUTPUT

[[  0.   0. 255.]
 [255. 255.   0.]]
[[  0.   0. 255.]
 [  0. 255. 255.]]
2

Solution

  • You can use PIL's ImageChops like this:

    #!/usr/local/bin/python3
    import numpy as np
    from PIL import Image, ImageChops
    
    # Open images
    im1 = Image.open("im1.png")
    im2 = Image.open("im2.png")
    
    result = ImageChops.logical_xor(im1,im2)
    result.save('result.png')
    

    So, if you start with these two:

    enter image description here

    enter image description here

    The result will be:

    enter image description here

    Of course, if you are a physicist, you can write that like this ;-)

    #!/usr/local/bin/python3
    from PIL import Image, ImageChops 
    ImageChops.logical_xor(Image.open("im1.png"), Image.open("im2.png")).save('result.png')
    

    Or you can use Numpy's XOR like this:

    #!/usr/local/bin/python3
    import numpy as np
    from PIL import Image
    
    # Open images
    im1 = Image.open("im1.png")
    im2 = Image.open("im2.png")
    
    # Make into Numpy arrays
    im1np = np.array(im1)*255
    im2np = np.array(im2)*255
    
    # XOR with Numpy
    result = np.bitwise_xor(im1np, im2np).astype(np.uint8)
    
    # Convert back to PIL image and save
    Image.fromarray(result).save('result.png')
    

    You can sum the pixels by adding this at the end:

    print('Sum: {}'.format(np.sum(result)))
    

    Or you can not bother writing any Python and just type the following ImageMagick command into your Terminal:

    magick im1.png im2.png -evaluate-sequence xor result.png
    

    If you are using v6, or older, use the following instead:

    convert im1.png im2.png -evaluate-sequence xor result.png