2012-01-13 2 views
4

Je sais qu'il y a déjà plusieurs questions avec le même sujet posées ici, mais je n'ai trouvé aucune aide.Détection OpenCV Surf and Outliers

Donc je veux comparer 2 images afin de voir à quel point elles sont similaires et j'utilise la démo find_obj.cpp bien connue pour extraire des descripteurs de surf et ensuite pour la correspondance j'utilise les flannFindPairs. Mais comme vous le savez, cette méthode ne supprime pas les valeurs aberrantes et j'aimerais connaître le nombre de correspondances vraies positives, donc je peux comprendre à quel point ces deux images sont similaires.

J'ai déjà vu cette question: Detecting outliers in SURF or SIFT algorithm with OpenCV et le gars suggère d'utiliser findFundamentalMat mais une fois que vous obtenez la matrice fondamentale, comment puis-je obtenir le nombre de valeurs aberrantes/vrai positif de cette matrice? Je vous remercie.

Répondre

5

Voici un extrait de l'échantillon descriptor_extractor_matcher.cpp disponible à partir OpenCV:

if(!isWarpPerspective && ransacReprojThreshold >= 0) 
    { 
     cout << "< Computing homography (RANSAC)..." << endl; 
     vector<Point2f> points1; KeyPoint::convert(keypoints1, points1, queryIdxs); 
     vector<Point2f> points2; KeyPoint::convert(keypoints2, points2, trainIdxs); 
     H12 = findHomography(Mat(points1), Mat(points2), CV_RANSAC, ransacReprojThreshold); 
     cout << ">" << endl; 
    } 

    Mat drawImg; 
    if(!H12.empty()) // filter outliers 
    { 
     vector<char> matchesMask(filteredMatches.size(), 0); 
     vector<Point2f> points1; KeyPoint::convert(keypoints1, points1, queryIdxs); 
     vector<Point2f> points2; KeyPoint::convert(keypoints2, points2, trainIdxs); 
     Mat points1t; perspectiveTransform(Mat(points1), points1t, H12); 

     double maxInlierDist = ransacReprojThreshold < 0 ? 3 : ransacReprojThreshold; 
     for(size_t i1 = 0; i1 < points1.size(); i1++) 
     { 
      if(norm(points2[i1] - points1t.at<Point2f>((int)i1,0)) <= maxInlierDist) // inlier 
       matchesMask[i1] = 1; 
     } 
     // draw inliers 
     drawMatches(img1, keypoints1, img2, keypoints2, filteredMatches, drawImg, CV_RGB(0, 255, 0), CV_RGB(0, 0, 255), matchesMask 
#if DRAW_RICH_KEYPOINTS_MODE 
        , DrawMatchesFlags::DRAW_RICH_KEYPOINTS 
#endif 
        ); 

#if DRAW_OUTLIERS_MODE 
     // draw outliers 
     for(size_t i1 = 0; i1 < matchesMask.size(); i1++) 
      matchesMask[i1] = !matchesMask[i1]; 
     drawMatches(img1, keypoints1, img2, keypoints2, filteredMatches, drawImg, CV_RGB(0, 0, 255), CV_RGB(255, 0, 0), matchesMask, 
        DrawMatchesFlags::DRAW_OVER_OUTIMG | DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); 
#endif 
    } 
    else 
     drawMatches(img1, keypoints1, img2, keypoints2, filteredMatches, drawImg); 

Les lignes principales pour le filtrage sont effectuées ici:

if(norm(points2[i1] - points1t.at<Point2f>((int)i1,0)) <= maxInlierDist) // inlier 
       matchesMask[i1] = 1; 

qui mesure la distance norme L2 entre la points (soit 3 pixels si rien n'a été spécifié, soit erreur de reprojection du nombre de pixels défini par l'utilisateur).

Espérons que ça aide!

+0

merci pour votre réponse ... Je ne peux pas utiliser directement ce code dans le find_obj.cpp puisque cela est codé en C et cet extrait est C++. Cependant, je l'ai essayé dans la démo SURFFlannMatcher.cpp et cela ne donne pas vraiment de bons résultats. Par exemple, si j'obtiens 2 images du même objet, même scène, c'est-à-dire des images presque identiques mais des résolutions différentes, la fonction findHomography ne trouvera que des valeurs aberrantes et pas d'inliers ... c'est très étrange. – user1148222

1

Vous pouvez utiliser la taille du vecteur nommé "ptpairs" afin de décider à quel point les images sont similaires. ce vecteur contient les points-clés correspondants, donc sa taille/2 est le nombre de correspondances. Je pense que vous pouvez utiliser la taille de ptpairs divisé par le nombre total de keypoints afin de définir un seuil approprié. cela vous donnera probablement une estimation de la similiarty entre eux.