skip to Main Content

I have two similar masked images with transparent backgrounds.
I want to get image difference and expect it as low value as images are similar.

lenna1.png lenna2.png

But the result shows huge difference over transparent area which looks just same.
(white means diff)

diff_res = ImageChops.difference(lenna1, lenna2).convert('RGB')

diff_res

I checked lenna1, lenna2 image difference on some website and it says images are just same except small diffs on boundaries.

I then suspected alpha channel value and converted lenna1, lenna2 into ‘RGB’.
and it shows one’s background as black but the other’s as white.

lenna1 = Image.open('lenna1.png')
lenna2 = Image.open('lenna2.png')

converted_lenna1 = lenna1.convert('RGB')
converted_lenna2 = lenna2.convert('RGB')

converted_lenna1   converted_lenna2

Now I know convert() makes transparent area into black as default. But I still don’t get it.

  1. Why there’s image difference between transparent area?
  2. Why some transparent image became white and How can I make my own “will be white” transparent image?

*I also tested with same alpha level using .putalpha()

Thank you for reading this question.

2

Answers


  1. Both images have transparency in them, it’s just that one has white pixels made transparent and the other has black pixels made transparent. Another way of saying the same thing is that the underlying colour of transparent pixels is black in one image and white in the other. You can’t see the difference because they are transparent!

    Here is lenna1 with the alpha layer removed on the left, then the alpha layer itself on the right:

    enter image description here

    And here is lenna2 with the alpha layer removed on the left, then the alpha layer itself on the right:

    enter image description here

    You can make them the same by finding all the transparent pixels, and making them white like this:

    # Load the image and make into Numpy array
    rgba = np.array(Image.open('lena2.png'))
    
    # Make image transparent white anywhere it is transparent
    rgba[rgba[...,-1]==0] = [255,255,255,0]
    
    # Make back into PIL Image and save
    Image.fromarray(rgba).save('result.png')
    

    If you want to make the transparent pixels visible blue so you can see them for testing, use:

    rgba[rgba[...,-1]==0] = [0,0,255,255]
    

    If you have ImageMagick installed, you can force all transparent pixels to become the colour of your choice, say magenta, in Terminal:

    magick lenna1.png -background magenta -alpha background result.png
    

    That often means you can improve PNG compression and decrease PNG file sizes by making all transparent pixels black and, as a result, the image is likely to compress much better than if the transparent pixels are all wildly different colours:

    magick image.png -background black -alpha background result.png
    
    Login or Signup to reply.
  2. In Imagemagick 7, you can do masked compare to ignore regions of the image. (Python Wand 0.5.3 supports Imagemagick 7, though I do not know if it supports the masked compare, yet). Here is an example in command line Imagemagick 7:

    White:

    enter image description here

    Green:

    enter image description here

    Mask:

    enter image description here

    magick compare -metric rmse -read-mask hat_mask.png hat_white.png hat_green.png hat_diff.png
    
    0 (0)
    

    Differences would show in the following as red.

    enter image description here

    If I use your images:

    magick image1.png -alpha extract mask.png
    magick compare -metric rmse -read-mask mask.png image1.png image2.png -alpha deactivate diff.png
    
    or
    
    magick compare -metric rmse  ( image1.png -alpha extract -write mpr:mask +delete ) -read-mask mpr:mask image1.png image2.png -alpha deactivate diff.png
    
    
    7179.85 (0.109557) <--- ~11% different in opaque area
    

    enter image description here

    If we compare the whole image including the areas under the transparent regions, then

    magick compare -metric rmse image1.png image2.png -alpha off null:
    59598.7 (0.909419) <--- ~91% different over the whole area
    

    If we include the alpha channel, then due to the inclusion of two same alpha channels, this decreases the comparison metric, which is misleading, and we get:

    magick compare -metric rmse image1.png image2.png null:
    
    or
    
    magick compare -metric rmse -channel rgba image1.png image2.png null:
    
    2828.15 (0.0431548) <--- ~4.3% different.
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search