2014-11-11 10 views
6

Ich versuche, 2 entgegengesetzte Bilder mit OpenCV DescriptorMatcher ohne Glück zu entsprechen. Die Bilder sind: http://i61.tinypic.com/28whu0g.jpg (von links nach rechts) und http://i61.tinypic.com/x35vte.jpg (von rechts nach links).OpenCV - Java - Keine Übereinstimmung mit 2 gegenüberliegenden Bildern mit DescriptorMatcher

Mein Code ist ziemlich wie viele Beispiele, die ich in StackOverflow und im Web sah, aber immer noch bekomme ich keine Übereinstimmung.

 String firstImageSourcePath = "RTL_IMAGE_PATH"; 
     String secondImageSourcePath = "LTR_IMAGE_PATH"; 

     Mat firstImageSrcImgMat = Highgui.imread(firstImageSourcePath); 
     Mat secondImageSrcImgMat = Highgui.imread(firstImageSourcePath); 

     if (firstImageSrcImgMat.empty() || secondImageSrcImgMat.empty()) { 
      System.out.println("Failed to load images"); 
      return; 
     } 

     System.out.println("Loaded image at " + firstImageSourcePath + " and " + secondImageSourcePath); 

     FeatureDetector featureDetector = FeatureDetector.create(FeatureDetector.BRISK); 

     MatOfKeyPoint firstImgMatOfKeyPoints = new MatOfKeyPoint(); 
     MatOfKeyPoint secondImgMatOfKeyPoints = new MatOfKeyPoint(); 

     featureDetector.detect(firstImageSrcImgMat, firstImgMatOfKeyPoints); 
     featureDetector.detect(secondImageSrcImgMat, secondImgMatOfKeyPoints); 

     System.out.println("Detected " + firstImgMatOfKeyPoints.size() + " and " + secondImgMatOfKeyPoints + " blobs in the images"); 

     List<KeyPoint> firstImgKeyPoints = firstImgMatOfKeyPoints.toList(); 
     List<KeyPoint> secondImgKeyPoints = secondImgMatOfKeyPoints.toList(); 

     System.out.println("First Image key points: " + firstImgKeyPoints); 
     System.out.println("Second Image key points: " + secondImgKeyPoints); 

     Mat firstImgDescriptors = new Mat(); 
     Mat secondImgDescriptors = new Mat(); 

     DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRISK); 
     extractor.compute(firstImageSrcImgMat, firstImgMatOfKeyPoints, firstImgDescriptors); 
     extractor.compute(secondImageSrcImgMat, secondImgMatOfKeyPoints, secondImgDescriptors); 

     System.out.println("descriptorsA.size() : " + firstImgDescriptors.size()); 
     System.out.println("descriptorsB.size() : " + secondImgDescriptors.size()); 

     MatOfDMatch matches = new MatOfDMatch(); 

     DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMINGLUT); // BRUTEFORCE_HAMMINGLUT 
     matcher.match(firstImgDescriptors, secondImgDescriptors, matches); 

     System.out.println("matches.size() : " + matches.size()); 
     System.out.println("matches : " + matches); 

     MatOfDMatch matchesFiltered = new MatOfDMatch(); 

     List<DMatch> matchesList = matches.toList(); 
     List<DMatch> bestMatches = new ArrayList<DMatch>(); 

     Double max_dist = 0.0; 
     Double min_dist = 100.0; 

     for (int i = 0; i < matchesList.size(); i++) { 
      Double dist = (double) matchesList.get(i).distance; 

      if (dist > 0) 
       System.out.println("dist : " + dist); 

      if (dist < min_dist && dist != 0) { 
       min_dist = dist; 
      } 

      if (dist > max_dist) { 
       max_dist = dist; 
      } 

     } 

     System.out.println("max_dist : " + max_dist); 
     System.out.println("min_dist : " + min_dist); 

     if (min_dist > 50) { 
      System.out.println("No match found, min_dist under minimum value"); 
      return; 
     } 

     double threshold = 3 * min_dist; 
     double threshold2 = 2 * min_dist; 

     if (threshold > 75) { 
      threshold = 75; 
     } else if (threshold2 >= max_dist) { 
      threshold = min_dist * 1.1; 
     } else if (threshold >= max_dist) { 
      threshold = threshold2 * 1.4; 
     } 

     System.out.println("Threshold : " + threshold); 

     for (int i = 0; i < matchesList.size(); i++) { 
      Double dist = (double) matchesList.get(i).distance; 

      if (dist < threshold) { 
       bestMatches.add(matches.toList().get(i)); 
       System.out.println(String.format(i + " best match added : %s", dist)); 
      } 
     } 

     matchesFiltered.fromList(bestMatches); 

     System.out.println("matchesFiltered.size() : " + matchesFiltered.size()); 

     if (matchesFiltered.rows() >= 1) { 
      System.out.println("match found"); 
     } else { 
      System.out.println("match not found"); 
     } 

ein Hinweis, was mache ich falsch?

+0

Wie viele keypoints Sie haben und wie viele Deskriptoren? Kannst du sie dir vorstellen? Bist du sicher, dass dein Thresholding-Schema Spiele nicht zu aggressiv killt? Und bedenken Sie, dass es in einer perfekten Welt keine Übereinstimmungen geben sollte, aus dem einfachen Grund, dass es einen Paritätsunterschied (LTR vs. RTL) gibt und Deskriptoren solche Unterschiede unterscheiden sollen. Können Sie versuchen, zwischen dem LTR und dem Horizontal-Flip des RTL zu suchen? –

+0

Ich muss sagen, dass ich nicht wirklich verstanden habe, was Sie gefragt haben :(ABER, ich habe versucht, zwischen zwei identischen Bildern (gleiche Datei) zu finden und trotzdem habe ich keine Übereinstimmung. – Avisho

Antwort

5

Als @ Iwillnotexist-Idonotexist angegeben das erste Problem ist die Schwelle, die Sie anwenden. Versuchen Sie, einen Schwellenwert zu verwenden, der nicht vom Abstand zwischen Deskriptoren abhängt, der nicht gut funktioniert, da einige der Deskriptoren viel diskriminierender sind als andere. Ich denke, das wird dir bessere Ergebnisse bringen. Ich empfehle Ihnen, den von D. Lowe in der SIFT-Arbeit vorgeschlagenen Ratio-Test zu verwenden. Bitte werfen Sie einen Blick auf Abschnitt 7.1: http://cs.ubc.ca/~lowe/papers/ijcv04.pdf

Das zweite Problem ist, dass Sie BRISK verwenden, um Funktionen in Ihren Bildern zu erkennen. Diese OpenCV-Implementierung hat Fehler (Sie können hier überprüfen: http://code.opencv.org/issues/3976) versuchen Sie also einen anderen FeatureDetector wie FAST, ORB, etc ... (Deskriptor ist in Ordnung, so können Sie es weiter verwenden)

Ich endete in Ihren Bildern testen und ich verwaltet (keypoints ohne Spiel -> gelb)

BRISK Detektor und Beschreiber: einige Ergebnisse mit verschiedenen Detektoren/Deskriptoren zu bekommen BRISK/BRISK

  • linkes Bild keypoints: 74
  • rechtes Bild keypoints: 86
  • Spiele: 3 (Selbst mit gebrochenem Detektor Ich habe Streichhölzer)

ORB Detektor mit BRISK als Beschreiber: ORB/BRISK

  • linkes Bild keypoints: 499
  • Bild rechts keeppoints: 500
  • entspricht: 26

ORB-Detektor und Beschreiber using ORB

  • linkes Bild keypoints: 841
  • rechtes Bild keypoints: 907
  • Spiele: 43

Alle Ergebnisse wurden unter Verwendung der Verhältnistest, um falsche Übereinstimmungen zu entfernen. Ich hoffe, das hilft!

EDIT:

BruteForceMatcher<Hamming> matcher; 
vector< vector<DMatch> > matches; 
vector <DMatch> goodMatches; 
matcher.knnMatch(imgDescriptors1, imgDescriptors2, matches, 2); 
// Ratio Test 
for (unsigned int matchIdx = 0; matchIdx < matches.size(); ++matchIdx) 
{ 
    const float ratio = 0.8; // As in Lowe's paper (can be tuned) 
    if (matches[matchIdx][0].distance < ratio * matches[matchIdx][1].distance) 
    { 
     goodMatches.push_back(matches[matchIdx][0]); 
    } 
} 
+0

Danke zedv! Ich habe versucht, ein Codebeispiel zu suchen für ratio match, aber ohne glück ... kannst du mich bitte an einen verweisen? – Avisho

+0

Kannst du deinen C++ code hier angeben? sorry, aber ich weiß nicht einmal welche klassen zu verwenden ... – Avisho

+0

Ich habe keinen code geschrieben weil ich nicht java benutze .. Wie auch immer ich denke, es wird einfach sein, eine Umwandlung von meinem C++ Code zu machen. Ich aktualisierte meine Antwort mit dem Code. Hoffe das hilft – zedv

2

Java-Version ist:

DescriptorMatcher descriptorMatcher; 
descriptorMatcher=DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); 
MatOfDMatch good_matches; 
good_matches = new MatOfDMatch(); 

LinkedList<MatOfDMatch> dmatchesListOfMat = new LinkedList<>(); 
descriptorMatcher.knnMatch(imgDescriptors1, imgDescriptors2, dmatchesListOfMat, 2); 

LinkedList<DMatch> good_matchesList = new LinkedList<>(); 
for (int matchIndx = 0; matchIndx < dmatchesListOfMat.size() ; matchIndx++) { 
    double ratio = 0.8; 
    if (dmatchesListOfMat.get(matchIndx).toArray()[0].distance < ratio * dmatchesListOfMat.get(matchIndx).toArray()[1].distance) { 
     good_matchesList.addLast(dmatchesListOfMat.get(matchIndx).toArray()[0]); 
    } 
} 
good_matches.fromList(good_matchesList); 
Verwandte Themen