FLANN matcher-OPENCV 3-min max disatance

asked 2015-10-12 00:00:27 -0500

I have some code which uses the Flann matcher and ORB detector to find features between two images of a person. I'm using opencv 3 on ubuntu. I have a few doubts.. The Code is as follows:

      #include <iostream>
#include </home/sruthi/opencv/include/opencv2/opencv.hpp>

using namespace cv;

//void readme();

/** @function main */
int main(int argc, char** argv)
{
   if( argc != 3 )
  { //readme(); 
     return -1; }

  Mat img_object = imread( argv[1], IMREAD_GRAYSCALE );
  Mat img_scene = imread( argv[2], IMREAD_GRAYSCALE );


    if (!img_object.data || !img_scene.data)
    {
        std::cout << " --(!) Error reading images " << std::endl; return -1;
    }

    //-- Step 1: Detect the keypoints using ORB Detector
    Ptr<FeatureDetector> detector = ORB::create();

    std::vector<KeyPoint> keypoints_object, keypoints_scene;

    detector->detect(img_object, keypoints_object);
    detector->detect(img_scene, keypoints_scene);

    //-- Step 2: Calculate descriptors (feature vectors)
    Ptr<DescriptorExtractor> extractor = ORB::create();

    Mat descriptors_object, descriptors_scene;

    extractor->compute(img_object, keypoints_object, descriptors_object);
    extractor->compute(img_scene, keypoints_scene, descriptors_scene);

    descriptors_object.convertTo(descriptors_object,CV_32F);
    descriptors_scene.convertTo(descriptors_scene,CV_32F);


    //-- Step 3: Matching descriptor vectors using FLANN matcher
    Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
    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;
    }

    printf("-- Max dist : %f \n", max_dist);
    printf("-- Min dist : %f \n", min_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), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

    //-- Localize the object
    std::vector<Point2f> obj;
    std::vector<Point2f> scene;
    for (int i = 0; i < good_matches.size(); i++)
    {
        //-- Get the keypoints from the good matches
        obj.push_back(keypoints_object[good_matches[i].queryIdx].pt);
        scene.push_back(keypoints_scene[good_matches[i].trainIdx].pt);
    }


    //-- Show detected matches
  imshow( "Good Matches", img_matches );

  for( int i = 0; i < (int)good_matches.size(); i++ )
  { printf( "-- Good Match [%d] Keypoint 1: %d  -- Keypoint 2: %d  \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); }

    waitKey(0);
    return 0;


}
  1. double max_dist = 0; double min_dist = 100; Why do we declare these distances as 0 and 100 respectively? As output I get Max dist : 488.559113 Min dist : 100.000000. It seems wrong.

    1. if (matches[i].distance < 3 * min_dist) { good_matches.push_back(matches[i]); } Why am I not able to change 3min_dist to 2min_dist? I get no matches if I do it.

    2. Is it compulsory that there have to parallel lines as shown in the official documentation. I dont get parallel lines. I'm not able to post a screenshot.

edit retag flag offensive close merge delete

Comments

ORB descriptors are binary, you must not use the Flann matcher, but BFMatcher(HAMMING). (also, the float conversion has to go).

it seems, you modified an example, that was using SIFT or SURF originally. the 0..100 values are heuristcal, you have to find your own for a different situation

berak gravatar imageberak ( 2015-10-12 00:28:08 -0500 )edit

@berak When I use surf.. I'm getting an error in spite of using the opencv 3 API.

sruti_kalapatapu gravatar imagesruti_kalapatapu ( 2015-10-12 04:00:46 -0500 )edit

I get the following error:

    /home/sruthi/c++/flann_surf.cpp:25:37: error: ‘SURF’ has not been declared
     Ptr<FeatureDetector> detector = SURF::create();
                                     ^
/home/sruthi/c++/flann_surf.cpp:34:42: error: ‘SURF’ has not been declared
     Ptr<DescriptorExtractor> extractor = SURF::create();
sruti_kalapatapu gravatar imagesruti_kalapatapu ( 2015-10-12 04:10:58 -0500 )edit
1

you need to build with opencv_contrib to get SIFT/SURF, and then it's xfeatures2d::SURF::create();

berak gravatar imageberak ( 2015-10-12 05:47:11 -0500 )edit

@berak is it okay to have the contrib folder outside the opencv source folder?

sruti_kalapatapu gravatar imagesruti_kalapatapu ( 2015-10-12 23:51:58 -0500 )edit

sure, just put it next to the opencv folder, and point OPENCV_EXTRA_MODULES_PATH in cmake at it

berak gravatar imageberak ( 2015-10-13 00:00:37 -0500 )edit

@berak How do I compare an image of person with a set of images of the same person and give out a best match?

sruti_kalapatapu gravatar imagesruti_kalapatapu ( 2015-10-13 00:20:34 -0500 )edit

not like this. look here

berak gravatar imageberak ( 2015-10-13 00:31:52 -0500 )edit

@berak how do I modify //http://docs.opencv.org/modules/contrib/doc/facerec/tutorial/facerec_video_recognition.html to take an image as input?

sruti_kalapatapu gravatar imagesruti_kalapatapu ( 2015-10-13 00:51:43 -0500 )edit

ahh, cmon, just use imread()

berak gravatar imageberak ( 2015-10-13 01:04:25 -0500 )edit