我有两张图片,我想让它们变得明显。我想为两个图像添加颜色,以便用户可以在一两秒钟内清楚地发现所有差异。
例如,这是两张图片,有些不同:
leftImage.jpg:
rightImage.jpg:
我当前使差异显而易见的方法是创建一个蒙版(两个图像之间的差异),将其着色为红色,然后将其添加到图像中。目的是用强烈的红色清楚地标记所有差异。这是我当前的代码:
[disabled]=
diff.png:
diffOverImage1.png
diffOverImage2.png
当前代码存在问题: 计算出的蒙版显示了一些差异,但不是全部(例如,请参见右上角的细小片段,或蓝色包装袋上的绳子)。这些差异在计算出的蒙版中仅显示得很浅,但与其他差异一样,它们应清楚地显示为红色。
输入:2张图片,有些不同。
输出: 3张图像:两张输入图像,但差异突出显示(以可配置的颜色清晰突出显示),第三张图像仅包含差异(遮罩)。
答案 0 :(得分:7)
要显示两个图像之间的差异,我们可以采用定量方法,使用Image Quality Assessment: From Error Visibility to Structural Similarity中引入的结构相似性指数(SSIM)来确定图像之间的确切差异。该方法已经在scikit-image库中实现了图像处理。您可以将scikit-image
与pip install scikit-image
一起安装。
使用scikit-image中的compare_ssim()
函数,它返回一个score
和一个差异图像diff
。 score
代表两个输入图像之间的结构相似性指标,并且可以落在[-1,1]范围内,其值更接近一个代表更高相似性的值。但是,由于您只对两个图像的不同之处感兴趣,因此我们将重点关注diff
图像。具体地,diff
图像包含实际图像差异,其中较暗的区域具有更大的视差。较大的差异区域以黑色突出显示,而较小的差异以灰色突出显示。
灰色嘈杂区域可能是由于.jpg有损压缩所致。如果使用无损压缩图像格式,我们将获得更清晰的结果。比较两张图片后的SSIM得分显示它们非常相似。
图像相似度0.9198863419190031
现在,我们只过滤diff
图像,因为我们只想查找图像之间的较大差异。我们遍历每个轮廓,使用最小阈值区域进行过滤以消除灰色噪声,并使用边框突出显示差异。这是结果。
要显示出确切的差异,我们将轮廓填充到蒙版和原始图像上。
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)
答案 1 :(得分:4)
一种快速识别两个图像之间差异的好方法是使用动画GIF,如下所示:
描述了该过程,并且可用的代码here。它很容易适应Python。照原样,它使用 ImageMagick ,它已安装在大多数Linux发行版中,并且可用于macOS和Windows。
仅供参考,我在终端机中使用了此命令:
flicker_cmp -o result.gif -r x400 a.jpg b.jpg
答案 2 :(得分:3)
如果您愿意使用Imagemagick,则可以使用其比较工具。由于您的图片是JPG,由于每个图片的压缩,它们会显示差异。因此,我添加了-fuzz 15%,以允许差异的15%容差而没有显示出来。结果将在图像不同的地方显示红色(默认情况下)。但是颜色可以更改。
Linux随附Imagemagick。 Mac OSX和Windows也可以使用这些版本。
还有使用Imagemagick的Python魔杖。
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
答案 3 :(得分:2)
让我们在image1中说点image1 [x,y] = [10,10,200]。在不同的矩阵中,differential [x,y] = [0,0,255]。经过“ +”运算后,新值为[10,10,455],由于R值超过255,因此无法使用。
我建议您可以尝试
image1[mask != 255] = [0, 0, 255]
image2[mask != 255] = [0, 0, 255]