Use of drawMatches (OpenCV3)

asked 2014-10-24 13:43:18 -0600

Doombot gravatar image

updated 2014-10-27 07:44:45 -0600

TL;DR: How to match the BRISK descriptors and show the match with drawMatches in OpenCV3?

===

According to the doc and to the definition in features2d.hpp, the function "drawMatches" parameter "matches1to2" has to possible types:

  • const vector< DMatch >& matches1to2 ....................// --in CV_EXPORTS_W void drawMatches
  • const vector< vector< DMatch >>& matches1to2 .....// --in CV_EXPORTS_AS (drawMatchesKnn)

Now, I am using FLANN to match some keypoint-descriptor pairs:

cv::Mat results;
cv::Mat dists;
vector<DMatch> matches;

int k=2; // find the 2 nearest neighbors
if(objectDescriptors.type()==CV_8U)
{
    // Create Flann LSH index
    cv::flann::Index flannIndex(sceneDescriptors, 
                   cv::flann::LshIndexParams(12, 20, 2), cvflann::FLANN_DIST_HAMMING);

    // search (nearest neighbor)
    flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
}

So with the data written in "Mat results". I have successfully printed on the console a 2x112 array "results" containing seemingly plausible coordinates for matching keypoints (I think). Sadly (for me), the authors of the tutorial are then using Qt to display the matches, and I don't (can't).

In other sample code (third party project) I have come across, a different method is used:

std::vector<std::vector<cv::DMatch> > matches;
int k=2;
cv::BFMatcher matcher(cv::NORM_HAMMING);
matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k);

So they are not matching with FLANN but doing Hammming distance stuff. BTW this is not working for me, "matcher" is underlined and the error is: "object of abstract class type "cv::BFMatcher" is not allowed: pure virtual function "cv::DescriptorMatcher::clone" has no overrider"

Then, in others:

  FlannBasedMatcher matcher;
  std::vector< DMatch > matches;
  matcher.match( descriptors_object, descriptors_scene, matches );

  double max_dist = 0; double min_dist = 100;

  //-- Quick calculation of max and min distances between keypoints
  for( int i = 0; i < descriptors_object.rows; i++ )
  { double dist = matches[i].distance;
    if( dist < min_dist ) min_dist = dist;
    if( dist > max_dist ) max_dist = dist;
  }

  //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
  std::vector< DMatch > good_matches;

  for( int i = 0; i < descriptors_object.rows; i++ )
  { if( matches[i].distance < 3*min_dist )
     { good_matches.push_back( matches[i]); }
  }

  Mat img_matches;
  drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
               good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
               vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

This is not working, the "FlannBasedMatcher matcher" displays the same error about pure virtual function (I am sure this error is obvious to an experienced programmer, I confess) .

But in the last two methods their "matched keypoint" are in a vector of DMatch format. Now, my results are in the cv::Mat format but I need to have them in the vector<dmatch> format in order to be able to use drawMatches. Well I have tried to plug a Mat object instead of a vector<dmatch> and it doesn't work. ;)

Actually, I know that I have been asking a couple of question lately but in the end that is what I am trying to solve. When I'll confirm "visually" that my matching program using BRISK (other descriptors will be tested later) is working, I'll have the leisure of delving more deeply into the code and will be ... (more)

edit retag flag offensive close merge delete

Comments

1

main source of your confusion seems to be, that matcher.match() takes a single vector<DMatch>, while the matcher.knnMatch() version uses a vector<vector<DMatch>> (k vector<DMatch>)

berak gravatar imageberak ( 2014-10-28 05:16:04 -0600 )edit