比较两个图像并找出所有不同的像素坐标

Compare two images and find all pixel coordinates that differ

我设计了一个程序来比较两个图像并为您提供两个图像中不同像素的坐标并绘制使用 pygame。我不介意必须使用另一个库或重新制作我的整个代码,但理想情况下它应该花费少于 0.6 秒的时间来处理并且它不应该减少文件大小,我需要它做的就是 return 坐标相对到图片

我的代码:

import cv2
import pygame
from pygame.locals import *
import time

lib = 'Map1.png'
lib2 = 'Map2.png'
lib3 = ()
coordenatesx = ()
coordenatesy = ()

Read = list(cv2.imread(lib).astype("int"))
Read2 = list(cv2.imread(lib2).astype("int"))

counter = 0

pygame.init()

flags = DOUBLEBUF
screen = pygame.display.set_mode((500,500), flags, 4)

start = time.process_time()#To tell me how long it takes
for y in range(len(Read)):#y coords
    for x in range(len(Read[y])):#x coords
        all = list(Read[y][x])[0]
        all2 = list(Read2[y][x])[0]
        difference = (all)-(all2)
        if difference > 10 or difference < -10: #To see if the pixel's difference is in the boundary if not it is different and it gets plotted
            counter+=1
            pygame.draw.rect(screen, (255, 0, 0), pygame.Rect(x, y, 1, 1))

pygame.display.update()
print(time. process_time() - start)

if counter >= (y * x) * 0.75:
    print('They are similar images')
    print('They are different by only :', str((counter / (y * x)) * 100), '%')
else:
    print('They are different')
    print('They are different by:', str((counter / (y * x)) * 100), '%')

pygame.display.update()
image1 image2

您不需要使用 for 循环来做同样的事情。

Numpy 让事情变得简单:

  • 很容易理解
  • 加快操作速度

正在读取您的两张灰度图像:

img1 = cv2.imread(r'C:\Users4316\Desktop\Stack\m1.png', 0)
1mg2 = cv2.imread(r'C:\Users4316\Desktop\Stack\m2.png', 0)

减去它们。 cv2.subtract() 负责规范化,因此它不会 return 负值。没有变化的坐标保持黑色(像素强度= 0)

sub = cv2.subtract(img1, img2)

使用numpy查找变化大于0的坐标

coords = np.argwhere(sub > 0)

# return first 10 elements of the array coords
coords[:10]

array([[ 0, 23],
       [ 0, 24],
       [ 0, 25],
       [ 0, 26],
       [ 0, 27],
       [ 0, 28],
       [ 0, 29],
       [ 0, 30],
       [ 0, 31],
       [ 0, 32]], dtype=int64)

coords returns一个数组,可以转换为列表:

coords_list = coords.tolist()
# return first 10 elements of the list:
>>> coords_list[:10]
[[0, 23], [0, 24], [0, 25], [0, 26], [0, 27], [0, 28], [0, 29], [0, 30], [0, 31], [0, 32]]

更新:

根据 fmw42 的评论,如果您只是在寻找像素强度之间的差异小于或大于某个值(比如 10)的坐标;您可以执行以下操作:

sub = cv2.absDiff(img1, img2)
np.argwhere(sub > 10)

如果您碰巧还想要两个图像之间的定量相似性得分,这里有一个方法使用 scikit-image 中的 skimage.metrics.structural_similarity 函数,其中 returns a scorediff 图片。由于您主要对所有不同的像素坐标感兴趣,因此 diff 图像包含实际图像差异,我们可以在其中搜索所有 (x y) 像素坐标。

Image Similarity: 34.3664%

Numpy 形式的坐标(可以转换为列表)

[[  0  20]
 [  0  21]
 [  0  22]
 ...
 [572 521]
 [572 522]
 [572 523]]

代码

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

# Load images as grayscale
image1 = cv2.imread('1.png', 0)
image2 = cv2.imread('2.png', 0)

# Compute SSIM between the two images
# diff contains the actual image differences between the two images
(score, diff) = structural_similarity(image1, image2, full=True)
diff = 255 - (diff * 255).astype("uint8")
print("Image Similarity: {:.4f}%".format(score * 100))

# Search for all pixels that are different 
# Type is <class 'numpy.ndarray'>, you can optionally convert to a list
coords = np.argwhere(diff > 0)
# coords = coords.tolist() 
print(coords)

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