I have tried 3 methods mentioned above and elsewhere.
There seems to be two main type of image comparison, Pixel-By-Pixel, and Histogram.
I have tried both, and Pixel one does fail 100%, as it actually should, as if we shift second image by 1 pixel, all pixel will not match and we will have 100% no match.
But Histogram comparison should work really good in theory, but it does not.
Here are two images with slightly shifted view port and histogram looks 99% similar, yet algorithm produces result that says "Very Different"
Centered
Same, but Shifted ~15º
4 different Algorithm result:
- Perfect match: False
- Pixel difference: 115816402
- Histogram Comparison: 83.69564286668303
- HistComparison: 1744.8160719686186
And same comparison of the first image (centred QR) with a 100% different image:
Totally different image and histogram
Algorithm results:
- Perfect match: False
- Pixel difference: 207893096
- HistogramComparison: 104.30194643642095
- HistComparison: 6875.766716148522
Any suggestions on how to measure two image difference in a more precise and usable way would be much appreciated. At this stage none of these algorithms seem to produce usable results as slightly different image has very similar/close results to a 100% different image.
from PIL import Image
from PIL import ImageChops
from functools import reduce
import numpy
import sys
import math
import operator
# Just checking if images are 100% the same
def equal(im1, im2):
img1 = Image.open(im1)
img2 = Image.open(im2)
return ImageChops.difference(img1, img2).getbbox() is None
def histCompare(im1, im2):
h1 = Image.open(im1).histogram()
h2 = Image.open(im2).histogram()
rms = math.sqrt(reduce(operator.add, map(lambda a, b: (a - b)**2, h1, h2)) / len(h1))
return rms
# To get a measure of how similar two images are, we calculate the root-mean-square (RMS)
# value of the difference between the images. If the images are exactly identical,
# this value is zero. The following function uses the difference function,
# and then calculates the RMS value from the histogram of the resulting image.
def rmsdiff_1997(im1, im2):
#"Calculate the root-mean-square difference between two images"
img1 = Image.open(im1)
img2 = Image.open(im2)
h = ImageChops.difference(img1, img2).histogram()
# calculate rms
return math.sqrt(reduce(operator.add,
map(lambda h, i: h * (i**2), h, range(256))
) / (float(img1.size[0]) * img1.size[1]))
# Pixel by pixel comparison to see if images are reasonably similar.
def countDiff(im1, im2):
s = 0
img1 = Image.open(im1)
img2 = Image.open(im2)
if img1.size != img2.size or img1.getbands() != img2.getbands():
return -1
for band_index, band in enumerate(img1.getbands()):
m1 = numpy.array([p[band_index] for p in img1.getdata()]).reshape(*img1.size)
m2 = numpy.array([p[band_index] for p in img2.getdata()]).reshape(*img2.size)
s += numpy.sum(numpy.abs(m1 - m2))
return s
print("[Same Image]")
print("Perfect match:", equal("data/start.jpg", "data/start.jpg"))
print("Pixel difference:", countDiff("data/start.jpg", "data/start.jpg"))
print("Histogram Comparison:", rmsdiff_1997("data/start.jpg", "data/start.jpg"))
print("HistComparison:", histCompare("data/start.jpg", "data/start.jpg"))
print("\n[Same Position]")
print("Perfect match:", equal("data/start.jpg", "data/end.jpg"))
print("Pixel difference:", countDiff("data/start.jpg", "data/end.jpg"))
print("Histogram Comparison:", rmsdiff_1997("data/start.jpg", "data/end.jpg"))
print("HistComparison:", histCompare("data/start.jpg", "data/end.jpg"))
print("\n[~5º off]")
print("Perfect match:", equal("data/start.jpg", "data/end2.jpg"))
print("Pixel difference:", countDiff("data/start.jpg", "data/end2.jpg"))
print("Histogram Comparison:", rmsdiff_1997("data/start.jpg", "data/end2.jpg"))
print("HistComparison:", histCompare("data/start.jpg", "data/end2.jpg"))
print("\n[~15º off]")
print("Perfect match:", equal("data/start.jpg", "data/end3.jpg"))
print("Pixel difference:", countDiff("data/start.jpg", "data/end3.jpg"))
print("Histogram Comparison:", rmsdiff_1997("data/start.jpg", "data/end3.jpg"))
print("HistComparison:", histCompare("data/start.jpg", "data/end3.jpg"))
print("\n[100% different]")
print("Perfect match:", equal("data/start.jpg", "data/end4.jpg"))
print("Pixel difference:", countDiff("data/start.jpg", "data/end4.jpg"))
print("Histogram Comparison:", rmsdiff_1997("data/start.jpg", "data/end4.jpg"))
print("HistComparison:", histCompare("data/start.jpg", "data/end4.jpg"))