image - calcular - entropia de una señal matlab
Información mutua y entropía conjunta de dos imágenes-MATLAB (1)
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 histograma de articulación entre dos imágenes. El histograma de articulación es esencialmente el mismo que un histograma 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 histograma 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 histograma 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 histograma conjunto es muy simple de hacer.
- 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). - 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.
- Encuentre esta ubicación en la matriz e incremente este punto en la matriz en
1
. - Repita esto para el resto de las ubicaciones en su imagen.
- 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 histograma 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 objetivo 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 sumar todos los valores de 1
ese mapa al mismo contenedor, que es exactamente como calcularíamos un histograma. 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 suma de todos los valores asignados a esa clave. Por ejemplo, la primera posición sería la suma de todos los valores asignados a la clave de 1, la segunda posición sería la suma de todos los valores asignados a la clave de 2 y así sucesivamente.
Sin embargo, para el histograma 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 suma 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 tecla 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 histograma conjunto, es realmente simple calcular la entropía conjunta. Es similar a la entropía en 1D, excepto que ahora solo estamos sumando toda la matriz de probabilidad conjunta. Tenga en cuenta que es muy probable que su histograma 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 histograma conjunto en lugar de la matriz de probabilidad conjunta. Esto se debe a que el histograma 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 apilado, 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 histograma / 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 supuesto que las imágenes con las que ha tratado tienen intensidades que tienen valores enteros. ¿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 histogramas o distribuciones de probabilidad para cada imagen individualmente utilizando la matriz de probabilidad conjunta. Si quisiera calcular las distribuciones de histogramas / 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, y para que pueda usar lo que hicimos anteriormente con el histograma de articulación, luego calcular los histogramas 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!