How can I compare two images? I found Python's PIL library, but I do not really understand how it works.
-
2well this doesn't make any sense, that's why I asked. An image is basically an array (2D or 3D, depends if you are in RGB/grayscale), and there a multiple ways to compare 2 images : if you need to see if they are identical, image1-image2 will give you the information. If you need to find the transformation between 2 images, that's another thing. – CoMartel Feb 03 '16 at 14:10
7 Answers
To check does jpg files are exactly the same use pillow library:
from PIL import Image
from PIL import ImageChops
image_one = Image.open(path_one)
image_two = Image.open(path_two)
diff = ImageChops.difference(image_one, image_two)
if diff.getbbox():
print("images are different")
else:
print("images are the same")

- 817
- 8
- 15
-
2This might not work correctly if the images have an alpha channel (github.com/python-pillow/Pillow/issues/4849), or are using different modes (pillow.readthedocs.io/en/stable/handbook/concepts.html#modes). – Yay295 Jul 24 '22 at 19:04
-
weird, I get a failure: `AssertionError: comparison of imgs failed: diff.getbbox()=None` but I'm nearly certain it should work. Why would that be? – Charlie Parker Oct 03 '22 at 18:27
Based on Victor Ilyenko's answer, I needed to convert the images to RGB as PIL fails silently when the .png you're trying to compare contains a alpha channel.
image_one = Image.open(path_one).convert('RGB')
image_two = Image.open(path_two).convert('RGB')

- 3,782
- 4
- 16
- 33

- 151
- 1
- 4
-
3Doesn’t that mean that an image with an alpha channel and another with no such channel would be seen as the same even if they’re not? – bfontaine Dec 16 '20 at 10:32
-
Yes, this excludes the alpha channel from comparison. I would recommend using imagemagick: `compare -metric AE $file1 $file2 /dev/null`. – mara004 Oct 03 '21 at 11:03
-
weird, I get a failure: `AssertionError: comparison of imgs failed: diff.getbbox()=None` but I'm nearly certain it should work. Why would that be? – Charlie Parker Oct 03 '22 at 18:31
It appears that Viktor's implementation can fail when the images are different sizes.
This version also compares alpha values. Visually identical pixels are (I think) treated as identical, such as (0, 0, 0, 0) and (0, 255, 0, 0).
from PIL import ImageChops
def are_images_equal(img1, img2):
equal_size = img1.height == img2.height and img1.width == img2.width
if img1.mode == img2.mode == "RGBA":
img1_alphas = [pixel[3] for pixel in img1.getdata()]
img2_alphas = [pixel[3] for pixel in img2.getdata()]
equal_alphas = img1_alphas == img2_alphas
else:
equal_alphas = True
equal_content = not ImageChops.difference(
img1.convert("RGB"), img2.convert("RGB")
).getbbox()
return equal_size and equal_alphas and equal_content

- 61
- 2
- 4
-
weird, I get a failure: `AssertionError: comparison of imgs failed: diff.getbbox()=None` but I'm nearly certain it should work. Why would that be? – Charlie Parker Oct 03 '22 at 18:31
-
No idea, maybe there's something unusual about the images. If you're running a debugger you could probably find the point the code diverges from the usual path. – Toren Darby Oct 03 '22 at 19:28
-
This won't work if the alpha channel has non-matching colors like (0,0,0,0) and (0,255,0,0). I had to implement a different solution because of this shortcoming – jramm Jan 21 '23 at 16:22
Another implementation of Viktor's answer using Pillow:
from PIL import Image
im1 = Image.open('image1.jpg')
im2 = Image.open('image2.jpg')
if list(im1.getdata()) == list(im2.getdata()):
print("Identical")
else:
print ("Different")
Note:
This might not work correctly if the images have an alpha channel, or are using different modes.

- 657
- 4
- 29
-
This might not work correctly if the images have an alpha channel (https://github.com/python-pillow/Pillow/issues/4849), or are using different modes (https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes). – Yay295 Jul 24 '22 at 19:04
-
-
@CharlieParker whatever Image.open() returns. To be more precise, Image. – Michael Oct 05 '22 at 05:51
That did work for me, you just have to set the quantity of different pixels you accept, in my case 100, as the image diference was a complete black image but still had 25 diferent pixels. I tested other completelly diffferent images and they had diferrent pixels by thousands:
from PIL import ImageChops
if len(set(ImageChops.difference(img1, img2).getdata())) > 100:
print("Both images are diffent!")

- 101
- 1
- 1
You can use ImageChops.difference
in combination with getbbox
:
from PIL import Image
from PIL import ImageChops
def are_equal(image_a: Image, image_b: Image) -> bool:
diff = ImageChops.difference(image_a, image_b)
channels = diff.split()
for channel in channels:
if channel.getbbox() is not None:
return False
return True
The reason why we need to split the channels is because of the (possible presence of an) alpha channel. If you have two images that have exactly the same alpha channel (e.g. by both being fully opaque), then ImageChops.difference
will produce an image whose alpha channel is zero all over. This means that for the pixel values of the image, we ignore the other channels because we know they final pixel is just black. Thus, the bbox
of the difference of two fully opaque images is None
, which is not what we want.

- 31
- 1
Just to compare if same pixel information for all pixels by numpy to check if all pixel data same.
from pathlib import Path
from PIL import Image
import numpy as np
import PySimpleGUI as sg
def same(path1, path2):
try:
im1, im2 = Image.open(path1), Image.open(path2)
except Exception as e:
return e
ar1, ar2 = np.asarray(im1), np.asarray(im2)
im1.close(), im2.close()
return "Same Images" if np.array_equal(ar1, ar2) else "Different Images"
layout = [
[sg.Text("Image File 1"), sg.Input(key='File 1'), sg.FileBrowse()],
[sg.Text("Image File 2"), sg.Input(key='File 2'), sg.FileBrowse()],
[sg.Push(), sg.Button("Check"), sg.Push()],
[sg.Text("(Result)", size=0, justification='center', expand_x=True, key='Result')],
]
window = sg.Window('Comparison for two Image files', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == 'Check':
window['Result'].update(same(values["File 1"], values["File 2"]))
window.close()

- 11,284
- 2
- 9
- 23