gpt4 book ai didi

python - 使用 OpenCV Python 检测和可视化两个图像之间的差异

转载 作者:太空狗 更新时间:2023-10-29 22:06:15 27 4
gpt4 key购买 nike

我有两张图片,我想让它们明显不同。我想为两个图像添加颜色,以便用户可以在一两秒内清楚地发现所有差异。

例如,这里有两张有一些不同的图片:

<表类="s-表"><头> leftImage.jpg: rightImage.jpg:<正文> image_1 image_2

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

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)
<表类="s-表"><头> diff.png: diffOverImage1.png diffOverImage2.png<正文> img_3 img_4 img_5

当前代码的问题:计算出的掩码显示了一些差异,但并非全部(例如,请参见右上角的小块,或蓝色数据包上的绳索)。这些差异在计算出的蒙版中只显示得非常少,但它们应该像其他差异一样清晰地显示为红色。

输入:2 张有一些差异的图像。

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

最佳答案

方法 #1:结构相似性指数 (SSIM)

为了可视化两幅图像之间的差异,我们可以采用定量方法,使用在 Image Quality Assessment: From Error Visibility to Structural Similarity 中引入的结构相似性指数 (SSIM) 来确定图像之间的确切差异。 .此方法已在 scikit-image 中实现图像处理库。您可以使用 pip install scikit-image 安装 scikit-image

使用 skimage.metrics.structural_similarity来自 scikit-image 的函数,它返回一个 score 和一个差异图像,diffscore 表示两个输入图像之间的结构相似性指数,可以落在范围 [-1,1] 之间,值越接近 1 表示相似性越高。但是由于您只对两个图像的不同之处感兴趣,因此我们将重点关注 diff 图像。具体来说,diff 图像包含实际图像差异,较暗区域的差异更大。较大的差异区域以黑色突出显示,而较小的差异区域以灰色突出显示。

所有差异->显着区域差异

灰色嘈杂区域可能是由于 .jpg 有损压缩造成的。如果我们使用无损压缩图像格式,我们将获得更清晰的结果。比较两幅图像后的 SSIM 分数表明它们非常相似。

Image Similarity: 91.9887%

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

为了可视化确切的差异,我们将轮廓填充到蒙版和原始图像上。

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

# Load images
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 the two images
(score, diff) = structural_similarity(before_gray, after_gray, full=True)
print("Image Similarity: {:.4f}%".format(score * 100))

# 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")
diff_box = cv2.merge([diff, diff, diff])

# 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, 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.rectangle(diff_box, (x, y), (x + w, y + h), (36,255,12), 2)
cv2.drawContours(mask, [c], 0, (255,255,255), -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('diff_box', diff_box)
cv2.imshow('mask', mask)
cv2.imshow('filled after', filled_after)
cv2.waitKey()

局限性:虽然此方法效果很好,但也有一些重要的局限性。两个输入图像必须具有相同的大小/尺寸,并且还存在一些问题,包括缩放、平移、旋转和扭曲。 SSIM 在模糊或嘈杂的图像上也表现不佳。对于不具有相同尺寸的图像,我们必须使用深度学习特征模型从识别像素相似性切换到识别对象相似性,而不是比较单个像素值。参见 checking images for similarity with OpenCV using Dense Vector Representations用于尺度不变和变换无关图像。

注意使用的scikit-image版本是0.18.1


方法 #2:cv2.absdiff

为了完整性,OpenCV 提供了一个非常简单的内置方法,使用 cv2.absdiff但结果不如 SSIM,也没有计算两幅图像之间的相似度得分。此方法仅生成差异图像。

结果非常洗涤,仍然受到同样的限制。这种方法虽然简单很多,但还是推荐使用SSIM。

import cv2

# Load images as grayscale
image1 = cv2.imread("left.jpg", 0)
image2 = cv2.imread("right.jpg", 0)

# Calculate the per-element absolute difference between
# two arrays or between an array and a scalar
diff = 255 - cv2.absdiff(image1, image2)

cv2.imshow('diff', diff)
cv2.waitKey()

关于python - 使用 OpenCV Python 检测和可视化两个图像之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56183201/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com