首页 > 解决方案 > 如何让 python 向我展示 2 个图像之间的差异并用 Circles 显示它们

问题描述

所以我开始了一个程序,它拍摄两张图像,一张是模型图像,另一张是有变化的图像,我希望它检测差异并通过圈出差异向我展示。当我的圆圈一直在图像中间结束时,我遇到了一个寻找差异坐标的问题。

这是我的代码:

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

此代码当前同时获取图像并将背景涂黑,仅在图像中留下差异,然后程序旨在获取差异的位置并在主图像的中心周围放置一个圆圈,即有差异的那个.

标签: pythonopencv

解决方案


您的主要问题是JPG更改像素以更好地压缩图像的格式 - 这会在所有区域中产生差异。如果您显示diff或者difference然后您应该看到许多灰色像素

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

在此处输入图像描述

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


我的版本没有PIL.

按任意键关闭带有图像的窗口。

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.

您也可以尝试阈值

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

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


推荐阅读