web-dev-qa-db-ja.com

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

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

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

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

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

私はまだそれをどれほどうまくやっているか試していませんが、それで十分だと思います。画像はすでにかなり似ているので(私の使用例では)、かなり高いしきい値を使用できます。

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


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

また、指紋を取得する機能を備えたこれらの実装に出くわしました。

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


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

一般的なファジー検索に関するやや一般的な質問は here です。例えば。 局所性に敏感なハッシュ最近傍検索 があります。

177
Albert

スクリーンショットまたはアイコンを変換できますか(スケーリング、回転、傾斜...)?私の頭の上には、おそらくあなたを助けることができるかなりの方法があります:

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

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

99
Karel Petranek

私は最近同じ問題に直面し、この問題を解決するために(2つの画像を比較するためのシンプルで高速なアルゴリズム)、すべてのために、opencv_contribに img_hash module を提供します。詳細は このリンク

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

コード例

Origin lena Origin lena

blur lena ブレナー

resize lena レナのサイズ変更

shift lena shift lena

#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

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

Performance under different attacks

Img_hashのパフォーマンスも良好です

PHashライブラリとの速度比較(ukbenchからの100枚の画像)compute performancecomparison performance

これらのアルゴリズムの推奨しきい値を知りたい場合は、この投稿を確認してください( 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 )。

36
StereoMatching

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

10
carlosdc

2つの写真の類似性に関するインデックスを取得する場合は、メトリックからSSIMインデックスをお勧めします。人間の目とより一致しています。それについての記事は次のとおりです: Structural Similarity Index

OpenCVにも実装されており、GPUで高速化できます: OpenCV SSIM with GPU

5
ramez

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

アライメントがほんの少しだけずれている場合は、ピクセルの差の合計を見つける前に cv :: GaussianBlur で両方の画像をローパスできます。

アライメントの品質が潜在的に低い場合、 Histogram of Oriented Gradients またはOpenCVの便利なキーポイント検出/記述子アルゴリズムのいずれか( SIFT または SURF )。

4
rcv

同一の画像をマッチングする場合-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
}

速い。しかし、照明/視点などの変化に対して堅牢ではありません。 ソース

3
Kiran

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

2
Hua Er Lim