Чтобы визуализировать различия между двумя изображениями, мы можем использовать количественный подход для определения точных расхождений между изображениями, используя Структурный индекс сходства (SSIM), который был представлен в Оценка качества изображения: с ошибкой Видимость структурного сходства . Этот метод уже реализован в библиотеке scikit-image для обработки изображений. Вы можете установить scikit-image
с pip install scikit-image
.
Используя функцию compare_ssim()
из scikit-image, он возвращает score
и разностное изображение diff
. score
представляет индекс структурного сходства между двумя входными изображениями и может находиться в диапазоне [-1,1] со значениями, близкими к единице, представляющей более высокое сходство. Но поскольку вас интересует только то, где эти два изображения различаются, мы сосредоточимся на изображении diff
. В частности, изображение diff
содержит фактические различия изображения с более темными областями, имеющими большее расхождение. Большие области несоответствия выделены черным, а меньшие различия - серым.
Серая шумная область, вероятно, из-за сжатия .jpg с потерями. Мы получили бы более чистый результат, если бы использовали формат сжатия без потерь. Оценка SSIM после сравнения двух изображений показывает, что они очень похожи.
Сходство изображения 0,9198863419190031
Теперь мы фильтруем изображение diff
, так как нам нужно только найти большие различия между изображениями. Мы перебираем каждый контур, фильтруем, используя минимальную пороговую область, чтобы удалить серый шум, и выделяем различия с помощью ограничительной рамки Вот результат.
Чтобы визуализировать точные различия, мы заполняем контуры маской и исходным изображением.
from skimage.measure import compare_ssim
import cv2
import numpy as np
before = cv2.imread('left.jpg')
after = cv2.imread('right.jpg')
# Convert images to grayscale
before_gray = cv2.cvtColor(before, cv2.COLOR_BGR2GRAY)
after_gray = cv2.cvtColor(after, cv2.COLOR_BGR2GRAY)
# Compute SSIM between two images
(score, diff) = compare_ssim(before_gray, after_gray, full=True)
print("Image similarity", score)
# The diff image contains the actual image differences between the two images
# and is represented as a floating point data type in the range [0,1]
# so we must convert the array to 8-bit unsigned integers in the range
# [0,255] before we can use it with OpenCV
diff = (diff * 255).astype("uint8")
# 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]
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
mask = np.zeros(before.shape, dtype='uint8')
filled_after = after.copy()
for c in contours:
area = cv2.contourArea(c)
if area > 40:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(before, (x, y), (x + w, y + h), (36,255,12), 2)
cv2.rectangle(after, (x, y), (x + w, y + h), (36,255,12), 2)
cv2.drawContours(mask, [c], 0, (0,255,0), -1)
cv2.drawContours(filled_after, [c], 0, (0,255,0), -1)
cv2.imshow('before', before)
cv2.imshow('after', after)
cv2.imshow('diff',diff)
cv2.imshow('mask',mask)
cv2.imshow('filled after',filled_after)
cv2.waitKey(0)