python + opencv - как правильно сравнивать изображения (через гистограммы)? - PullRequest
1 голос
/ 06 апреля 2019

У меня есть куча изображений (из коллекции MC Escher), которые я хочу организовать, поэтому первый шаг, который я имел в виду, - это сгруппировать их, сравнив их (вы знаете, у некоторых разные разрешения / формы и т. Д.) .

я написал очень жестокий сценарий для: * читать файлы * вычислить их гистограммы * сравните их

но качество сравнения действительно низкое, как будто есть файлы, которые абсолютно разные

взгляните на то, что я написал до сих пор:

Подготовка гистограмм

files_hist = {}

for i, f in enumerate(files):
    try:
        frame = cv2.imread(f)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        hist = cv2.calcHist([frame],[0],None,[4096],[0,4096])
        cv2.normalize(hist, hist, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)

        files_hist[f] = hist
    except Exception as e:
        print('ERROR:', f, e)

Сравнение гистограмм

pairs = list(itertools.combinations(files_hist.keys(), 2))

for i, (f1, f2) in enumerate(pairs):
    correl = cv2.compareHist(files_hist[f1], files_hist[f2], cv2.HISTCMP_CORREL)

    if correl >= 0.999:
        print('MATCH:', correl, f1, f2)

сейчас, например, я получаю совпадение для этих 2 файлов:

m._c._escher_244_ (1933) .jpg m._c._escher_244_(1933).jpg

и

* * M._c._escher_208_ тысячу двадцать-один (1931) .jpg m._c._escher_208_(1931).jpg

и их соотношение, используя приведенный выше код, составляет 0.9996699595530539 (поэтому они практически одинаковы :()

что я делаю не так? Как я могу улучшить этот код, чтобы избежать ложных совпадений?

спасибо!

1 Ответ

2 голосов
/ 06 апреля 2019

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

Существуют лучшие способы количественно оценить разницу между изображениями, в этом посте упоминает хороший вариант:

  • Загрузить оба изображения в виде массивов (scipy.misc.imread) и вычислить поэлементную (попиксельная) разницу. Рассчитайте норму разности.

редактирование:

Отвечая на некоторые вопросы:

Я принимаю, что нулевая норма на пиксель будет равна значению 0,0-1,0, а значения, близкие к 0,0, означают «изображения одинаковы», верно?

Значения, близкие к 0,0, означают, что пиксели совпадают. Чтобы сравнить изображения в целом, нужно сложить все пиксели. Если итоговое значение близко к 0.0, это означает, что изображения почти одинаковы.

что если 2 размера изображения отличаются?

это хорошо. Для расчета разницы в нормах изображения должны иметь одинаковый размер. Я вижу два способа добиться этого:

  • первым будет изменение размера одного изображения до формы другого, проблема в том, что это может вызвать искажение изображения.

  • вторая будет заполнять меньшие изображения нулями, пока размеры не совпадут.

obs: при суммировании по пиксельной норме у вас будет значение от нуля до количества пикселей в изображении. Это может сбивать с толку, если вы сравниваете несколько изображений. Например, предположим, что вы сравниваете изображения A и B, и оба имеют форму 50x50 (следовательно, изображения имеют 2500 пикселей); значения, близкие к 2500, означают, что изображения совершенно разные. Теперь предположим, что вы сравниваете изображения C и D, и оба имеют форму 1000x1000, в этом случае такие значения, как 2500, означают, что изображения похожи. Чтобы преодолеть эту проблему, вы можете разделить попиксельную сумму на количество пикселей в изображении, это приведет к значению от 0,0 до 1,0, 0,0 означает, что изображения одинаковы, а 1,0 означает, что они совершенно разные.

да вот ошибка, которую я получил при сравнении 2 изображений с разным размером diff = image1 - image2 ValueError: operands could not be broadcast together with shapes (850,534) (663,650)

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

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