Skip to content

Instantly share code, notes, and snippets.

@rachmadaniHaryono
Last active February 18, 2021 03:25
Show Gist options
  • Save rachmadaniHaryono/9748fa415cbe45cf34a593a5cf57ce0e to your computer and use it in GitHub Desktop.
Save rachmadaniHaryono/9748fa415cbe45cf34a593a5cf57ce0e to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
"""based on this article
https://www.pyimagesearch.com/2017/06/19/image-difference-with-opencv-and-python/
tested on python 3.6.2, ubuntu 18.10 with following package
imutils==0.5.2
matplotlib==3.0.2
opencv-python==3.4.3.18
scikit-image==0.14.1
to install package:
```console
$ pip install scikit-image opencv-python matplotlib imutils
```
"""
import argparse
# import the necessary packages
from matplotlib import pyplot as plt
from skimage.measure import compare_ssim
import cv2
import imutils
def image_resize(image, width=None, height=None, inter=cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation=inter)
# return the resized image
return resized
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-f", "--first", required=True, help="first input image")
ap.add_argument("-s", "--second", required=True, help="second")
args = vars(ap.parse_args())
# load the two input images
imageA = cv2.imread(args["first"])
imageB = cv2.imread(args["second"])
max_w, max_h = None, None
if imageA.shape[:2] != imageB.shape[:2]:
max_w = max(imageA.shape[0], imageB.shape[0])
max_h = max(imageA.shape[1], imageB.shape[1])
# convert the images to grayscale
if max_w or max_h:
grayA = cv2.cvtColor(
imutils.resize(imageA, width=max_w, height=max_h), cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(
imutils.resize(imageB, width=max_w, height=max_h), cv2.COLOR_BGR2GRAY)
if grayA.shape != grayB.shape:
gray_max_w = max(grayA.shape[0], grayB.shape[0])
gray_max_h = max(grayA.shape[1], grayB.shape[1])
right_a, bottom_a = gray_max_h-grayA.shape[1], gray_max_w-grayA.shape[0]
right_b, bottom_b = gray_max_h-grayB.shape[1], gray_max_w-grayB.shape[0]
if (bottom_a, right_a) != (0, 0):
grayA = cv2.copyMakeBorder(
grayA, 0, bottom_a, 0, right_a,
cv2.BORDER_CONSTANT, value=(0, 0, 0))
if (bottom_b, right_b) != (0, 0):
o_grayB = grayB.copy()
grayB = cv2.copyMakeBorder(
grayB, 0, bottom_b, 0, right_b,
cv2.BORDER_CONSTANT, value=(0, 0, 0))
else:
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
print("SSIM: {}".format(score))
# threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
thresh = cv2.threshold(diff, 0, 255, 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)
# 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(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2)
# show the output images using cv2
# cv2.imshow("Original", imageA)
# cv2.imshow("Modified", imageB)
# cv2.imshow("Diff", diff)
# cv2.imshow("Thresh", thresh)
# cv2.waitKey(0)
# cv2.imshow("Original", imageA)
plt.subplot(221), plt.imshow(imutils.opencv2matplotlib(imageA)), plt.title('A')
plt.gca().axes.get_xaxis().set_visible(False)
plt.gca().axes.get_yaxis().set_visible(False)
plt.subplot(222), plt.imshow(imutils.opencv2matplotlib(imageB)), plt.title('B')
plt.gca().axes.get_xaxis().set_visible(False)
plt.gca().axes.get_yaxis().set_visible(False)
plt.subplot(223), plt.imshow(diff, cmap='gray'), plt.title('diff')
plt.gca().axes.get_xaxis().set_visible(False)
plt.gca().axes.get_yaxis().set_visible(False)
plt.subplot(224), plt.imshow(thresh, cmap='gray'), plt.title('thresh')
plt.gca().axes.get_xaxis().set_visible(False)
plt.gca().axes.get_yaxis().set_visible(False)
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment