Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用OpenCV Python检测并可视化两个图像之间的差异_Python_Image_Opencv_Image Processing_Computer Vision - Fatal编程技术网

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

使用OpenCV Python检测并可视化两个图像之间的差异,python,image,opencv,image-processing,computer-vision,Python,Image,Opencv,Image Processing,Computer Vision,我有两张图片,我想让大家看清楚区别在哪里。我想为这两幅图像添加颜色,这样用户就可以在一两秒钟内清楚地发现所有的差异 例如,以下是两张有一些区别的图像: leftImage.jpg: rightImage.jpg: 我目前的做法是创建一个遮罩(两幅图像之间的差异),将其涂成红色,然后将其添加到图像中。目标是用强烈的红色清楚地标记所有差异。这是我目前的代码: import cv2 # load images image1 = cv2.imread("leftImage.jpg") image2

我有两张图片,我想让大家看清楚区别在哪里。我想为这两幅图像添加颜色,这样用户就可以在一两秒钟内清楚地发现所有的差异

例如,以下是两张有一些区别的图像:

leftImage.jpg:

rightImage.jpg:

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

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

当前代码有问题: 计算出的掩码显示了一些差异,但不是全部(例如,请参见右上角的小片,或蓝色数据包上的绳子)。这些差异仅在计算遮罩中显示得非常轻微,但它们应该像其他差异一样清晰地显示为红色

输入:2张图像,有些不同


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

快速识别两个图像之间差异的一个好方法是使用如下动画GIF:

描述了该过程,代码可用。它可以很容易地适应Python。实际上,它使用的是安装在大多数Linux发行版上的、适用于macOS和Windows的ImageMagick

仅供参考,我在终端中使用了以下命令:

flicker_cmp -o result.gif -r x400 a.jpg b.jpg

假设在图像1中,点图像1[x,y]=[10,10200]。在不同的矩阵中,不同的[x,y]=[0,0255]。在“+”计算之后,新值为[10,10455],这将不起作用,因为R值超过255

我建议你试试

image1[mask != 255] = [0, 0, 255]
image2[mask != 255] = [0, 0, 255]

如果您愿意使用Imagemagick,则可以使用其比较工具。由于您的图像是JPG,因此由于每个图像的压缩,它们将显示差异。因此,我添加了-fuzz 15%以允许15%的公差,而不显示差异。结果将显示红色(默认情况下),其中图像不同。但是颜色是可以改变的

Linux附带Imagemagick。Mac OSX和Windows也有相应的版本

还有Python Wand,它使用Imagemagick

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

另一种方法是使用较低的模糊值,并使用形态学处理来去除噪声,并填充一点

使用convert并首先复制左侧图像并将其变白。然后再次复制左侧图像并用红色填充。然后复制左侧图像,并使用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

为了直观地显示两幅图像之间的差异,我们可以采用一种定量方法,使用中引入的结构相似性指数(SSIM)来确定图像之间的精确差异。此方法已在图像处理库中实现。您可以使用
pip install scikit image
安装
scikit image

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

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

图像相似性0.9198863419190031

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

为了使精确的差异可视化,我们将轮廓填充到遮罩和原始图像上

from skimage.metrics import structural_similarity
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) = structural_similarity(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)

注意:使用的scikit图像版本是
0.18.1
。在以前的版本中,该函数是
skimage.measure.compare_ssim
,但在
0.18.1
中已被折旧和删除。根据,该功能仍然存在,但现在位于不同名称下的新
skimage.metrics
子模块下。新更新的函数是

,除非使用无损格式,否则每个图像都会与压缩有很多非常微小的差异(导致噪声)。我对此不太了解,所以这只是一个猜测,但也许一些频率滤波器可以帮助平滑这些位。使用absdiff而不是减法,您将获得所有差异,但噪声可能是一个问题。有关使用的一般概念,请参见absdiff@coffeewin:现有答案缺少什么?你在寻找什么?@CrisLuengo我在寻找一种方法,可以识别两幅图像之间的差异,其中图像处于不同角度或稍微旋转,并且除了精确的差异外,还可以输出百分比差异。我已经研究了使用SIFT和ORB-bu进行特征匹配