画像の類似性を比較するためのシンプルで高速な方法


192

2つの画像の類似性を比較する簡単で高速な方法が必要です。つまり、まったく同じものが含まれていても、背景がわずかに異なり、数ピクセルずつ移動/サイズ変更されている可能性がある場合は、高い値を取得します。

(それが重要な場合、より具体的には:1つの画像がアイコンであり、他の画像がスクリーンショットのサブエリアであり、そのサブエリアが正確にアイコンであるかどうか知りたい。)

私はOpenCVを手元に持っていますが、まだ慣れていません。

これまでに考えた1つの可能性:両方の画像を10x10のセルに分割し、それらの100個のセルのそれぞれについて、カラーヒストグラムを比較します。次に、いくつかの構成されたしきい値を設定できます。取得した値がそのしきい値を超えている場合、それらは類似していると想定します。

まだ十分に機能していないので、まだ試していませんが、これで十分でしょう。画像はすでに(私の使用例では)かなり似ているので、かなり高いしきい値を使用できます。

これには他にも何十もの解決策があり、多かれ少なかれ機能すると思います(本当に非常に類似している場合にのみ類似性を検出したいので、タスク自体は非常に単純なので)。何を提案しますか?


画像から署名/指紋/ハッシュを取得することに関して、非常に関連する/類似した質問がいくつかあります。

また、フィンガープリントを取得するための機能を備えたこれらの実装に遭遇しました。

知覚的画像ハッシュに関するいくつかの議論:ここ


少し問題:オーディオ指紋を作成する方法はたくさんあります。MusicBrainzは、曲の指紋ベースの検索を提供するWebサービスであり、wikiに概要があります。現在、AcoustIDを使用してます。これは、正確な(またはほぼ完全な)一致を見つけるためのものです。同様の一致を見つけるには(または一部のスニペットまたはノイズが多い場合)、Echoprintを参照してください。関連するSOの質問はこちらです。したがって、これはオーディオについては解決されているようです。これらのソリューションはすべて非常に優れています。

ファジー検索全般についてのもう少し一般的な質問はこちらです。たとえば、局所性に敏感なハッシュ最近傍探索があります。


1
たぶん、画像のフィンガープリントが役立つでしょうか?stackoverflow.com/questions/596262/...
GWW

Earth Moverの距離(EMD)としても知られているWassersteinメトリックは、人々が知らないように見えるものですが、ここであなたが望むものをほとんど与えます。
mmgp 2013年


こんにちは、私は改良されたdHashを思いつきました-私はそれをIDHashと呼びました:github.com/Nakilon/dhash-vips
Nakilon

回答:


107

スクリーンショットまたはアイコンを変換できますか(拡大縮小、回転、傾斜...)?私の頭の上にはかなりの数の方法があります。

  • @carlosdcによって言及されている単純なユークリッド距離(変換された画像では機能せず、しきい値が必要です)。
  • (正規化)相互相関 -画像領域の比較に使用できる単純なメトリック。単純なユークリッド距離よりも堅牢ですが、変換された画像では機能しないため、再度しきい値が必要になります。
  • ヒストグラムの比較 -正規化されたヒストグラムを使用する場合、この方法は適切に機能し、アフィン変換の影響を受けません。問題は正しいしきい値を決定することです。また、色の変化(明るさ、コントラストなど)にも非常に敏感です。前の2つと組み合わせることができます。
  • MSER(Maximally Stable Extremal Regions)SURFSIFTなどの特徴的なポイント/エリアの検出器。これらは非常に堅牢なアルゴリズムであり、単純なタスクには複雑すぎる場合があります。良いことは、アイコンが1つしかない正確な領域を持っている必要がないことです。これらの検出器は、適切な一致を見つけるのに十分強力です。これらの方法の優れた評価は、このホワイトペーパーにあります。局所不変特徴検出器:調査

これらのほとんどはすでにOpenCVで実装されています-たとえばcvMatchTemplateメソッド(ヒストグラムマッチングを使用)を参照してください:http : //dasl.mem.drexel.edu/~noahKuntz/openCVTut6.html。特徴点/エリア検出器も利用可能です-OpenCV機能検出を参照してください。


1
拡大縮小またはわずかに移動できます。また、アイコンの背景も異なります。ヒストグラム比較を試しましたが、多くの誤検知がありました。ユークリッド距離も試してみましたが、誤検出が多すぎます(ただし、アイコンのアルファ値の処理を少し改善できるかもしれません)。私はそれをもう少し試します、そうでなければMSER、SURFまたはSIFTをチェックアウトします。
アルバート

1
別のアイデア-ソーベル演算子を適用した後に画像のヒストグラム比較を使用した場合、うまくいきませんか?それはエッジの類似性を比較するだけです。背景がどれほど「エッジの効いた」かによって、機能しない場合があります。
Karel Petranek 2010年

44

私は最近同じ問題に直面していますが、この問題(2つの画像を比較するための単純で高速なアルゴリズム)を一度に解決するために、img_hashモジュールをopencv_contribに提供しています。詳細は、このリンクから確認できます。

img_hashモジュールは、非常に使いやすい6つの画像ハッシュアルゴリズムを提供します。

コードの例

オリジンレナオリジンレナ

レナをぼかしレナをぼかし

レナのサイズ変更レナのサイズ変更

シフトレナシフトレナ

#include <opencv2/core.hpp>
#include <opencv2/core/ocl.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/img_hash.hpp>
#include <opencv2/imgproc.hpp>

#include <iostream>

void compute(cv::Ptr<cv::img_hash::ImgHashBase> algo)
{
    auto input = cv::imread("lena.png");
    cv::Mat similar_img;

    //detect similiar image after blur attack
    cv::GaussianBlur(input, similar_img, {7,7}, 2, 2);
    cv::imwrite("lena_blur.png", similar_img);
    cv::Mat hash_input, hash_similar;
    algo->compute(input, hash_input);
    algo->compute(similar_img, hash_similar);
    std::cout<<"gaussian blur attack : "<<
               algo->compare(hash_input, hash_similar)<<std::endl;

    //detect similar image after shift attack
    similar_img.setTo(0);
    input(cv::Rect(0,10, input.cols,input.rows-10)).
            copyTo(similar_img(cv::Rect(0,0,input.cols,input.rows-10)));
    cv::imwrite("lena_shift.png", similar_img);
    algo->compute(similar_img, hash_similar);
    std::cout<<"shift attack : "<<
               algo->compare(hash_input, hash_similar)<<std::endl;

    //detect similar image after resize
    cv::resize(input, similar_img, {120, 40});
    cv::imwrite("lena_resize.png", similar_img);
    algo->compute(similar_img, hash_similar);
    std::cout<<"resize attack : "<<
               algo->compare(hash_input, hash_similar)<<std::endl;
}

int main()
{
    using namespace cv::img_hash;

    //disable opencl acceleration may(or may not) boost up speed of img_hash
    cv::ocl::setUseOpenCL(false);

    //if the value after compare <= 8, that means the images
    //very similar to each other
    compute(ColorMomentHash::create());

    //there are other algorithms you can try out
    //every algorithms have their pros and cons
    compute(AverageHash::create());
    compute(PHash::create());
    compute(MarrHildrethHash::create());
    compute(RadialVarianceHash::create());
    //BlockMeanHash support mode 0 and mode 1, they associate to
    //mode 1 and mode 2 of PHash library
    compute(BlockMeanHash::create(0));
    compute(BlockMeanHash::create(1));
}

この場合、ColorMomentHashが最良の結果をもたらします

  • ガウスぼかし攻撃:0.567521
  • シフト攻撃:0.229728
  • リサイズ攻撃:0.229358

各アルゴリズムの長所と短所

さまざまな攻撃下でのパフォーマンス

img_hashのパフォーマンスも良い

PHashライブラリとの速度比較(ukbenchからの100画像) 計算パフォーマンス 比較性能

これらのアルゴリズムの推奨しきい値を知りたい場合は、この投稿(http://qtandopencv.blogspot.my/2016/06/introduction-to-image-hash-module-of.html)を確認してください。img_hashモジュール(速度とさまざまな攻撃を含む)のパフォーマンスの測定方法に興味がある場合は、このリンク(http://qtandopencv.blogspot.my/2016/06/speed-up-image-hashing-of)を確認してください。-opencvimghash.html)。


11

スクリーンショットにはアイコンのみが含まれていますか?その場合、2つの画像のL2距離で十分です。L2距離が機能しない場合、次のステップは、Lucas-Kanadeのような、シンプルで確立されたものを試すことです。OpenCVで利用できると確信しています。


サブエリアには、アイコンのみ(ランダムな背景を含む)または何か別のものが含まれています。どちらのケースか知りたい。わずかにずれたり、サイズが変更されたりする可能性があります。そのため、距離を(どのような基準で)見ればよいのかわかりませんでした。しかし、私は縮小版で試してみます。
アルバート


5

テンプレート(アイコン)をテスト領域に正確に配置できることが確実な場合は、古いピクセル合計の合計が機能します。

配置がほんの少しずれている場合は、ピクセルの差の合計を見つける前にcv :: GaussianBlurを使用して両方の画像をローパスすることができます。

アライメントの品質が潜在的に悪い場合は、方向付きヒストグラムのヒストグラムか、OpenCVの便利なキーポイント検出/記述子アルゴリズム(SIFTSURFなど)のいずれかをお勧めします。


4

同一の画像を照合する場合-L2距離のコード

// Compare two images by getting the L2 error (square-root of sum of squared error).
double getSimilarity( const Mat A, const Mat B ) {
if ( A.rows > 0 && A.rows == B.rows && A.cols > 0 && A.cols == B.cols ) {
    // Calculate the L2 relative error between images.
    double errorL2 = norm( A, B, CV_L2 );
    // Convert to a reasonable scale, since L2 error is summed across all pixels of the image.
    double similarity = errorL2 / (double)( A.rows * A.cols );
    return similarity;
}
else {
    //Images have a different size
    return 100000000.0;  // Return a bad value
}

速い。しかし、その他の照明/視点の変化に対してロバストではない ソース


2

画像の類似性を比較する場合は、OpenCVを使用することをお勧めします。OpenCVでは、機能のマッチングとテンプレートのマッチングはほとんどありません。特徴照合には、SURF、SIFT、FASTなどの検出器があります。これを使用して、画像を検出、説明し、照合することができます。その後、特定のインデックスを使用して、2つの画像間の一致数を見つけることができます。


1
「その後、特定のインデックスを使用して、2つの画像の一致数を見つけることができます。」同じオブジェクトを「含む」という2つの画像の最小一致数はいくつですか。
–InêsMartins、2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.