本文介绍了使用OpenCV Python检测并可视化两个图像之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两张图片,我想让它们之间的区别显而易见.我想为两个图像添加颜色,以便用户可以在一两秒钟内清楚地发现所有差异.

I have two images and would like to make it obvious where the differences are. I want to add color to the two images such that a user can clearly spot all the differences within a second or two.

例如,这是两张图片,但有一些区别:

For example, here are two images with a few differences:

leftImage.jpg:

rightImage.jpg:

我当前使差异明显的方法是创建一个蒙版(两个图像之间的差异),将其着色为红色,然后将其添加到图像中.目的是用强烈的红色清楚地标记所有差异.这是我当前的代码:

My current approach to make the differences obvious, is to create a mask (difference between the two images), color it red, and then add it to the images. The goal is to clearly mark all differences with a strong red color. Here is my current code:

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:

diffOverImage1.png

diffOverImage2.png

当前代码有问题:计算出的蒙版显示了一些差异,但不是全部(例如,请参见右上角的细小片段,或蓝色包装袋上的绳子).这些差异在计算出的蒙版中仅显示得很浅,但与其他差异一样,它们应该清楚地显示为红色.

Problem with the current code:The computed mask shows some differences but not all of them (see for example the tiny piece in the upper right corner, or the rope thingy on the blue packet). These differences are shown only very lightly in the computed mask, but they should be clearly red like the other differences.

输入:2张图片,有些差异.

Input: 2 images with some differences.

预期输出: 3张图像:两张输入图像,但差异突出显示(以可配置的颜色清楚突出显示),第三张图像仅包含差异(遮罩).

Expected Output: 3 images: the two input images but with the differences highlighted (clearly highlighted in a configurable color), and a third image containing only the differences (the mask).

推荐答案

要显示两个图像之间的差异,我们可以采用定量方法,使用图像质量评估:从错误可见性到结构相似性. scikit-image 用于图像处理的库.您可以将scikit-imagepip install scikit-image一起安装.

To visualize differences between two images, we can take a quantitative approach to determine the exact discrepancies between images using the Structural Similarity Index (SSIM) which was introduced in Image Quality Assessment: From Error Visibility to Structural Similarity. This method is already implemented in the scikit-image library for image processing. You can install scikit-image with pip install scikit-image.

使用scikit-image中的compare_ssim()函数,它将返回score和差异图像diff. score代表两个输入图像之间的结构相似性指标,并且可以落在[-1,1]范围内,其值更接近一个代表更高相似性的值.但是,由于您只对两个图像的不同之处感兴趣,因此我们将重点关注diff图像.具体地,diff图像包含实际图像差异,其中较暗的区域具有更大的视差.较大的差异区域以黑色突出显示,而较小的差异则以灰色突出显示.

Using the compare_ssim() function from scikit-image, it returns a score and a difference image, diff. The score represents the structural similarity index between the two input images and can fall between the range [-1,1] with values closer to one representing higher similarity. But since you're only interested in where the two images differ, the diff image is what we'll focus on. Specifically, the diff image contains the actual image differences with darker regions having more disparity. Larger areas of disparity are highlighted in black while smaller differences are in gray.

灰色嘈杂区域可能是由于.jpg有损压缩所致.如果使用无损压缩图像格式,我们将获得更清晰的结果.比较两张图片后的SSIM得分显示它们非常相似.

The gray noisy areas are probably due to .jpg lossy compression. We would obtain a cleaner result if we used a lossless compression image format. The SSIM score after comparing the two images show that they are very similar.

现在,由于我们只想查找图像之间的较大差异,因此我们对diff图像进行了过滤.我们遍历每个轮廓,使用最小阈值区域进行过滤以消除灰色噪声,并使用边框突出显示差异.这是结果.

Now we filter through the diff image since we only want to find the large differences between the images. We iterate through each contour, filter using a minimum threshold area to remove the gray noise, and highlight the differences with a bounding box. Here's the result.

要显示出确切的差异,我们将轮廓填充到蒙版和原始图像上.

To visualize the exact differences, we fill the contours onto a mask and on the original 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)

这篇关于使用OpenCV Python检测并可视化两个图像之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 15:45