20

[編集] 画像比較用のコードを考案しました。マッチング部分はまだ少し欠陥があり、私はいくつかの支援が大好きです。プロジェクトは--GitHubにあります。

私はこれらの2つの画像Img1Img2を持っています:

ここに画像の説明を入力してください ここに画像の説明を入力してください

openCVで次のコマンドを使用すると

Mat img1 = Highgui.imread("mnt/sdcard/IMG-20121228.jpg");
Mat img2 = Highgui.imread("mnt/sdcard/IMG-20121228-1.jpg");

try{
    double l2_norm = Core.norm( img1, img2 );
    tv.setText(l2_norm+"");
} catch(Exception e) {
    //image is not a duplicate
}

l2_normのdouble値を取得します。このdouble値は、重複する画像ペアによって異なります。ただし、画像が異なる場合は、例外がスローされます。これは、重複する画像を識別する方法ですか?それとももっと良い方法がありますか?私は広範囲にグーグルで検索しましたが、本当に説得力のある答えを見つけることができませんでした。true2つの画像を比較し、画像のブール値またはfalse画像に応じてブール値を取得する方法について、コードと説明をお願いします。

編集

Scalar blah= Core.sumElems(img2);
    Scalar blah1=Core.sumElems(img1);

    if(blah.equals(blah1))
    {
        tv.setText("same image");
    }
    }

私はこれを試しましたが、if条件が満たされることはありません。いくつかの違いがあると思いますが、のcompare関数はありませんScalar。私は何をしますか?

編集

try{
    Scalar blah= Core.sumElems(img2);
    Scalar blah1=Core.sumElems(img1);
    String b=blah.toString();
    String b1=blah1.toString();
    System.out.println(b+" "+b1);
    double comp=b.compareTo(b1);
    tv.setText(""+comp);
    }

この方法にも欠陥があります。適切な精度で画像を比較するために使用できますが、画像のサイズが異なると失敗します。

画像のサイズが異なり、スカラー値を印刷すると、次のようになります。

[9768383.0, 1.0052889E7, 1.0381814E7, 0.0] [1.5897384E7, 1.6322252E7, 1.690251E7, 0.0]

同じサイズの画像を比較した場合と比べると、それほど大きくはありませんが、2番目と3番目の数値のばらつきはそれほど大きくありません。ただし、最初の番号は最も大きな変化を被ります。

2つの画像の内容を比較するための最良の最速の方法は何でしょうか?

[編集]

ここで見つけたコードを使用しています。

私が理解できないのは、MatOfKeyPoint変数keypointsとを初期化する方法logoKeypointsです。これが私のコードスニペットです:

           FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF);
        //FeatureDetector detector = FeatureDetector.create(FeatureDetector.FAST);
        //Imgproc.cvtColor(img1, img1, Imgproc.COLOR_RGBA2RGB);
        //Imgproc.cvtColor(img2, img2, Imgproc.COLOR_RGBA2RGB);

        DescriptorExtractor SurfExtractor = DescriptorExtractor
        .create(DescriptorExtractor.SURF);


        //extract keypoints
        MatOfKeyPoint keypoints, logoKeypoints;
        long time= System.currentTimeMillis();
        detector.detect(img1, keypoints);
        Log.d("LOG!", "number of query Keypoints= " + keypoints.size());
        detector.detect(img2, logoKeypoints);
        Log.d("LOG!", "number of logo Keypoints= " + logoKeypoints.size());
        Log.d("LOG!", "keypoint calculation time elapsed" + (System.currentTimeMillis() -time));

        //Descript keypoints
        long time2 = System.currentTimeMillis();
        Mat descriptors = new Mat();
        Mat logoDescriptors = new Mat();
        Log.d("LOG!", "logo type" + img2.type() + "  intype" + img1.type());
        SurfExtractor.compute(img1, keypoints, descriptors);
        SurfExtractor.compute(img2, logoKeypoints, logoDescriptors);
        Log.d("LOG!", "Description time elapsed" + (System.currentTimeMillis()- time2));

私は明らかに変数keypointsを初期化することができず、 logoKeypointsnullcuzにするとnullポインター例外を受け取ります。それらを初期化するにはどうすればよいですか?

4

3 に答える 3

30

これは単純な質問ではなく、従うことができるさまざまな概念があることを理解する必要があります。ソースコードなしの2つの解決策だけを指摘します。

  1. ヒストグラムの比較:両方の画像をグレースケールに変換して、[0、...、255]の範囲のヒストグラムを作成できます。すべてのピクセル値がカウントされます。次に、両方のヒストグラムを比較に使用します。ピクセル強度の分布がいくつかのしきい値(おそらくすべてのピクセルの90%)以上である場合、この画像は重複していると見なすことができます。しかし、これは最も単純な解決策の1つであり、画像の分布が等しい場合は安定しません。
  2. Interest-Point-Detectors / -Descriptors:SIFT/SURF画像検出器と記述子を見てください。検出器は、画像内の強度の一意のキーポイントを決定しようとします。記述子はこの位置I(x、y)で計算されます。ブルートフォースアプローチとユークリッド距離を持つ通常のマッチャーは、記述子を使用してこれらの画像をマッチングできます。画像が重複している場合、特定の一致率は非常に高くなるはずです。このソリューションは実装に適していて、このトピックに関する十分なチュートリアルがある可能性があります。

これがお役に立てば幸いです。ご不明な点がございましたらお問い合わせください。

[UPDATE-1] C ++チュートリアル: http://morf.lv/modules.php?name = tutorials&lasit = 2#.UR- ewKU3vCk

一部のJavaCVチュートリアル:http ://code.google.com/p/javacv/w/list

[UPDATE-2] これは、デフォルトのパラメーターを使用したSIFT-DetectorとSIFT-Descriptorの例です。RANSAC-ホモグラフィのしきい値は65、再投影エラー(イプシロン)は10、交差検定が有効です。一致したものを数えることができます。Inliner-Outlier-Ratioが高すぎる場合、このペアが重複していると見なされる可能性があります。 SIFT検出器とSIFT記述子を使用したimg1とimg2のマッチング 例:これらの画像は、IMG1で180個のキーポイントを生成し、IMG2で198個のキーポイントを生成します。一致した記述子は163であり、そのうち3つだけが外れ値です。したがって、これは本当に良い比率を与えます。これは、これらの画像が重複している可能性があることを意味するだけです。

[UPDATE-3] MatOfKeypointsを初期化できる理由がわかりません。APIを読みましたが、パブリックコンストラクターがあります。AND:分析したい画像のマットを使用できます。これはすごく素敵。=)

MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage);

マッチングには、BRUTEFORCE_SL2記述子-マッチャーを使用します。これにより、SURFまたはSIFTのユークリッド距離が必要になります。

于 2013-02-16T10:37:51.903 に答える
1

cv2.absDiff写真間の差を計算し、cv2.sumElemsすべてのピクセルの差の合計を取得するために使用します。

次に、2つの画像が類似しているかどうかを判断するためのしきい値を考案します。

于 2013-02-13T13:09:19.173 に答える
0

次のコードを試すことができます。

Mat img1 = Highgui.imread("mnt/sdcard/IMG-20121228.jpg");
Mat img2 = Highgui.imread("mnt/sdcard/IMG-20121228-1.jpg");
Mat result = new Mat();

Core.compare(img1,img2,result,Core.CMP_NE);

int val = Core.countNonZero(result);

if(val == 0) {
    //Duplicate Image
} else {
    //Different Image
}

ここで、コード比較関数は2つの画像を比較し、画像間に非類似性がある場合、特定の行列値は255になり、他のすべての値はゼロになります。次に、ゼロ以外の値の数を数えて、画像が等しいかどうかを判断できます。これは、まったく同じ画像に対してのみ機能します。

光の影響を無視して画像を比較したい場合は、最初にエッジ画像を生成し(OpenCVのcanny関数を使用)、次に画像を比較することをお勧めします。

この答えがお役に立てば幸いです!!

于 2013-02-21T14:04:25.947 に答える