Detecting image differences using Python and OpenCV

Danny Morris



This post was inspired by this post written by Adrian Rosebrock of PyImageSearch.

This document shows how to detect differences between two images using Python and OpenCV.

Python packages

from skimage.measure import compare_ssim
import argparse
import imutils
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

Read and resize images

# load the two input images
image_orig = cv2.imread("credit-card-original.PNG")
image_mod = cv2.imread("credit-card-modified.PNG")

# resize for faster processing
resized_orig = cv2.resize(image_orig, (300, 200))    
resized_mod = cv2.resize(image_mod, (300, 200))


Convert images to grayscale

gray_orig = cv2.cvtColor(resized_orig, cv2.COLOR_BGR2GRAY)
gray_mod = cv2.cvtColor(resized_mod, cv2.COLOR_BGR2GRAY)

Compute Structural Similarity Index between images and obtain difference image

(score, diff) = compare_ssim(gray_orig, gray_mod, full=True)
diff = (diff * 255).astype("uint8")
print("Structural Similarity Index: {}".format(score))

## Structural Similarity Index: 0.9537481523548417

Obtain image contours

# threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
thresh = cv2.threshold(diff, 0, 25, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

Plot image differences

# loop over the contours
for c in cnts:
# compute the bounding box of the contour and then draw the
# bounding box on both input images to represent where the two
# images differ
    (x, y, w, h) = cv2.boundingRect(c)
    cv2.rectangle(resized_orig, (x, y), (x + w, y + h), (0, 0, 255), 2)
    cv2.rectangle(resized_mod, (x, y), (x + w, y + h), (0, 0, 255), 2)
# show the output images
plt.imshow("Original", resized_orig)
plt.imshow("Modified", resized_mod)
cv2.imshow("Diff", diff)
cv2.imshow("Thresh", thresh)