白黒の画像が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
結合エントロピーを計算するには、2つの画像間の結合ヒストグラムを計算する必要があります。結合ヒストグラムは基本的に通常の1Dヒストグラムと同じですが、最初の次元は最初の画像の強度を記録し、2番目の次元は2番目の画像の強度を記録します。これは、一般に 共起行列 と呼ばれるものとよく似ています。ジョイントヒストグラムの(i,j)
の場所で、最初の画像に強度i
があり、2番目の画像に強度j
がある強度値の数がわかります。
重要なことは、これがこの強度のペアを何回目にしたかをログに記録することです同じ対応する場所で。たとえば、(7,3) = 2
の結合ヒストグラムカウントがある場合、これは、両方の画像をスキャンしているときに、2番目の画像の同じ対応する場所で7
の強度に遭遇したときに、合計で3
の強度に遭遇したことを意味します2
回の。
結合ヒストグラムの作成は非常に簡単です。
256 x 256
マトリックスを作成し(画像が符号なしの8ビット整数であると想定)、それらをすべてゼロに初期化します。また、両方の画像が同じサイズ(幅と高さ)であることを確認する必要があります。1
だけマトリックス内のこのスポットを増分します。for
ループを使用してこれを行う傾向がありますが、一般に知られているように、for
ループは低速であることが悪名高いため、可能な限り回避する必要があります。ただし、MATLABで次のように簡単に実行できますwithoutループ。 im1
とim2
が比較する最初と2番目の画像であると仮定しましょう。私たちにできることは、im1
とim2
をベクトルに変換することです。次に 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);
結合確率行列の代わりに結合ヒストグラムを検索したことに注意してください。これは、結合ヒストグラムが整数で構成されるのに対し、結合確率行列は0
と1
の間にあるためです。除算のため、数値の丸めと不安定性のために、この行列のエントリを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));
indrow
とindcol
では、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;
お役に立てれば!