首页 > 解决方案 > 图像差异:忽略平移运动

问题描述

我正在寻找一些关于什么是解决我的问题的最佳方法的见解。我正在比较两个单独的图像的差异,但我遇到了小平移运动的问题。

我有一个“福音”形象,它本身就是“黄金标准”: 福音形象

然后我有多个不同的拍摄图像进行比较。这是一个示例:示例图像

这是显示我的问题的示例差异图像:差异图像

如您所见,它们非常小。我现在区分图像的方法是首先将图像大小调整为 32x32,手动将对比度降低 100,然后使用 OpenCV 应用模糊。

之后,我使用 skimage 的“structural_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)

当我执行上述步骤时,您可以看到“福音”和拍摄的图像之间的一些翻译差异。解决这个问题的最佳方法是什么,因为我只想得到字母黑色的差异,而不是它的对齐程度?

标签: pythonimageopencv

解决方案


这是我在 Python/OpenCV 中进行模板匹配和差异化的方法。

  • 阅读参考和示例图像
  • 使用背景灰色将示例图像填充到其尺寸的两倍。
  • 与参考进行模板匹配以找到最佳匹配位置和匹配分数。
  • 裁剪填充的示例图像,使其左上角位于匹配位置,但参考图像的大小
  • 获取绝对差图像
  • 保存结果

参考:

在此处输入图像描述

例子:

在此处输入图像描述

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)


填充示例:

在此处输入图像描述

显示最佳匹配位置的相关图像:

在此处输入图像描述

比赛结果:

correlation: 0.969
x_match_loc = 10 y_match_loc = 9

mean of diff in range 0 to 100 = 1.3956887102667155


裁剪以与参考对齐的示例:

在此处输入图像描述

差异图像(白色是它们不同的地方):

在此处输入图像描述


推荐阅读