I'm trying to create a program that checks if 2 images are the same. I have the following code which gets executed with both the images:
img = cv2.imread('canvas.png')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (70,70,300,250)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
img = img[84:191, 84:203]
count = 1
cv2.imwrite("tmp/"+str(count)+".png", img)
First time I run this, I get the following output: First image. After some time ~7 seconds, I do it with exactly the same image, and I get the following output: Second image. I tried it again, and I again got a different output: Third try?
I'm trying to check if the image is the same (as in the contents), but I can't get this working. I'm using the following piece of code found on Stackoverflow to check similarities:
def is_similar(image1, image2):
return image1.shape == image2.shape and not(np.bitwise_xor(image1,image2).any())
And that returns false when check the first with the second image. How can I make this work out?
Thanks for your time,
==== EDIT ====
Here is canvas.png
==== EDIT 2 ====
After looking at @Rotem their answer, I've tried it out, but it still shows a slight difference, which the function above return False
on:
and
cv2.grabCut
doesn't give deterministic results because the GrabCut algorithm uses built in randomness.
According to Wikipedia:
This is used to construct a Markov random field over the pixel labels...
You may avoid randomness by resetting the seed of the random generator of OpenCV before executing cv2.grabCut
:
cv2.setRNGSeed(0)
Here is a code sample:
for count in range(10):
cv2.setRNGSeed(0)
img = cv2.imread('canvas.png')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (70,70,300,250)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
img = img[84:191, 84:203]
cv2.imwrite(str(count)+".png", img)
Update:
You may use the following loop to compare the images:
# Verify that all images are the same
for count in range(10):
im = cv2.imread(str(count)+".png")
is_same = is_similar(im, img)
if not is_same:
print('Images are not the same, and it is strange!')
In my machine they are all the same.
Complete code:
import cv2
import numpy as np
# Disable OpenCL and disable multi-threading.
cv2.ocl.setUseOpenCL(False)
cv2.setNumThreads(1)
def is_similar(image1, image2):
return image1.shape == image2.shape and not(np.bitwise_xor(image1,image2).any())
for count in range(10):
cv2.setRNGSeed(0)
img = cv2.imread('canvas.png')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (70,70,300,250)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
img = img[84:191, 84:203]
cv2.imwrite(str(count)+".png", img)
# Verify that all images are the same
for count in range(10):
im = cv2.imread(str(count)+".png")
is_same = is_similar(im, img)
if not is_same:
print('Images are not the same, and it is strange!')