web-dev-qa-db-ja.com

2つの画像の相互情報量と結合エントロピー-MATLAB

白黒の画像が2つあり、相互情報量を計算する必要があります。

Image 1 = X 
Image 2 = Y

相互情報量は次のように定義できることを知っています。

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

MATLABには既にエントロピーを計算するための組み込み関数がありますが、結合エントロピーを計算するための関数はありません。本当の質問は次のとおりだと思います:2つの画像の結合エントロピーを計算するにはどうすればよいですか?

これが私が共同エントロピーを見つけたい画像の例です:

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
24
Jorge

結合エントロピーを計算するには、2つの画像間の結合ヒストグラムを計算する必要があります。結合ヒストグラムは基本的に通常の1Dヒストグラムと同じですが、最初の次元は最初の画像の強度を記録し、2番目の次元は2番目の画像の強度を記録します。これは、一般に 共起行列 と呼ばれるものとよく似ています。ジョイントヒストグラムの(i,j)の場所で、最初の画像に強度iがあり、2番目の画像に強度jがある強度値の数がわかります。

重要なことは、これがこの強度のペアを何回目にしたかをログに記録することです同じ対応する場所で。たとえば、(7,3) = 2の結合ヒストグラムカウントがある場合、これは、両方の画像をスキャンしているときに、2番目の画像の同じ対応する場所で7の強度に遭遇したときに、合計で3の強度に遭遇したことを意味します2回の。

結合ヒストグラムの作成は非常に簡単です。

  1. 最初に、256 x 256マトリックスを作成し(画像が符号なしの8ビット整数であると想定)、それらをすべてゼロに初期化します。また、両方の画像が同じサイズ(幅と高さ)であることを確認する必要があります。
  2. それが終わったら、各画像の最初のピクセルを見てください。これを左上隅と呼びます。具体的には、この場所の最初の画像と2番目の画像の強度を確認してください。最初の画像の強度は行として機能し、2番目の画像の強度は列として機能します。
  3. マトリックス内のこの場所を見つけ、1だけマトリックス内のこのスポットを増分します。
  4. イメージ内の残りの場所について、これを繰り返します。
  5. 完了したら、すべてのエントリをいずれかの画像の要素の総数で割ります(同じサイズにする必要があることに注意してください)。これにより、両方の画像間の結合確率分布が得られます。

forループを使用してこれを行う傾向がありますが、一般に知られているように、forループは低速であることが悪名高いため、可能な限り回避する必要があります。ただし、MATLABで次のように簡単に実行できますwithoutループ。 im1im2が比較する最初と2番目の画像であると仮定しましょう。私たちにできることは、im1im2をベクトルに変換することです。次に accumarray を使用して、結合ヒストグラムを計算することができます。 accumarrayは、MATLABで最も強力な関数の1つです。 MapReduceの小さなパラダイムと考えることができます。簡単に言えば、各データ入力にはキーとそれに関連付けられた値があります。 accumarrayの目標は、同じキーに属するすべての値をビニングし、これらのすべての値に対して何らかの操作を行うことです。私たちの場合、「キー」は強度値であり、値自体はすべての強度値の1の値です。次に、add同じビンにマップする1のすべての値を上げます。これは、正確にヒストグラムを計算する方法です。 accumarrayのデフォルトの動作は、これらの値をすべて追加することです。具体的には、accumarrayの出力は、各位置がそのキーにマップされたすべての値の合計を計算する配列になります。たとえば、最初の位置は1のキーにマップされたすべての値の合計であり、2番目の位置は2のキーにマップされたすべての値の合計です。

ただし、ジョイントヒストグラムの場合、どの値が(i,j)の同じ強度ペアにマップされるかを把握する必要があるため、ここでのキーは2D座標のペアになります。したがって、最初の画像でiの強度、2番目の画像でjの強度を持つ強度同じ空間位置に 2つの画像間で共有同じキー。したがって、2Dの場合、accumarrayの出力は2D行列となり、各要素(i,j)には、前述の1Dの場合と同様に、キー(i,j)にマップされたすべての値の合計が含まれます。後です。

言い換えると:

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では、最初の入力はキーで、2番目の入力は値です。 accumarrayに関するメモは、各キーにsame値がある場合、2番目の入力に定数を割り当てることができるということです。これは私がやったことで、1です。一般に、これは最初の入力と同じ行数の配列です。また、最初の2行に特に注意してください。画像には必ず0の強度がありますが、MATLABは1からインデックスを開始するため、両方の配列を1でオフセットする必要があります。

これで結合ヒストグラムができたので、結合エントロピーを計算するのは本当に簡単です。 1Dのエントロピーに似ていますが、結合確率行列全体を合計しているだけです。結合ヒストグラムに多くの0エントリが含まれる可能性が非常に高いことに注意してください。これらをスキップしないと、log2オペレーションが未定義になります。ここで、ゼロのエントリをすべて削除しましょう。

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

結合確率行列の代わりに結合ヒストグラムを検索したことに注意してください。これは、結合ヒストグラムが整数で構成されるのに対し、結合確率行列は01の間にあるためです。除算のため、数値の丸めと不安定性のために、この行列のエントリを0と比較しないようにします。上記はまた、結合確率行列を積み上げ1Dベクトルに変換しますが、これは問題ありません。

したがって、結合エントロピーは次のように計算できます。

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

MATLABでの画像のエントロピーの計算に関する私の理解が正しい場合は、256ビンのヒストグラム/確率分布を計算する必要があります。そのため、ここで計算したばかりの結合エントロピーでこの関数を確実に使用できます。

代わりに浮動小数点データがある場合はどうなりますか?

これまでのところ、あなたが扱った画像は整数値の強度を持っていると仮定しました。浮動小数点データがある場合はどうなりますか? accumarrayは、整数を使用して出力配列にインデックスを付けようとしていることを前提としていますが、この小さなバンプで目的どおりの結果を確実に達成できます。あなたがすることは、両方の画像の各浮動小数点値にnique IDを割り当てるだけです。したがって、代わりにこれらのIDでaccumarrayを使用します。このIDの割り当てを容易にするには、 unique を使用します。具体的には、関数からの3番目の出力です。各画像を取得して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));

indrowindcolでは、uniqueの3番目の出力をこれらの変数に直接割り当ててから、前に計算したのと同じ結合エントロピーコードを使用しています。 uniqueはID 1から始まるを割り当てるため、以前のように変数を1だけオフセットする必要もありません。

さておき

結合確率行列を使用して、実際に各画像のヒストグラムまたは確率分布を個別に計算できます。最初の画像のヒストグラム/確率分布を計算する場合は、各行のすべての列を累積するだけです。 2番目の画像に対してこれを行うには、単純に各列のすべての行を累積します。そのため、次のことができます。

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

その後、これらの両方のエントロピーを自分で計算できます。再確認するには、これらの両方をPDFに変換してから、上記のような標準の方程式を使用してエントロピーを計算します。


最終的に相互情報量を計算するにはどうすればよいですか?

最終的に相互情報量を計算するには、2つの画像のエントロピーが必要になります。 MATLABの組み込み entropy 関数を使用できますが、これは256の一意のレベルがあることを前提としています。おそらく、256ではなくNの異なるレベルがある場合にこれを適用する必要があります。そのため、上記の結合ヒストグラムを使用して、上記の脇のコードの各画像のヒストグラムを計算できます。 、次に各画像のエントロピーを計算します。一緒に使用されたエントロピー計算を繰り返すだけで、それを各画像に個別に適用します。

%// 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;

お役に立てれば!