Información mutua y entropía conjunta de dos imágenes – MATLAB

Tengo dos imágenes en blanco y negro y necesito calcular la información mutua.

Image 1 = X Image 2 = Y 

Sé que la información mutua se puede definir como:

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

MATLAB ya tiene funciones incorporadas para calcular la entropía pero no para calcular la entropía conjunta. Supongo que la verdadera pregunta es: ¿cómo puedo calcular la entropía conjunta de dos imágenes?

Aquí hay un ejemplo de las imágenes en las que me gustaría encontrar la entropía conjunta de:

 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 

Para calcular la entropía conjunta, debe calcular el histogtwig de articulación entre dos imágenes. El histogtwig de articulación es esencialmente el mismo que un histogtwig 1D normal, pero la primera dimensión registra intensidades para la primera imagen y la segunda dimensión registra intensidades para la segunda imagen. Esto es muy similar a lo que comúnmente se conoce como una matriz de concurrencia . En la ubicación (i,j) en el histogtwig de articulación, te dice cuántos valores de intensidad hemos encontrado que tienen intensidad i en la primera imagen e intensidad j en la segunda imagen.

Lo importante es que esto registra cuántas veces hemos visto este par de intensidades en las mismas ubicaciones correspondientes . Por ejemplo, si tenemos un conteo de histogtwig conjunto de (7,3) = 2 , esto significa que cuando estábamos escaneando ambas imágenes, cuando encontramos la intensidad de 7 , en la misma ubicación correspondiente en la segunda imagen, encontramos el intensidad de 3 para un total de 2 veces.

La construcción de un histogtwig conjunto es muy simple de hacer.

  1. Primero, cree una matriz de 256 x 256 (suponiendo que su imagen sea un entero de 8 bits sin signo) y los inicialice en todos los ceros. Además, debe asegurarse de que ambas imágenes tengan el mismo tamaño (ancho y alto).
  2. Una vez que lo hagas, eche un vistazo al primer píxel de cada imagen, que denotaremos como la esquina superior izquierda. Específicamente, eche un vistazo a las intensidades para la primera y segunda imagen en esta ubicación. La intensidad de la primera imagen servirá como la fila mientras que la intensidad de la segunda imagen servirá como la columna.
  3. Encuentre esta ubicación en la matriz e incremente este punto en la matriz en 1 .
  4. Repita esto para el rest de las ubicaciones en su imagen.
  5. Una vez que haya terminado, divida todas las entradas por la cantidad total de elementos en cada imagen (recuerde que deben ser del mismo tamaño). Esto nos dará la distribución de probabilidad conjunta entre ambas imágenes.

Uno estaría inclinado a hacer esto con bucles for , pero como es comúnmente conocido, los bucles son notoriamente lentos y deben evitarse si es posible. Sin embargo, puede hacer esto fácilmente en MATLAB de la siguiente manera sin bucles. Supongamos que im1 e im2 son la primera y la segunda imagen que desea comparar. Lo que podemos hacer es convertir im1 e im2 en vectores. Luego podemos usar accumarray para ayudarnos a calcular el histogtwig conjunto. accumarray es una de las funciones más potentes de MATLAB. Puedes pensarlo como un paradigma MapReduce en miniatura. En pocas palabras, cada entrada de datos tiene una clave y un valor asociado. El objective de accumarray es accumarray todos los valores que pertenecen a la misma clave y realizar alguna operación en todos estos valores. En nuestro caso, la “clave” serían los valores de intensidad, y los valores en sí mismos son el valor de 1 para cada valor de intensidad. Entonces, querríamos sumr todos los valores de 1 ese mapa al mismo contenedor, que es exactamente como calcularíamos un histogtwig. El comportamiento predeterminado para accumarray es agregar todos estos valores. Específicamente, la salida de accumarray sería una matriz en la que cada posición calcula la sum de todos los valores asignados a esa clave. Por ejemplo, la primera posición sería la sum de todos los valores asignados a la clave de 1, la segunda posición sería la sum de todos los valores asignados a la clave de 2 y así sucesivamente.

Sin embargo, para el histogtwig de articulación, desea averiguar qué valores se correlacionan con el mismo par de intensidad de (i,j) , por lo que las claves aquí serían un par de coordenadas 2D. Como tal, cualquier intensidad que tenga una intensidad de i en la primera imagen j en la segunda imagen en la misma ubicación espacial compartida entre las dos imágenes vaya a la misma tecla. Por lo tanto, en el caso 2D, la salida de accumarray sería una matriz 2D donde cada elemento (i,j) contiene la sum de todos los valores asignados a la clave (i,j) , similar al caso 1D que se mencionó anteriormente que es exactamente lo que buscamos

En otras palabras:

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

Con accumarray , la primera entrada son las teclas y la segunda entrada son los valores. Una nota con accumarray es que si cada clave tiene el mismo valor, simplemente puede asignar una constante a la segunda entrada, que es lo que hice y es 1 . En general, esta es una matriz con el mismo número de filas que la primera entrada. Además, tome nota especial de las dos primeras líneas. Inevitablemente habrá una intensidad de 0 en su imagen, pero debido a que MATLAB comienza a indexar en 1 , necesitamos compensar ambas matrices por 1 .

Ahora que tenemos el histogtwig conjunto, es realmente simple calcular la entropía conjunta. Es similar a la entropía en 1D, excepto que ahora solo estamos sumndo toda la matriz de probabilidad conjunta. Tenga en cuenta que es muy probable que su histogtwig conjunto tenga muchas entradas. Necesitamos asegurarnos de omitirlos o la operación log2 no estará definida. Deshagámonos de cualquier entrada cero ahora:

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

Tenga en cuenta que busqué el histogtwig conjunto en lugar de la matriz de probabilidad conjunta. Esto se debe a que el histogtwig conjunto consta de números enteros, mientras que la matriz de probabilidad conjunta se encuentra entre 0 y 1 . Debido a la división, quiero evitar comparar cualquier entrada en esta matriz con 0 debido al redondeo numérico y la inestabilidad. Lo anterior también convertirá nuestra matriz de probabilidad conjunta en un vector 1D astackdo, lo cual está bien.

Como tal, la entropía conjunta se puede calcular como:

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

Si mi comprensión del cálculo de entropía para una imagen en MATLAB es correcta, debe calcular la distribución de histogtwig / probabilidad en 256 bins, por lo que ciertamente puede usar esa función aquí con la entropía conjunta que acaba de calcularse.

¿Qué pasa si tenemos datos de punto flotante en su lugar?

Hasta ahora, hemos asumido que las imágenes que ha tratado tienen intensidades que son de valor entero. ¿Qué pasa si tenemos datos de coma flotante? accumarray asume que estás tratando de indexar en la matriz de salida usando enteros, pero aún podemos lograr lo que queremos con este pequeño bache en el camino. Lo que harías es simplemente asignar cada valor de punto flotante en ambas imágenes para tener una ID única . Por lo tanto, usaría accumarray con estas ID en su lugar. Para facilitar esta asignación de ID, use unique , específicamente la tercera salida de la función. Tomaría cada una de las imágenes, las pondría en unique y las convertiría en índices para ingresar en accumarray . En otras palabras, haz esto en su lugar:

 [~,~,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)); 

Tenga en cuenta que con indrow e indcol , estamos asignando directamente el tercer resultado unique de estas variables y luego utilizando el mismo código de entropía conjunta que calculamos anteriormente. Tampoco tenemos que compensar las variables por 1 como lo hicimos anteriormente porque unique asignará ID a partir de 1 .

Aparte

En realidad, puede calcular los histogtwigs o distribuciones de probabilidad para cada imagen individualmente utilizando la matriz de probabilidad conjunta. Si quisiera calcular las distribuciones de histogtwigs / probabilidad para la primera imagen, simplemente acumularía todas las columnas para cada fila. Para hacerlo en la segunda imagen, simplemente acumulará todas las filas para cada columna. Como tal, puedes hacer:

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

Después, puedes calcular la entropía de ambos por ti mismo. Para verificarlo dos veces, asegúrese de convertir ambos en archivos PDF, luego calcule la entropía usando la ecuación estándar (como se muestra arriba).


¿Cómo puedo finalmente calcular la información mutua?

Para finalmente calcular la información mutua, vas a necesitar la entropía de las dos imágenes. Puede usar la función de entropy incorporada de MATLAB, pero esto supone que hay 256 niveles únicos. Probablemente desee aplicar esto para el caso de que haya N niveles distintos en lugar de 256, de modo que pueda usar lo que hicimos anteriormente con el histogtwig de articulación, luego calcular los histogtwigs para cada imagen en el código de anotación de arriba, y luego calcular el entropía para cada imagen. Simplemente, debería repetir el cálculo de entropía que se utilizó conjuntamente, pero aplíquelo a cada imagen individualmente:

 %// Find non-zero elements for first image's 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; 

¡Espero que esto ayude!