小さなプロジェクトの場合、ある画像を別の画像と比較する必要があります。画像がほぼ同じかどうかを判断するためです。画像は小さく、幅は25〜100ピクセルです。画像は同じ画像データであることが意図されていますが、微妙に異なるため、単純なピクセルの同等性チェックは機能しません。次の2つの可能なシナリオを検討してください。
ヒストグラムを使用して各画像を表すことにしました.3つの1Dヒストグラムを使用します:各RGBチャンネルに1つ-色を使用するだけで、テクスチャヒストグラムとエッジヒストグラムを無視しても安全です(別のアプローチでは、各画像に単一の3Dヒストグラムを使用し、しかし、それは余分な複雑さを追加するので、それを避けています。したがって、ヒストグラムを比較してそれらがどれほど似ているかを確認する必要があります。類似性の尺度がしきい値を超えた場合、各画像が視覚的に同じであると自信を持って言うことができます-各画像の対応するチャネルヒストグラムを比較します1の赤のヒストグラムと画像2の赤のヒストグラム、次に画像1の青のヒストグラムと画像2の青のヒストグラム、そして緑のヒストグラム-だから、私は画像1の赤のヒストグラムと画像2の青のヒストグラムを比較していません。
3つの画像の赤のRGBチャネルの要約を表すこれらの3つのヒストグラムがあるとしましょう(簡単にするために7ピクセルの画像に5つのビンを使用します)。
H1 H2 H3
X X X
X X X X X
X X X X X X X X X X X X X
0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
H1 = [ 1, 3, 0, 2, 1 ]
H2 = [ 3, 1, 0, 1, 2 ]
H3 = [ 1, 1, 1, 1, 3 ]
画像1(H1
)は私の参照画像であり、画像2(H2
)および/または画像3(H3
)は画像1に似ています。この例では、画像2は画像1に似ていますが、画像3は似ていません。
「ヒストグラムの差」アルゴリズム(少なくとも私が理解できるアルゴリズム)の大まかな検索を行ったとき、各ビン間の差を単に合計することが一般的なアプローチであることがわかりましたが、このアプローチはすべてのビンの差が同じであるために失敗することがよくあります。
このアプローチの問題をデモンストレーションするには、C#コードで次のようにします。
Int32[] image1RedHistogram = new Int32[] { 1, 3, 0, 2, 1 };
Int32[] image2RedHistogram = new Int32[] { 3, 2, 0, 1, 2 };
Int32[] image3RedHistogram = new Int32[] { 1, 1, 1, 1, 3 };
Int32 GetDifference(Int32[] x, Int32[] y) {
Int32 sumOfDifference = 0;
for( int i = 0; i < x.Length; i++ ) {
sumOfDifference += Math.Abs( x[i] - y[i] );
}
return sumOfDifferences;
}
出力は次のとおりです。
GetDifference( image1RedHistogram, image2RedHistogram ) == 6
GetDifference( image1RedHistogram, image3RedHistogram ) == 6
これは間違っています。
分布の形状を考慮した2つのヒストグラムの違いを判断する方法はありますか?
ヒストグラムを比較すること自体が非常に重要です。
比較関数には、ビン間比較とビン間比較という2つの大きなクラスがあります。
H1.red[0] = 0.001 and H2.red[0] = 0.011
は、H1.red[0] = 0.1 and H2.red[0] = 0.11
よりもはるかに重要であり、どちらの場合も|H1.red[0] - H2.red[0]| = 0.01
です。M(i,j)
がビンiとjの類似性である類似性マトリックスMが必要です。 bin[i]
が赤であると仮定します。 bin[j]
が暗赤色の場合、M(i,j)
は大きくなります。 bin[j]
が緑色の場合、M(i,j)
は小さいです。この場合、ヒストグラムH1とH2の間の距離はsqrt((H1-H2)*M*(H1-H2))
になります。この方法は、「近い」ビンについてあなたが言ったことを考慮に入れます! 地球移動距離(EMD)は、別の種類のクロスビン距離です。最後に、3つのポイントがあります。
M = P'*D*P
を対角化できる場合、P'
はP
の転置で、その後sqrt((H1-H2)'*M*(H1-H2)) = sqrt((H1-H2)'*P'*D*P*(H1-H2)) = sqrt((P(H1-H2))'*D*(P(H1-H2)))
です。 P(H1-H2)
を計算するのがいかに簡単かによっては、計算時間を節約できます。直感的に、H1
が元のヒストグラムである場合、P*H1
はソフト割り当てであり、暗黙的な類似性マトリックスM = P'*Id*P
を使用しています誰もヒストグラム比較のopencv実装について言及していないことに驚いています。また、異なる形式(uchar、float、doubleなど)のマルチチャネルイメージ(グレースケール、rgb、rgbaなど)を簡単に処理できます。
バタチャリャ距離、カイ二乗法、相関法、交差法が含まれます。あなたが見つけることができます
compareHist(InputArray H1, InputArray H2, int method)
マニュアルの機能 こちら 。
このタイプのヒストグラム比較には、Earth Mover's Distance(EMD)がよく使用されます。 EMDは、ヒストグラムのあるビンから別のビンにピクセルを「移動」するコストを定義する値を使用し、特定のヒストグラムをターゲットヒストグラムに変換する際の総コストを提供します。ビンが遠くなるほど、コストが高くなります。
あなたの例では、5単位をred [0]からred 1 に移動すると(c*1*5)
5ユニットを赤[0]から赤[10]に移動すると、コストが(c*10*5)
。
いくつかの実装があります。 FastEMD にはC++のコードがあり、JavaおよびMatlab。OpenCVにも何らかのサポートがあると思います。
大規模な画像データベースの類似検索のために、この手法を使用して公開された多くの論文があります。
ヒストグラムを比較する場合、カイ二乗検定を開始するのに適した場所であることがわかりました。各ヒストグラムに同じ数のエントリがない場合は、「通常の」式を使用できないため、もう少し注意する必要があります。メモリから、ヒストグラムのエントリ数が等しくないと仮定すると、カイ二乗検定は一般化されます
1 /(MN)SUM_i [((Mni-Nmi)^ 2)/(mi + ni)]。
MとNは各ヒストグラムのエントリの総数、miはヒストグラムMのビンiのエントリの数、niはヒストグラムNのビンiのエントリの数です。
もう1つのテストは、コルモゴロフ-スミルノフテストです。このテストでは、2つのヒストグラムの累積確率分布の最大差を調べます。これを実装するのは難しいです。Cの数値レシピにはCのコードスニペットがあり、Matlabにあると確信しています。違いにもっと興味がある場合はヒストグラムの形状であり、正確な値はそれほど多くないので、これはそのノンパラメトリックでもより良いテストになるでしょう。
基本的には、 確率距離 を探します。多数あり、アプリケーションに適したものを決定する必要があります。最近、私はカイ二乗とカルバック・ライブラーで運が良かった。
着信ヒストグラムの各ビンの値を、ヒストグラムのベースとなるピクセルの総数で除算することにより、ヒストグラムを正規化します。次に、 @ tkerwinのEMD を使用します。
EMDはビン間方法と比較してクロスビン問題を解決するための良い解決策だと思います。ただし、いくつか言及するように、EMDは非常に長い時間です。クロスビンのためのいくつかの他のアプローチを私に提案してもらえますか?