Arwen
Arwen

Reputation: 1

How to compare image with python

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

Answers (3)

epx
epx

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

Preet Kukreti
Preet Kukreti

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

mnowotka
mnowotka

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

Related Questions