Reputation: 1
I'm looking for an algorithm to compare two images (I work with python).
I find the PIL library, numpy/scipy and opencv. I know how to transform in greyscale, binary, make an histogram, .... that's ok but I don't know what I have to do with the two images to say "yes they're similar // they're probably similar // they don't match".
Do you know the right way to go about it ?
Upvotes: 0
Views: 1594
Reputation: 1096
A script that I put together, for visual inspection of changes in image. The result is an image that is white, except for pixels that are different. The pixels are proportionally darker, the bigger the difference; and they are "tinted" to show the color change e.g. if the old image was more red, the diff image will show cyan areas; if the new image is more read instead, the diff image will show red areas.
The only defect is being slow, but I am sure that it can be improved using numpy or simply using comprehensions that handle pixel groups.
#!/usr/bin/env python
TINT = 1 # exxagerate differences in tone
MINUTE = 5 # less than "x" points of difference
INCREASE_MINUTE = 2 # boost of minute differences
import sys
from PIL import Image
img1 = Image.open(sys.argv[1])
img2 = Image.open(sys.argv[2])
i1 = img1.load()
i2 = img2.load()
if img1.size != img2.size:
print "Images %s and %s have different sizes, cannot compare" \
% (sys.argv[1], sys.argv[2])
sys.exit(1)
imgmap = Image.new( 'RGB', img1.size, "white")
imap = imgmap.load()
row_averages = []
for y in range(img1.size[1]):
for x in range(img1.size[0]):
p1 = i1[x, y]
p2 = i2[x, y]
diffpixel = [255, 255, 255]
# color differences
diffs = [p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]]
absdiff = reduce(lambda a, b: abs(a) + abs(b), diffs)
diffsmag = [a * TINT for a in diffs]
diffplus = [max(0, a) for a in diffs]
totplus = reduce(lambda a, b: a + b, diffplus)
diffminus = [min(0, a) for a in diffs]
# apply negative differences (e.g. less red -> take red)
diffpixel = [ a + b for a, b in zip(diffpixel, diffminus)]
# subtract positive differences (e.g. more red -> take from non-red channels)
diffpixel = [ a - totplus for a in diffpixel ]
# ... put back what we took from red
diffpixel = [ a + b for a, b in zip(diffpixel, diffplus)]
if absdiff > 0 and absdiff < MINUTE:
# Increase contrast of minute differences
diffpixel = [a - INCREASE_MINUTE for a in diffpixel]
diffpixel = [max(0, a) for a in diffpixel]
imap[x, y] = tuple(diffpixel)
imgmap.save(sys.argv[3])
Upvotes: 0
Reputation: 8607
A naive implementation would be to aggregate the error/dissimilarity between corresponding normalised pixel coordinates between the two images. More advanced techniques would involve comparing spatial features (using feature detection/computer vision techniques), and color distribution/frequency techniques. You can also experiment with scaling images down (algorithmically, or using hardware/mipmapping if 3D context) before comparing them to provide more tolerance. Bleeding edge AFAIK is wavelet transforms/representations of images.
Of course you could also search for an existing library that does this such as pHash
Upvotes: 1
Reputation: 17218
If you want to check if they are binary equal you can count a checksum on them and compare it. If you want to check if they are similar in some other way , it will be more complicated and definitely would not fit into simple answer posted on Stack Overflow. It just depends on how you define similarity but anyway it would require good programming skills and a lot of code written.
Upvotes: 1