Дифференцирование изображения: игнорирование поступательного движения - PullRequest
0 голосов
/ 24 марта 2020

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

У меня есть изображение "Евангелия", которое само по себе является "золотым стандартом": Евангелие image

Тогда у меня есть несколько разных снятых изображений для сравнения. Вот пример: пример изображения

Вот пример разницы, показывающей мою проблему: разность изображений

Как видите, они довольно маленькие , Теперь я различаю изображения, сначала изменив размер изображения до 32x32, вручную уменьшив контрастность на 100, а затем применив размытие с помощью OpenCV.

После этого я использую функцию Skimage 'Structure_integrity', чтобы вычитать и количественно определить различия между изображениями. Остальное только для просмотра.

import cv2
import numpy as np
from PIL import Image
from skimage.metrics import structural_similarity

def change_contrast(img, level):
    img = Image.fromarray(img)
    factor = (259 * (level + 255)) / (255 * (259 - level))
    def contrast(c):
        return 128 + factor * (c - 128)
    return np.asarray(img.point(contrast))

# Open and preprocess the images
image_orig = cv2.imread(IMAGE_PATH)
image = cv2.resize(image, (32, 32))
image = change_contrast(image_orig, -100)
image = cv2.blur(image, (5, 5))
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

gospel_orig = cv2.imread(GOSPEL_PATH)
gospel = cv2.resize(gospel_orig, (32, 32))
gospel = change_contrast(gospel, -100)
gospel = cv2.blur(gospel, (5, 5))
gospel = cv2.cvtColor(gospel, cv2.COLOR_BGR2GRAY)

# Get image similarities and an output difference image
(score, diff) = structural_similarity(image, gospel, full=True)
print("Image similarity", score)

diff = (diff * 255).astype("uint8")

# Viewing stuff below
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

filled_gospel = cv2.cvtColor(gospel, cv2.COLOR_GRAY2BGR)

for c in contours:
    area = cv2.contourArea(c)
    if area > 40:
        x,y,w,h = cv2.boundingRect(c)
        cv2.drawContours(filled_gospel, [c], 0, (0,255,0), -1)

cv2.imshow('image', image)
cv2.imshow('gospel', gospel)
cv2.imshow('diff',diff)
cv2.imshow('filled gospel',filled_gospel)
cv2.waitKey(0)

Когда я делаю описанные выше шаги, вы можете увидеть некоторые переводческие различия между «Евангелием» и снятым изображением. Как лучше всего бороться с этим, так как я хочу получить различия только в черном цвете буквы, а не в том, насколько хорошо он выровнен?

1 Ответ

0 голосов
/ 24 марта 2020

Вот как я бы делал сопоставление и различие шаблонов в Python / OpenCV.

  • Прочитайте справочные и примеры изображений
  • Дополните примерное изображение двойным размером с его серым цветом фона.
  • Выполните сопоставление шаблона со ссылкой, чтобы найти лучшее место для матча и счет матча.
  • Обрезать примерное изображение с подкладкой в ​​верхнем левом углу в месте совпадения, но размер эталонного изображения
  • Получить абсолютное разностное изображение
  • Сохранить результаты

Ссылка:

enter image description here

Пример:

enter image description here

import cv2
import numpy as np

# read reference and convert to gray
ref = cv2.imread('reference.png')
ref_gray = cv2.cvtColor(ref, cv2.COLOR_BGR2GRAY)
hr, wr = ref_gray.shape

# read example and convert to gray
ex = cv2.imread('example.png')
ex_gray = cv2.cvtColor(ex, cv2.COLOR_BGR2GRAY)
he, we = ex_gray.shape

# pad the example to double its dimensions with gray=190
color=190
wp = we // 2
hp = he // 2
ex_gray = cv2.copyMakeBorder(ex_gray, hp,hp,wp,wp, cv2.BORDER_CONSTANT, value=color)

# do template matching
corrimg = cv2.matchTemplate(ref_gray,ex_gray,cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(corrimg)
max_val_corr = '{:.3f}'.format(max_val)
print("correlation: " + max_val_corr)
xx = max_loc[0]
yy = max_loc[1]
print('x_match_loc =',xx,'y_match_loc =',yy)

# crop the padded example image at top left corner of xx,yy and size hr x wr
ex_gray_crop = ex_gray[yy:yy+hr, xx:xx+wr]

# get absolute difference image
ref_grayf = ref_gray.astype(np.float32)
ex_gray_cropf = ex_gray_crop.astype(np.float32)
diff = 255 - np.abs(cv2.add(ref_gray, -ex_gray_crop))

# compute mean of diff
mean = cv2.mean(diff)[0]
print("mean of diff in range 0 to 100 =",mean)

cv2.imshow('ref_gray', ref_gray)
cv2.imshow('ex_gray', ex_gray)
cv2.imshow('ex_gray_crop', ex_gray_crop)
cv2.imshow('correlation image', corrimg)
cv2.imshow('diff', diff)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('reference_gray.jpg', ref_gray)
cv2.imwrite('example_gray_padded.jpg', ex_gray)
cv2.imwrite('reference_example_correlation.jpg', (255*corrimg).clip(0,255).astype(np.uint8))
cv2.imwrite('example_gray_padded_cropped.jpg', ex_gray_crop)
cv2.imwrite('reference_example_diff.jpg', diff)


Пример дополнения:

enter image description here

Изображение корреляции с указанием мест наилучшего соответствия:

enter image description here

Результаты матчей:

correlation: 0.969
x_match_loc = 10 y_match_loc = 9

mean of diff in range 0 to 100 = 1.3956887102667155


Пример обрезан для выравнивания со ссылкой:

enter image description here

Дифференциальное изображение (там, где они различаются):

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...