Python OpenCV doesn't give same output at the same image

Aaron :

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: Picture 1 and Picutre 2

Rotem :

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!')

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=386913&siteId=1