如何让 python 向我显示 2 张图像之间的差异并用圆圈显示它们

How can I get python to show me the differance between 2 images and display them with Circles around

所以我启动了一个程序,它拍摄两张图像,一张是模型图像,另一张是经过更改的图像,我希望它能够检测到差异并通过圈出差异向我展示。我遇到了寻找差异坐标的问题,因为我的圆圈一直在图像中间结束。

这是我的代码:

import cv2 as cv
import numpy as np
from PIL import Image, ImageChops

#Ideal Image and The main Image
img2= cv.imread("ideal.jpg")
img1 = cv.imread("Actual.jpg")


#Verifys if there is or isnt a differance in the Image for the If statement
diff = cv.subtract(img2, img1)
results = not np.any(diff)

#Tells the User if there is a Differance within the 2 images with the model image and the image given
if results is True:
    print("The Images are the same!")

else:
    print("The images are differant")


#This is to make the image show the differance to circle
img_1=Image.open("Actual.jpg")
img_2=Image.open("ideal.jpg")
diff=ImageChops.difference(img_1,img_2)
diff.save("Differance.jpg")

#Reads the image Just saved
Differance = cv.imread("Differance.jpg", 0)

#Resize the Image to make it smaller

img1s = cv.resize(img1, (0, 0), fx=0.5, fy=0.5)
Differance = cv.resize(Differance, (0, 0), fx=0.5, fy=0.5)    

# Find anything not black, i.e. The differance
nz = cv.findNonZero(Differance)

# Find top, bottom, left and right edge of the Differance
a = nz[:,0,0].min()
b = nz[:,0,0].max()
c = nz[:,0,1].min()
d = nz[:,0,1].max()

# Average top and bottom edges, left and right edges, to give centre
c0 = (a+b)/2
c1 = (c+d)/2

#The Center Coords
c3 = (int(c0),int(c1))

#Values for the below code so it doesnt look messy
radius = 50
color = (0, 0, 255)
thickness = 2

#This Places a Circle around the center of the differance
Finished = cv.circle(img1s, c3, radius, color, thickness)

#Saves the Final Image with the circle around it
cv.imwrite("Final.jpg", Finished)

以及所附图片1 2

此代码当前拍摄两张图像并涂黑背景,只留下图像中的差异,然后该程序旨在获取差异的位置并在主图像的中心周围放置一个圆圈,即主图像与它的区别。

您的主要问题是 JPG 格式会更改像素以更好地压缩图像 - 这会在所有区域造成差异。如果您显示 diffdifference 那么您应该会看到许多灰色像素

我希望你能看到球下方的像素

如果您使用 PNG 作为原始图像(没有球),然后使用此图像创建带球的图像并保存在 PNG 中,则代码将正常工作。


我的版本没有 PIL

按任意键关闭 window 图片。

import cv2 as cv
import numpy as np

# load images
img1 = cv.imread("img1.png")
img2 = cv.imread("img2.png")

# calculate difference
diff = cv.subtract(img1, img2)  # other order `(img2, img1)` gives worse result

# saves difference
cv.imwrite("difference.png", diff)

# show difference - press any key to close
cv.imshow('diff', diff)
cv.waitKey(0)
cv.destroyWindow('diff')

if not np.any(diff):
    print("The images are the same!")
else:
    print("The images are differant")

# resize images to make them smaller
#img1_resized = cv.resize(img1, (0, 0), fx=0.5, fy=0.5)
#diff_resized = cv.resize(diff, (0, 0), fx=0.5, fy=0.5)    
img1_resized = img1
diff_resized = diff

# convert to grayscale (without saving and loading again)
diff_resized = cv.cvtColor(diff_resized, cv.COLOR_BGR2GRAY)

# find anything not black in differance
non_zero = cv.findNonZero(diff_resized)
#print(non_zero)

# find top, bottom, left and right edge of the differance
x_min = non_zero[:,0,0].min()
x_max = non_zero[:,0,0].max()
y_min = non_zero[:,0,1].min()
y_max = non_zero[:,0,1].max()
print('x:', x_min, x_max)
print('y:', y_min, y_max)

sizes = [x_max-x_min+1, y_max-y_min+1]
print('width :', sizes[0])
print('height:', sizes[1])

# center 
center_x = (x_min + x_max) // 2
center_y = (y_min + y_max) // 2
center = (center_x, center_y)
print('center:', center)

# radius 
radius = max(sizes) // 2
print('radius:', radius)

color = (0, 0, 255)
thickness = 2

# draw circle around the center of the differance
finished = cv.circle(img1_resized, center, radius, color, thickness)

# saves final image with circle
#cv.imwrite("final.png", finished)

# show final image - press any key to close
cv.imshow('finished', finished)
cv.waitKey(0)
cv.destroyWindow('finished')

img1.png

img2.png

difference.png

final.png


编辑:

如果你使用JPG那么你可以尝试减少噪音

diff = cv.subtract(img1, img2)

diff_gray = cv.cvtColor(diff, cv.COLOR_BGR2GRAY)

diff_gray[diff_gray < 50] = 0

对于不同的图像,您可能需要不同的值而不是 50

你也可以试试thresholding

(_, diff_gray) = cv.threshold(diff_gray, 50, 0, cv.THRESH_TOZERO)

它可能还需要其他功能,如 blur()erode()dilate()

不需要PIL

  1. 拍摄差异图像
  2. 阈值
  3. 使用 findcontour 查找区域
  4. 如果找到等高线就画出来
for cnt in contours:
    out_image = cv2.drawContours(out_image, [cnt], 0, (255,0,0), -1)
    (x,y),radius = cv2.minEnclosingCircle(cnt)
    center = (int(x),int(y))
    radius = int(radius)
    out_image = cv2.circle(out_image,center,radius,(0,255,0),2)