Does anyone have any suggestions as to how I might do image comparison in python to detect changes within an image? I\'m currently working on an app that will monitor my are
This might be a naive approach, but it's a simple place to begin. I'm sure you will be influenced by camera noise and you may want to distinguish changes in lighting from changes in image composition. But here's what came to my mind:
You can use PIL ImageChops to efficiently take a difference between images. Then you can take the entropy of that diff to get a single-value threshold.
It seems to work:
from PIL import Image, ImageChops
import math
def image_entropy(img):
"""calculate the entropy of an image"""
# this could be made more efficient using numpy
histogram = img.histogram()
histogram_length = sum(histogram)
samples_probability = [float(h) / histogram_length for h in histogram]
return -sum([p * math.log(p, 2) for p in samples_probability if p != 0])
# testing..
img1 = Image.open('SnowCam_main1.jpg')
img2 = Image.open('SnowCam_main2.jpg')
img3 = Image.open('SnowCam_main3.jpg')
# No Difference
img = ImageChops.difference(img1,img1)
img.save('test_diff1.png')
print image_entropy(img) # 1.58496250072
# Small Difference
img = ImageChops.difference(img1,img2)
img.save('test_diff2.png')
print image_entropy(img) # 5.76452986917
# Large Difference
img = ImageChops.difference(img1,img3)
img.save('test_diff3.png')
print image_entropy(img) # 8.15698432026
This, I believe is a much better algorithm for image entropy since it bins 3-dimensionally in color-space rather than creating a separate histogram for each band.
EDIT- this function was changed 6-Apr-2012
import numpy as np
def image_entropy(img):
w,h = img.size
a = np.array(img.convert('RGB')).reshape((w*h,3))
h,e = np.histogramdd(a, bins=(16,)*3, range=((0,256),)*3)
prob = h/np.sum(h) # normalize
prob = prob[prob>0] # remove zeros
return -np.sum(prob*np.log2(prob))
These are my test images:
Image 1
Image 2
Image 3