Чтобы найти различия между двумя изображениями, вы можете использовать Индекс структурного сходства (SSIM), который был представлен в Оценка качества изображения: от видимости ошибок до структурного сходства .Этот метод уже реализован в библиотеке scikit-image для обработки изображений.Вы можете установить scikit-image
с pip install scikit-image
.
Используя функцию compare_ssim()
из scikit-image, он возвращает score
и разностное изображение diff
.score
представляет индекс структурного сходства между двумя входными изображениями и может находиться в диапазоне [-1,1] со значениями, близкими к единице, представляющей более высокое сходство.Но поскольку вас интересует только то, где два изображения различаются, изображение diff
- то, что вы ищете.Изображение diff
содержит фактические различия между двумя изображениями.
Далее мы находим все контуры, используя cv2.findContours()
и фильтруем для наибольшего контура.Наибольший контур должен представлять новую обнаруженную разницу, так как небольшие различия должны быть меньше, чем добавленный маркер.
Здесь самая большая обнаруженная разница между двумя изображениями
Вот фактическаяразличия между двумя изображениями.Обратите внимание на то, как были зафиксированы все различия, но поскольку новая пуля, скорее всего, является наибольшим контуром, мы можем отфильтровать все другие незначительные движения между кадрами камеры.
Примечание: этот метод работает довольно хорошо, если предположить, что новая пуля будет иметь самый большой контур в изображении diff
.Если самая новая дыра была меньше, вам, возможно, придется замаскировать существующие области, и любые новые контуры в новом изображении будут новыми дырами (при условии, что изображение будет равномерным черным фоном с белыми дырами).
from skimage.measure import compare_ssim
import cv2
before = cv2.imread('before.png')
after = cv2.imread('after.png')
# 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)
# 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]
contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]
# The largest contour should be the new detected difference
if len(contour_sizes) > 0:
largest_contour = max(contour_sizes, key=lambda x: x[0])[1]
x,y,w,h = cv2.boundingRect(largest_contour)
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.imshow('before', before)
cv2.imshow('after', after)
cv2.imshow('diff',diff)
cv2.waitKey(0)
Вот еще один пример с различными входными изображениями.SSIM довольно хорош для обнаружения различий между изображениями