Information mutuelle et entropie commune de deux images-MATLAB

j'ai deux images en noir et blanc et j'ai besoin de calculer l'information mutuelle.

Image 1 = X 
Image 2 = Y

je sais que l'information mutuelle peut être défini comme suit:

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

MATLAB a déjà des fonctions intégrées pour calculer l'entropie mais pas pour calculer l'entropie commune. Je suppose que la vraie question est: comment calculer l'entropie commune de deux images?

voici un exemple des images que j'aimerais trouver l'entropie commune 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
20
demandé sur rayryeng 2014-05-16 05:47:03

1 réponses

Pour calculer l'entropie conjointe, vous devez calculer l'histogramme conjoint entre les deux images. L'histogramme joint est essentiellement le même qu'un histogramme 1D normal, mais la première dimension enregistre les intensités pour la première image et la deuxième dimension enregistre les intensités pour la deuxième image. Ceci est très similaire à ce qui est communément appelé matrice de co-occurrence. Au lieu (i,j) dans l'histogramme joint, il indique combien de valeurs d'intensité nous avons rencontré qui ont de l'intensité i dans la première image et l'intensité j dans la deuxième image.

Ce qui est important, c'est que ce dernier enregistre combien de fois nous avons vu cette paire d'intensités aux mêmes endroits. Par exemple, si nous avons un histogramme conjoint comte de (7,3) = 2, cela signifie que lorsque nous numérisions les deux images, lorsque nous avons rencontré l'intensité de 7, au même endroit correspondant dans la deuxième image, nous rencontré l'intensité de l' 3 pour un total de 2 fois.

construire un histogramme articulaire est très simple à faire.

  1. tout d'Abord, créez un 256 x 256 matrix (en supposant que votre image est un entier 8 bits non signé) et initialisez-les à tous les zéros. Aussi, vous devez vous assurer que vos deux images sont de la même taille (largeur et hauteur).
  2. une fois que vous avez fait cela, regardez le premier pixel de chaque image, que nous désignerons par le haut gauche de l'écran. Plus précisément, examinez les intensités de la première et de la deuxième image à cet endroit. L'intensité de la première image qui servira de ligne, tandis que l'intensité de la deuxième image servira de colonne.
  3. trouver cet emplacement dans la matrice et incrémenter cette tache dans la matrice par 1.
  4. répétez ceci pour le reste des emplacements de votre image.
  5. après avoir terminé, divisez toutes les entrées par le nombre total d'éléments dans l'image (n'oubliez pas qu'ils doivent être de la même taille). Cela nous donnera la distribution de probabilité conjointe entre les deux images.

On serait enclin à le faire avec for boucles, mais comme il est communément appelé, for les boucles sont notoirement lentes et doivent être évitées si possible. Cependant, vous pouvez facilement le faire dans MATLAB de la manière suivante sans boucles. Supposons que im1 et im2 sont les première et deuxième images souhaitez comparer. Ce que nous pouvons faire, c'est Convertir!--17--> et im2 en vecteurs. Nous pouvons alors utiliser accumarray pour nous aider à calculer l'histogramme conjoint. accumarray est l'une des fonctions les plus puissantes de MATLAB. Vous pouvez penser à lui comme une MapReduce paradigme miniature. En termes simples, chaque entrée de données a une clé et une valeur associée. Le but de accumarray est de biner toutes les valeurs qui appartiennent à la même clé et faire une opération sur toutes ces valeurs. Dans notre cas, la "clé" serait les valeurs d'intensité, et les valeurs elles-mêmes sont la valeur de 1 pour chaque valeur d'intensité. On voudrait alors ajouter toutes les valeurs de 1 cette correspondance à la même boîte, ce qui est exactement la façon de calculer un histogramme. Le comportement par défaut accumarray est d'ajouter toutes ces valeurs. Plus précisément, la sortie de accumarray serait un tableau dans lequel chaque position calcule la somme de toutes les valeurs qui correspondent à cette clé. Par exemple, la première position est la somme de toutes les valeurs qui ont cartographié à la clé de 1, la deuxième position est la somme de toutes les valeurs qui ont cartographié à la clé de 2 et ainsi de suite.

Cependant, pour l'histogramme commun, vous voulez savoir quelles valeurs correspondent à la même paire d'intensité de (i,j), et donc les clés ici seraient une paire de coordonnées 2D. En tant que tel, toute intensité qui ont une intensité de i dans la première image et j dans la deuxième image dans le même spatiales emplacement partagées entre les deux images vont à la même clé. Par conséquent, dans le cas 2D, la sortie de accumarray serait une matrice 2D où chaque élément (i,j) contient la somme de toutes les valeurs qui ont cartographié à la touche (i,j), semblable à L'affaire 1D qui a été mentionnée précédemment et qui est exactement ce que nous cherchons.

En d'autres termes:

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, la première entrée sont les clés et la seconde entrée sont les valeurs. Une note avec accumarray est que si chaque touche valeur, vous pouvez simplement assigner une constante à la seconde entrée, ce qui est ce que j'ai fait et c'est 1. En général, c'est un tableau avec le même nombre de lignes que la première entrée. Prenez également note des deux premières lignes. Il y aura inévitablement une intensité de 0 dans votre image, mais parce que MATLAB commence à indexer à 1, il faut décaler les deux tableaux de 1.

maintenant que nous avons l'histogramme articulaire, c'est très simple de calculer l'entropie commune. Il est similaire à l'entropie dans 1D, sauf que maintenant nous sommes juste sommation sur l'ensemble de la matrice de probabilité joint. Gardez à l'esprit qu'il sera très probable que votre conjoint histogramme aura beaucoup 0 entrées. Nous devons nous assurer que nous ignorer ceux ou l' log2 opération non définie. Débarrassons-nous des Zéro entrées maintenant:

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

sachez que j'ai cherché l'histogramme articulaire au lieu de l'histogramme articulaire matrice de probabilité. C'est parce que l'histogramme commun se compose de nombres entiers tandis que la matrice de probabilité commune se situera entre 0 et 1. En raison de la division, je veux éviter de comparer toutes les entrées dans cette matrice avec 0 en raison d'numérique d'arrondi et de l'instabilité. Ce qui précède convertira également notre matrice de probabilité conjointe en un vecteur 1D empilé, ce qui est très bien.

ainsi, l'entropie conjointe peut être calculée comme:

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

Si mon la compréhension du calcul de l'entropie pour une image dans MATLAB est correcte, il devrait calculer l'histogramme / distribution de probabilité sur 256 bacs, donc vous pouvez certainement utiliser cette fonction ici avec l'entropie commune qui vient d'être calculée.

et si nous avions des données à virgule flottante à la place?

jusqu'à présent, nous avons supposé que les images que vous avez traitées ont des intensités qui sont des valeurs entières. Et si nous avions des données à virgule flottante? accumarray suppose que vous essayez d'indexer dans le tableau de sortie en utilisant des entiers, mais nous pouvons encore certainement accomplir ce que nous voulons Avec cette petite bosse dans la route. Ce que vous feriez est tout simplement assigner chaque valeur flottante dans les deux images pour avoir un ID unique. Vous utiliseriez donc accumarray avec ces identificateurs à la place. Pour faciliter cette assignation D'ID, utilisez unique - spécifiquement la troisième sortie de la fonction. Tu prendrais chacune des images, tu les mettrais dans unique et à faire de ces indices à être entrée dans accumarray. En d'autres termes, faire ceci à la place:

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

Notez que indrow et indcol, nous assignons directement la troisième sortie de unique à ces variables et ensuite en utilisant le même code d'entropie que nous avons calculé plus tôt. Nous n'avons pas non plus à compenser les variables par 1 Comme nous l'avons fait précédemment parce que unique affecter des codes à partir de 1.

mis de côté

Vous peut en fait calculer les histogrammes ou les distributions de probabilité pour chaque image individuellement en utilisant la matrice de probabilité conjointe. Si vous vouliez calculer les histogrammes / distributions de probabilité pour la première image, il vous suffit d'accumuler toutes les colonnes pour chaque ligne. Pour le faire pour la deuxième image, vous accumuleriez simplement toutes les lignes pour chaque colonne. En tant que tel, vous pouvez faire:

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

Après, vous pouvez calculer l'entropie de la fois par vous-même. De double vérification, assurez-vous de transformer les deux en PDFs, puis de calculer l'entropie en utilisant l'équation standard (comme ci-dessus).


Comment puis-je enfin calculer L'Information mutuelle?

enfin calculer l'Information Mutuelle, vous allez avoir besoin de l'entropie des deux images. Vous pouvez utiliser la version intégrée de MATLAB entropy fonction, mais cela suppose qu'il y a 256 niveaux uniques. Vous voulez probablement appliquer ceci pour le cas de là étant N niveaux distincts au lieu de 256, et donc vous pouvez utiliser ce que nous avons fait ci-dessus avec l'histogramme commun, puis calculer les histogrammes pour chaque image dans le code de côté ci-dessus, et puis calculer l'entropie pour chaque image. Vous répétez simplement le calcul d'entropie qui a été utilisé conjointement, mais appliquez-le à chaque image individuellement:

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

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

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

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

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

J'espère que cela vous aidera!

56
répondu rayryeng 2018-09-25 15:59:09