Spot the difference

Usual modules

In [1]:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
from matplotlib.patches import Rectangle

Input image

In [134]:
image = mpimg.imread('sea.jpg')

fig, ax = plt.subplots(1,2, figsize=(20,10))
ax[0].imshow(image)
ax[1].imshow(image[ 80:-10, 50:-50, :]) # cropped
ax[0].add_patch(Rectangle((50,80), width = image.shape[1]-1-50-50, height = image.shape[0]-1-10-80,  ec='r', fc='none'))

plt.show()

Crop the 2nd image in 2 parts, overlap them and find the best match

In [135]:
#cropped = np.delete(image[ 10:-20, 20:-20, :],[3],axis=2)
cropped = image[ 80:-10, 50:-50, :]/255
cropped.shape
Out[135]:
(910, 756, 3)
In [148]:
crop1 = cropped[20:410,10:-10, :]
crop2 = cropped[-crop1.shape[0]:,10:-10, :] # <-- same size of crop1!

fig  = plt.figure(figsize=(20,10))
grid = fig.add_gridspec(2,4)
ax1  = fig.add_subplot(grid[0, :2])
ax2  = fig.add_subplot(grid[0, 2:])
ax3  = fig.add_subplot(grid[1, 1:3])
ax1.imshow(crop1)
ax2.imshow(crop2) # cropped
ax3.imshow(np.abs(crop1-crop2))
plt.show()

Find a better match for crop2

In [149]:
crop1.shape
Out[149]:
(390, 736, 3)
In [168]:
#crop1 = cropped[20:410,10:-10, :]
#crop2 = cropped[-crop1.shape[0]:,10:-10, :] # <-- same size of crop1!

difflist=[]
x = range(1,50)
for ivt in x:
    diff = np.abs(crop1 - cropped[-crop1.shape[0]-ivt :-ivt,10:-10, :]).sum()
    difflist.append(diff)
        
fig, ax = plt.subplots(1,1, figsize=(10,5))
ax.plot(x,difflist, 'o')
ax.plot(x[np.array(difflist).argmin()], np.array(difflist).min(),'*r', markersize=15)
print('min vertical pixel offset is ',x[np.array(difflist).argmin()])
min vertical pixel offset is  27
In [173]:
difflist=[]
x = range(0,10)
for ihz in x:
    diff = np.abs(crop1 - cropped[-crop1.shape[0]-27 :-27,15-ihz:-5-ihz, :]).sum()
    difflist.append(diff)
        
fig, ax = plt.subplots(1,1, figsize=(10,5))
ax.plot(x,difflist, 'o')
ax.plot(x[np.array(difflist).argmin()], np.array(difflist).min(),'*r', markersize=15)
print('min horiz pixel offset is ',x[np.array(difflist).argmin()])


plt.show()
min horiz pixel offset is  4
In [174]:
crop1 = cropped[20:410,10:-10, :]
crop2 = cropped[-crop1.shape[0]-27:-27,11:-9,:] # <-- same size of crop1!

fig  = plt.figure(figsize=(20,10))
grid = fig.add_gridspec(2,4)
ax1  = fig.add_subplot(grid[0, :2])
ax2  = fig.add_subplot(grid[0, 2:])
ax3  = fig.add_subplot(grid[1, 1:3])
ax1.imshow(crop1)
ax2.imshow(crop2) # cropped
ax3.imshow(np.abs(crop1-crop2))
plt.show()

Search in the difference image

In [197]:
def pixeldiff(img1, img2):
    return np.abs(img1.sum()-img2.sum())/(img1.sum()+img2.sum())

vt_step, vt_width = 3, 25
hz_step, hz_width = 3, 25

difflist=[]
for ivt in range(0, crop1.shape[0], vt_step):
    for ihz in range(0, crop1.shape[1], hz_step):
        if (ivt+vt_step < crop1.shape[0]) & (ihz+hz_step < crop1.shape[1]):
            difflist.append( [ivt, ihz, pixeldiff(crop1[ivt:ivt+vt_width, ihz:ihz+hz_width], crop2[ivt:ivt+vt_width, ihz:ihz+hz_width])])
In [198]:
adiff = np.array(difflist)
adiff.shape
# sort by diff and take first 20%

highdiff = adiff[adiff[:,-1].argsort()][-int(adiff.shape[0]*0.05):]
In [199]:
rlist = [Rectangle((el[1],el[0]),vt_width,hz_width, ec='r', fc='r', linewidth=0, alpha=0.01) for el in highdiff]
fig, ax = plt.subplots(figsize=(10,10))
#ax.imshow(np.abs(crop1-crop2)/np.abs(crop1+crop2))
ax.imshow((crop1+crop2)/2)
for r in rlist:
    ax.add_patch(r)
ax.axis('off')
plt.show()
In [ ]: