Взаимная информация и совместная энтропия двух изображений - MATLAB

У меня два черно-белых изображения, и мне нужно рассчитать взаимную информацию.

Image 1 = X 
Image 2 = Y

Я знаю, что взаимную информацию можно определить как:

MI = entropy(X) + entropy(Y) - JointEntropy(X,Y)

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

Вот пример изображений, которые я хотел бы найти в совместной энтропии:

X =

0    0    0    0    0    0
0    0    1    1    0    0
0    0    1    1    0    0
0    0    0    0    0    0
0    0    0    0    0    0

Y =

0    0    0    0    0    0 
0    0    0.38 0.82 0.38 0.04 
0    0    0.32 0.82 0.68 0.17
0    0    0.04 0.14 0.11 0 
0    0    0    0    0    0

Ответ 1

Чтобы рассчитать общую энтропию, вам нужно вычислить общую гистограмму между двумя изображениями. Совместная гистограмма по существу такая же, как и нормальная 1D-гистограмма, но в первом измерении регистрируются интенсивности для первого изображения, а во втором измерении регистрируются интенсивности для второго изображения. Это очень похоже на то, что обычно называют матрицей совпадения. При размещении (i,j) в общей гистограмме он сообщает вам, сколько значений интенсивности мы встретили, которые имеют интенсивность i в первом изображении и интенсивность j во втором изображении.

Важно то, что в этом журнале сколько раз мы видели эту пару интенсивностей в тех же соответствующих местах. Например, если у нас есть общий счет гистограммы (7,3) = 2, это означает, что когда мы сканировали оба изображения, когда мы столкнулись с интенсивностью 7, в том же соответствующем месте на втором изображении, мы столкнулись с интенсивностью 3 в общей сложности 2 раз.

Построение общей гистограммы очень просто.

  • Сначала создайте матрицу 256 x 256 (предположим, что ваше изображение является неподписанным 8-битным целым числом) и инициализируйте их для всех нулей. Кроме того, вы должны убедиться, что оба изображения имеют одинаковый размер (ширина и высота).
  • Как только вы это сделаете, взгляните на первый пиксель каждого изображения, который мы обозначим как верхний левый угол. В частности, взгляните на интенсивности для первого и второго изображений в этом месте. Интенсивность первого изображения будет служить строкой, а интенсивность второго изображения будет служить столбцом.
  • Найдите это местоположение в матрице и увеличьте это пятно в матрице на 1.
  • Повторите это для остальных мест вашего изображения.
  • После того, как вы закончите, разделите все записи на общее количество элементов в любом изображении (помните, что они должны быть одного размера). Это даст нам совместное распределение вероятностей между обоими изображениями.

Можно было бы сделать это с помощью циклов for, но, как известно, петли for, как известно, медленны и их следует избегать, если это вообще возможно. Однако вы можете легко сделать это в MATLAB следующим образом: без. Предположим, что im1 и im2 - это первое и второе изображения, с которыми вы хотите сравнить. Мы можем сделать преобразование im1 и im2 в векторы. Затем мы можем использовать accumarray, чтобы помочь нам вычислить общую гистограмму. accumarray - одна из самых мощных функций в MATLAB. Вы можете думать о нем как о миниатюрной парадигме MapReduce. Проще говоря, каждый ввод данных имеет ключ и соответствующее значение. Целью accumarray является объединение всех значений, принадлежащих одному и тому же ключу, и выполнение некоторых операций над всеми этими значениями. В нашем случае "ключ" будет значением интенсивности, а сами значения представляют собой значение 1 для каждого значения интенсивности. Затем мы хотели бы добавить все значения 1, которые сопоставляются с одним и тем же ящиком, что и мы вычислили гистограмму. Поведение по умолчанию для accumarray заключается в добавлении всех этих значений. В частности, вывод accumarray будет массивом, где каждая позиция вычисляет сумму всех значений, сопоставленных этому ключу. Например, первая позиция будет суммировать все значения, которые отображаются на ключ из 1, вторая позиция будет суммировать все значения, которые отображаются на ключ из 2 и так далее.

Однако для совместной гистограммы вы хотите выяснить, какие значения соответствуют одной и той же паре интенсивности (i,j), поэтому здесь будут две пары координат. Таким образом, любые интенсивности, имеющие интенсивность i в первом изображении и j во втором изображении в том же пространственном местоположении, разделяемом между двумя изображениями, переходят к одному и тому же ключу. Поэтому в 2D-случае вывод accumarray будет двумерной матрицей, в которой каждый элемент (i,j) содержит суммирование всех значений, отображаемых на ключ (i,j), аналогично случаю 1D, о котором упоминалось ранее, что и есть то, что мы после.

Другими словами:

indrow = double(im1(:)) + 1;
indcol = double(im2(:)) + 1; %// Should be the same size as indrow
jointHistogram = accumarray([indrow indcol], 1);
jointProb = jointHistogram / numel(indrow);

С accumarray первый вход - это клавиши, а второй вход - значения. Примечание с accumarray заключается в том, что если каждый ключ имеет тот жезначение, вы можете просто назначить константу второму входу, это то, что я сделал, и это 1. В общем, это массив с таким же количеством строк, что и первый вход. Также обратите особое внимание на первые две строки. На вашем изображении неизбежно будет интенсивность 0, но поскольку MATLAB начинает индексирование в 1, нам нужно смещать оба массива на 1.

Теперь, когда у нас есть совместная гистограмма, очень просто вычислить совместную энтропию. Он похож на энтропию в 1D, за исключением того, что теперь мы просто суммируем по всей совместной вероятностной матрице. Имейте в виду, что очень вероятно, что ваша общая гистограмма будет содержать много записей 0. Нам нужно убедиться, что мы пропустим те, или операция log2 будет undefined. Теперь избавьтесь от любых нулевых элементов:

indNoZero = jointHistogram ~= 0;
jointProb1DNoZero = jointProb(indNoZero);

Обратите внимание, что я искал совместную гистограмму вместо совместной матрицы вероятности. Это связано с тем, что совместная гистограмма состоит из целых чисел, а совместная вероятностная матрица будет находиться между 0 и 1. Из-за деления я хочу избежать сравнения любых элементов в этой матрице с 0 из-за численного округления и нестабильности. Вышеупомянутое также преобразует нашу совместную вероятностную матрицу в многослойный 1D-вектор, что отлично.

Таким образом, совместная энтропия может быть рассчитана как:

jointEntropy = -sum(jointProb1DNoZero.*log2(jointProb1DNoZero));

Если мое понимание вычисления энтропии для изображения в MATLAB правильное, оно должно рассчитать распределение гистограммы/вероятности над ячейками 256, поэтому вы можете использовать эту функцию здесь с объединенной энтропией, которая была просто рассчитана.

Что делать, если у нас есть данные с плавающей запятой?

До сих пор мы предполагали, что образы, с которыми вы имели дело, имеют интенсивности, которые являются целыми значениями. Что делать, если у нас есть данные с плавающей запятой? accumarray предполагает, что вы пытаетесь индексировать массив вывода с использованием целых чисел, но мы все равно можем выполнить то, что хотим, с этим небольшим ударом на дороге. Что бы вы сделали, просто назначьте каждое значение с плавающей запятой в обоих изображениях с уникальным идентификатором. Таким образом, вы использовали бы accumarray с этими идентификаторами. Чтобы облегчить назначение этого идентификатора, используйте unique - в частности, третий вывод функции. Вы берете каждое из изображений, помещаете их в unique и вводите эти индексы в accumarray. Другими словами, сделайте это вместо этого:

[~,~,indrow] = unique(im1(:)); %// Change here
[~,~,indcol] = unique(im2(:)); %// Change here

%// Same code
jointHistogram = accumarray([indrow indcol], 1);
jointProb = jointHistogram / numel(indrow);
indNoZero = jointHistogram ~= 0;
jointProb1DNoZero = jointProb(indNoZero);
jointEntropy = -sum(jointProb1DNoZero.*log2(jointProb1DNoZero));

Обратите внимание, что с помощью indrow и indcol мы непосредственно назначаем третий вывод unique этим переменным, а затем используя тот же самый общий энтропийный код, который мы вычислили ранее. Нам также не нужно смещать переменные на 1, как мы это делали ранее, потому что unique будет присваивать идентификаторы начиная с 1.

Помимо

Фактически вы можете рассчитать гистограммы или распределения вероятностей для каждого изображения индивидуально, используя совместную вероятностную матрицу. Если вы хотите рассчитать гистограммы/распределения вероятностей для первого изображения, вы просто аккумулируете все столбцы для каждой строки. Чтобы сделать это для второго изображения, вы просто аккумулируете все строки для каждого столбца. Таким образом, вы можете:

histogramImage1 = sum(jointHistogram, 1);
histogramImage2 = sum(jointHistogram, 2);

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


Как я могу наконец вычислить взаимную информацию?

Чтобы окончательно вычислить взаимную информацию, вам понадобится энтропия двух изображений. Вы можете использовать встроенную функцию MATLAB entropy, но это предполагает, что имеется 256 уникальных уровней. Вероятно, вы захотите применить это для случая наличия N различных уровней вместо 256, и поэтому вы можете использовать то, что мы сделали выше, с общей гистограммой, а затем вычислить гистограммы для каждого изображения в предыдущем коде выше, а затем вычисляя энтропию для каждого изображения. Вы просто повторите расчет энтропии, который использовался совместно, но примените его к каждому изображению индивидуально:

%// Find non-zero elements for first image histogram
indNoZero = histogramImage1 ~= 0;

%// Extract them out and get the probabilities
prob1NoZero = histogramImage1(indNoZero) / numel(histogramImage1);

%// Compute the entropy
entropy1 = -sum(prob1NoZero.*log2(prob1NoZero));

%// Repeat for the second image
indNoZero = histogramImage2 ~= 0;
prob2NoZero = histogramImage2(indNoZero) / numel(histogramImage2);
entropy2 = -sum(prob2NoZero.*log2(prob2NoZero));

%// Now compute mutual information
mutualInformation = entropy1 + entropy2 - jointEntropy;

Надеюсь, это поможет!