2013-02-13 30 views
19

[編集] 私は画像比較のためのコードを考案しました。一致する部分にはまだ欠陥があり、私はいくつかのassitanceが大好きです。このプロジェクトは - GitHubにあります。AndroidでのOpenCV画像比較

私は、これら二つの画像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 
} 

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

enter image description hereenter image description here

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

EDIT

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

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

私はこれを試してみたが、if条件を満たしことはありません。私はいくつかの違いがあると仮定していますが、Scalarにはcompareの機能はありません。私は何をしますか?

EDIT

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); 
    } 

この方法は、再び欠陥があります。イメージを適切な精度で比較するのに使用できますが、イメージのサイズが異なると失敗します。画像は、異なるサイズのものであり、Iは、スカラー値を印刷するとき

私はこれを取得:

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

もののあまり第二及び第三の数字の間のばらつきが同じのときに画像に比べて非常に大きいですサイズを比較する。しかし、最初の数字が最も変化します。

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

[EDIT]

私はhere見つけたコードを使用しています。

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

  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)); 

私は、nullポインタ例外を受け取りますcuzを私は明らかにnullに変数keypointslogoKeypointsを初期化することはできません。どのように初期化するのですか?

+0

このOpenCVチュートリアルでは、このトピックに関するいくつかの情報を提供しています。 http://goo.gl/gwN6e。 – harism

+2

try-catchはif-elseと同じではありません!例外がスローされた場合(catchブロック)、何かが完全に間違っていました! – sschrass

+0

@SatelliteSD - 私はそれを知っています。だからこそ私はもっと良い方法があるかどうか尋ねています。 –

答えて

25

これは簡単な質問ではなく、あなたが従うことのできる概念が異なることを理解しておく必要があります。ソースコードのない2つのソリューションだけを指摘します。

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

私はこれが役に立ちそうです。ご質問がある場合はお尋ねください。

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

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

[UPDATE-2] ここでは、SIFT検出器との一例であり、SIFT -Descriptorデフォルトパラメータを使用します。 RANSAC-ホモグラフィの閾値は65、再投影誤差(ε)は10、相互検証が可能です。あなたは一致したものを数えようとすることができます。 Inliner-Outlier-Ratioが高すぎると、このペアが重複しているとみなすことができます。 Matching img1 and img2 using SIFT-detector and SIFT-descriptor 例:これらの画像は、IMG2のIMG1とIMG2で180のキーポイントを生成します。一致した記述子は163であり、そのうちの3つだけが異常値である。これは、これらの画像が重複する可能性があるということだけを意味する本当に良い比率を与えます。

[UPDATE-3] MatOfKeypointsを初期化できる理由がわかりません。 I've read the APIとパブリックコンストラクタがあります。 AND:分析したい画像のマットを使用することができます。これはすごく素敵。 =)あなたはSURFのためのユークリッド距離を必要とするか、またはSIFTます原因BRUTEFORCE_SL2 Descriptor-Matcherを使用マッチングのための

MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage); 

+0

チュートリアルへのリンクを追加できますか? –

+0

私はいくつかの追加の材料を追加しました。 –

+0

私は自分の質問を編集しました。 –

1

cv2.absDiffを使用して、ピクチャとcv2.sumElemsの違いを計算して、すべてのピクセルの差の合計を取得します。

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

+0

あなたは解明できますか?私はabsDiffのしきい値を設定する必要があります。だから、それは欠陥がある。あるいは、あなたは最も安全なしきい値の値を教えてくれるでしょうか? –

+0

最初に、sumelemsはPythonのみであると思われるので、申し訳ありませんが、cv.sumを使用する必要があります。次に、合計からの戻り値のしきい値が必要です。合計とあなたのしきい値の戻り値に基づいて真または偽を返すメソッドでそれをラップすることができます。 – sschrass

+0

良いしきい値は何ですか? –

0

次のコード試すことができます:関数は、2つの画像を比較し、画像間のDIS類似性が存在する場合、その後、その後、特定の行列値は255と他のすべての値になります比較ここでは、コード内

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 
} 

をゼロになります。次に、ゼロ以外の値の数を数えて、イメージが等しいかどうかを判断できます。これは、正確に同じ画像に対してのみ機能します。

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

この回答をお寄せください。