Сравнивая две гистограммы - PullRequest
47 голосов
/ 28 июня 2011

Для небольшого проекта мне нужно сравнить одно изображение с другим - чтобы определить, являются ли изображения приблизительно одинаковыми или нет.Изображения небольшие, от 25 до 100 пикселей в поперечнике.Изображения должны иметь одни и те же данные изображения, но они отличаются друг от друга, поэтому простая проверка на равенство пикселей не сработает.Рассмотрим эти два возможных сценария:

  1. Камера видеонаблюдения (CCTV) в музее, смотрящая на экспонат: мы хотим быстро увидеть, показывают ли две разные видеокадры одну и ту же сцену, но небольшие различия в освещении ифокусировка камеры означает, что они не будут идентичны.
  2. Изображение значка графического интерфейса векторного компьютера, отображаемого с разрешением 64x64, по сравнению с тем же значком с разрешением 48x48 (но оба изображения будут уменьшены до 32x32, поэтому гистограммы имеютто же общее количество пикселей).

Я решил представить каждое изображение, используя гистограммы, используя три гистограммы 1D: по одной для каждого канала RGB - для меня безопасно просто использовать цвет и игнорировать текстуру играничные гистограммы (альтернативный подход использует одну трехмерную гистограмму для каждого изображения, но я избегаю этого, поскольку это добавляет дополнительную сложность).Поэтому мне нужно будет сравнить гистограммы, чтобы увидеть, насколько они похожи, и если мера сходства переходит некоторое пороговое значение, то я могу с уверенностью сказать, что соответствующие изображения визуально одинаковы - я бы сравнил гистограммы соответствующих каналов каждого изображения (например, изображениеКрасная гистограмма 1 с красной гистограммой изображения 2, затем синяя гистограмма изображения 1 с синей гистограммой изображения 2, затем зеленые гистограммы - так что я не сравниваю красную гистограмму изображения 1 с синей гистограммой изображения 2, которая была бы просто глупой).

Допустим, у меня есть эти три гистограммы, которые представляют сводку красного канала RGB для трех изображений (для простоты используется 5 бинов для 7-пиксельных изображений):

H1            H2            H3 

  X           X                     X
  X   X       X       X             X
X X   X X     X X   X X     X X X X X
0 1 2 3 4     0 1 2 3 4     0 1 2 3 4

H1 = [ 1, 3, 0, 2, 1 ]
H2 = [ 3, 1, 0, 1, 2 ]
H3 = [ 1, 1, 1, 1, 3 ] 

Изображение 1 (H1) - мое эталонное изображение, и я хочу посмотреть, похоже ли изображение 2 (H2) и / или изображение 3 (H3) на изображение 1. Обратите внимание, что в этом примере изображение 2 аналогично изображению 1, но изображение 3 - нет.

Когда я выполнил беглый поиск алгоритмов «разности гистограмм» (по крайней мере, те, которые я мог понять) Я нашел популярный подход, состоящий в том, чтобы просто суммировать различия между каждым бином, однако этот подход часто терпит неудачу, поскольку он взвешивает все различия бинов одинаково.

Чтобы продемонстрировать проблему с этим подходомв коде C #, например:

Int32[] image1RedHistogram = new Int32[] { 1, 3, 0, 2, 1 };
Int32[] image2RedHistogram = new Int32[] { 3, 2, 0, 1, 2 };
Int32[] image3RedHistogram = new Int32[] { 1, 1, 1, 1, 3 };

Int32 GetDifference(Int32[] x, Int32[] y) {
    Int32 sumOfDifference = 0;
    for( int i = 0; i < x.Length; i++ ) {
        sumOfDifference += Math.Abs( x[i] - y[i] );
    }
    return sumOfDifferences;
}

Вывод которого:

GetDifference( image1RedHistogram, image2RedHistogram ) == 6
GetDifference( image1RedHistogram, image3RedHistogram ) == 6

Это неверно.

Есть ли способ определить разницу междудве гистограммы, учитывающие форму распределения?

Ответы [ 8 ]

73 голосов
/ 28 июня 2011

Сравнение гистограмм само по себе является предметом.

У вас есть два больших класса функций сравнения: сравнение по бинам и сравнение по бинам.

  • Сравнение между корзинами. Как вы сказали, стандартная сумма различий довольно плохая. Есть улучшение, расстояние хи-квадрат , которое говорит, что если H1.red[0] = 0.001 and H2.red[0] = 0.011 гораздо важнее, чем H1.red[0] = 0.1 and H2.red[0] = 0.11, хотя в обоих случаях |H1.red[0] - H2.red[0]| = 0.01.
  • Сравнение между ячейками: стандартный пример, называемый матрицей подобия для ячейки , требует некоторой матрицы подобия M, где в M(i,j) - сходство между ячейками i и j. Предположим, bin[i] красный. Если bin[j] темно-красный, то M(i,j) большой. Если bin[j] зеленый, M(i,j) маленький. Тогда расстояние между гистограммами H1 и H2 будет sqrt((H1-H2)*M*(H1-H2)). Этот метод учитывает то, что вы сказали о «закрытых» корзинах! Расстояние перемещения Земли (EMD) - это еще один тип расстояния между ячейками.

Чтобы закончить, у меня есть три очка:

  • Вы должны прочитать этот документ на расстоянии гистограммы . Это довольно просто и знакомит вас с расстояниями гистограммы. Все расстояния, о которых я говорил, хорошо подытожены в главе 1. Честно говоря, последняя вещь, описанная в статье, не так уж сложна, но, вероятно, это излишне для вашего случая.
  • Расстояние между ячейками очень хорошее, но может быть дорогостоящим (то есть: долго вычислять, потому что оно включает матрицу, то есть O (n ^ 2)). Самый простой способ обойти дорогостоящее перекрестное вычисление (и это широко делается) состоит в том, чтобы сделать некоторое мягкое назначение: если пиксель красный, то вы должны заполнить ВСЕ ячейки, которые удаленно выглядят как красные (конечно, давая больше вес до ближайших цветов). Тогда вы можете использовать алгоритм bin-to-bin.
  • Немного более математически ориентированный: предыдущий пункт был посвящен сокращению сравнения между ячейками до сравнения между ячейками. Фактически, он состоит из неявной диагонализации матрицы подобия M. Если вы можете диагонализировать M = P'*D*P, где P' - транспонирование P, то sqrt((H1-H2)'*M*(H1-H2)) = sqrt((H1-H2)'*P'*D*P*(H1-H2)) = sqrt((P(H1-H2))'*D*(P(H1-H2))). В зависимости от того, насколько просто для вас вычислить P(H1-H2), это может сэкономить вам время вычислений. Интуитивно понятно, что если H1 является вашей исходной гистограммой, P*H1 является мягким заданием, и вы используете неявную матрицу сходства M = P'*Id*P
23 голосов
/ 27 декабря 2013

Я удивлен, что никто не упомянул реализацию opencv сравнения гистограмм, и может легко обрабатывать многоканальные изображения (оттенки серого, rgb, rgba и т. Д.) Различного формата (uchar, float, double и т. Д.)

Включает расстояние Бхаттачарьи, хи-квадрат, методы корреляции и пересечения. Вы можете найти

compareHist(InputArray H1, InputArray H2, int method)

функция в руководстве здесь .

14 голосов
/ 28 июня 2011

Расстояние движителя Земли (EMD) часто используется для сравнения гистограмм этого типа. EMD использует значение, которое определяет стоимость в «перемещении» пикселей из одной ячейки гистограммы в другую, и предоставляет общую стоимость преобразования конкретной гистограммы в целевую. Чем дальше корзина, тем выше стоимость.

В вашем примере перемещение 5 единиц из красного [0] в красное 1 обойдется в (c*1*5), в то время как перемещение 5 единиц из красного [0] в красное [10] будет стоить (c*10*5).

Существует несколько реализаций. FastEMD имеет код на C ++, Java и Matlab. Я считаю, что OpenCV также имеет некоторую поддержку.

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

6 голосов
/ 01 июля 2011

Я считаю, что критерий хи-квадрат будет хорошим началом для сравнения гистограмм.Если у вас нет одинакового количества записей в каждой гистограмме, вы должны быть немного осторожнее, поскольку вы не можете использовать «нормальное» выражение.По памяти, если предположить, что гистограммы имеют неодинаковое количество записей, критерий хи-квадрат обобщается до

1 / (MN) SUM_i [((Mni - Nmi) ^ 2) / (mi + ni)].

M и N - общее количество записей в каждой гистограмме, mi - количество записей в bin i гистограммы M, а ni - количество записей в bin i гистограммы N.

Другой тест - это тест Колмогорова-Смирнова.Этот тест рассматривает максимальную разницу между кумулятивным распределением вероятностей двух гистограмм.Это сложнее реализовать, я думаю, что числовые рецепты на C имеют фрагмент кода на C, и я уверен, что это в Matlab.Если вас больше интересует разница в форме гистограммы, а не в точных значениях, это может быть лучшим тестом, а также непараметрическим.

4 голосов
/ 28 июня 2011

Вы в основном хотите посмотреть вероятностные расстояния .Их много, и вам нужно решить, какой из них подходит для вашей заявки.В последнее время мне повезло с Chi-squared и Kullback-Leibler.

2 голосов
/ 28 июня 2011

Нормализуйте свои гистограммы, разделив значение в каждом бине входящей гистограммы на общее количество пикселей, на которых основана гистограмма. Затем используйте @ tkerwin's EMD .

0 голосов
/ 09 декабря 2015

Как уже упоминали другие, «Движение Земли» или EMD (он же метрика Вассерштейна), вероятно, является оптимальным решением.Метод Shortlist для быстрого вычисления EMD доступен в пакете R, transport .Он был представлен в статье 2014 года , сравнивая ее с другими методами, показывая более быстрое время вычислений.Единственным недостатком является то, что он в R, который не быстрый, если не запрограммирован в C ++ под капотом.

0 голосов
/ 19 сентября 2014

Я думаю, что EMD является хорошим решением для решения проблемы кросс-бина, сравнивая с методом bin-bin. Однако, как некоторые упоминают, EMD очень долго. Не могли бы вы предложить мне какой-то другой подход для кросс-бин?

...