Last active
February 18, 2021 03:25
-
-
Save rachmadaniHaryono/9748fa415cbe45cf34a593a5cf57ce0e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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