Обнаружение и визуализация различий между двумя изображениями с OpenCV Python - PullRequest
6 голосов
/ 17 мая 2019

У меня есть два изображения, и я хотел бы показать, в чем различия. Я хочу добавить цвет к двум изображениям, чтобы пользователь мог четко различить все различия в течение одной или двух секунд.

Например, вот два изображения с небольшими отличиями:

leftImage.jpg:

first image

rightImage.jpg:

second image

Мой текущий подход, чтобы сделать различия очевидными, состоит в том, чтобы создать маску (разницу между двумя изображениями), покрасить ее в красный цвет, а затем добавить ее к изображениям. Цель состоит в том, чтобы четко обозначить все различия ярко-красным цветом. Вот мой текущий код:

import cv2

# load images
image1 = cv2.imread("leftImage.jpg")
image2 = cv2.imread("rightImage.jpg")

# compute difference
difference = cv2.subtract(image1, image2)

# color the mask red
Conv_hsv_Gray = cv2.cvtColor(difference, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY_INV |cv2.THRESH_OTSU)
difference[mask != 255] = [0, 0, 255]

# add the red mask to the images to make the differences obvious
image1[mask != 255] = [0, 0, 255]
image2[mask != 255] = [0, 0, 255]

# store images
cv2.imwrite('diffOverImage1.png', image1)
cv2.imwrite('diffOverImage2.png', image1)
cv2.imwrite('diff.png', difference)

diff.png:

enter image description here

diffOverImage1.png

enter image description here

diffOverImage2.png

enter image description here

Проблема с текущим кодом: Вычисленная маска показывает некоторые различия, но не все из них (см., Например, крошечный кусочек в верхнем правом углу или веревку в синем пакете). Эти различия показаны очень слабо в вычисленной маске, но они должны быть четко красными, как и другие различия.

Ввод: 2 изображения с некоторыми отличиями.

Ожидаемый результат: 3 изображения: два входных изображения, но с выделенными различиями (четко выделены настраиваемым цветом) и третье изображение, содержащее только различия (маска).

Ответы [ 4 ]

7 голосов
/ 17 мая 2019

image image

Чтобы визуализировать различия между двумя изображениями, мы можем использовать количественный подход для определения точных расхождений между изображениями, используя Структурный индекс сходства (SSIM), который был представлен в Оценка качества изображения: с ошибкой Видимость структурного сходства . Этот метод уже реализован в библиотеке scikit-image для обработки изображений. Вы можете установить scikit-image с pip install scikit-image.

Используя функцию compare_ssim() из scikit-image, он возвращает score и разностное изображение diff. score представляет индекс структурного сходства между двумя входными изображениями и может находиться в диапазоне [-1,1] со значениями, близкими к единице, представляющей более высокое сходство. Но поскольку вас интересует только то, где эти два изображения различаются, мы сосредоточимся на изображении diff. В частности, изображение diff содержит фактические различия изображения с более темными областями, имеющими большее расхождение. Большие области несоответствия выделены черным, а меньшие различия - серым.

image image

Серая шумная область, вероятно, из-за сжатия .jpg с потерями. Мы получили бы более чистый результат, если бы использовали формат сжатия без потерь. Оценка SSIM после сравнения двух изображений показывает, что они очень похожи.

Сходство изображения 0,9198863419190031

Теперь мы фильтруем изображение diff, так как нам нужно только найти большие различия между изображениями. Мы перебираем каждый контур, фильтруем, используя минимальную пороговую область, чтобы удалить серый шум, и выделяем различия с помощью ограничительной рамки Вот результат.

image image

Чтобы визуализировать точные различия, мы заполняем контуры маской и исходным изображением.

image image

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)
4 голосов
/ 17 мая 2019

Один из отличных способов быстрой идентификации различий между двумя изображениями заключается в использовании анимированного GIF, например:

enter image description here

Процесс описан, и коддоступно здесь .Это может быть довольно легко адаптировано к Python.Он использует ImageMagick , который установлен на большинстве дистрибутивов Linux и доступен для macOS и Windows.

Просто для справки, я использовал эту команду в терминале:

flicker_cmp -o result.gif -r x400 a.jpg b.jpg
3 голосов
/ 17 мая 2019

Если вы хотите использовать Imagemagick, то вы можете использовать его инструмент сравнения. Поскольку ваши изображения в формате JPG, они будут показывать различия из-за сжатия каждого из них. Поэтому я добавляю -fuzz 15%, чтобы допустить разницу в 15%, не показывая этого. Результат покажет красный (по умолчанию), где изображения отличаются. Но цвет можно изменить.

Linux поставляется с Imagemagick. Версии также доступны для Mac OSX и Windows.

Существует также Python Wand, который использует Imagemagick.

compare -metric rmse -fuzz 25% left.jpg right.jpg diff.png


enter image description here

Альтернативный метод - использовать более низкое значение размытия и использовать морфологическую обработку, чтобы удалить шум и немного заполнить.

Использует конвертирует и сначала копирует левое изображение и отбеливает его. Затем снова копирует левое изображение и заполняет его красным. Затем копирует левое изображение и выполняет разностную операцию с правым с использованием более низкого значения размытия, равного 10%. Это оставит больше шума на изображении, но даст лучшее представление об истинных регионах. Поэтому я использую морфологическое сглаживание, чтобы убрать шум. Наконец, я использую последнее изображение в качестве маски, чтобы сложить красный цвет по белому левому изображению.

convert left.jpg \
\( -clone 0 -fill white -colorize 50% \) \
\( -clone 0 -fill red -colorize 100 \) \
\( -clone 0 right.jpg -compose difference -composite -threshold 10% -morphology smooth diamond:1 \) \
-delete 0 \
-compose over -composite \
result.png


enter image description here

3 голосов
/ 17 мая 2019

Скажем на изображении1 точка image1 [x, y] = [10,10,200].В разных матрицах разные [x, y] = [0,0,255].После вычисления «+» новое значение будет [10,10,455], оно не будет работать, поскольку значение R превышает 255.

Я советую попробовать

image1[mask != 255] = [0, 0, 255]
image2[mask != 255] = [0, 0, 255]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...