Python OpenCV не дает такой же вывод на том же изображении - PullRequest
2 голосов
/ 31 марта 2020

Я пытаюсь создать программу, которая проверяет, совпадают ли 2 изображения. У меня есть следующий код, который выполняется с обоими изображениями:

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)

При первом запуске я получаю следующий вывод: Первое изображение . Через некоторое время ~ 7 секунд я делаю это с точно тем же изображением и получаю следующий вывод: Второе изображение . Я попробовал это снова, и я снова получил другой вывод: Третья попытка?

Я пытаюсь проверить, является ли изображение таким же (как в содержании), но я могу Получите это работает. Я использую следующий фрагмент кода, найденный в Stackoverflow, для проверки сходства:

def is_similar(image1, image2):
    return image1.shape == image2.shape and not(np.bitwise_xor(image1,image2).any())

И это возвращает false, когда проверяется первое со вторым изображением. Как я могу заставить это работать?

Спасибо за ваше время,

==== РЕДАКТИРОВАТЬ ====

Вот canvas.png

==== РЕДАКТИРОВАТЬ 2 ====

Посмотрев на ответ @Rotem, я опробовал его, но он все еще показывает незначительное разница, которую функция выше возвращает False на: Picture 1 и Picutre 2

Ответы [ 2 ]

2 голосов
/ 31 марта 2020

cv2.grabCut не дает детерминированных c результатов, поскольку алгоритм GrabCut использует встроенную случайность .

Согласно Википедии :

Используется для построения поля Маркова random над метками пикселей ...

Вы можете избежать случайности, сбрасывая начальное число генератора случайных чисел OpenCV перед выполнением cv2.grabCut:

cv2.setRNGSeed(0)

Вот пример кода:

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)

Обновление:

Вы можете использовать следующие l oop для сравнения изображений:

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

В моей машине они все одинаковые.


Полный код:

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!')
1 голос
/ 31 марта 2020

В cv2.grabCut() есть элемент случайности. Модели гауссовой смеси используются для определения переднего плана и фона после первоначальной маркировки. Больше информации здесь или в цитируемой статье для grabcut.

Именно из-за этой случайности вы видите разные результаты. Вы должны рассмотреть использование некоторых методов снижения шума, таких как морфологические операции (cv2.erode() и cv2.dilate()), чтобы справиться с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...