Trying to match two images using sift in OpenCv, but too many matches

20,341

Rather than using BruteForceMatcher try to use FlannBasedMatcher and also calculate max and min distances between keypoints to keep only the good matches. See "Feature Matching with FLANN" for an example.

Share:
20,341
bahti
Author by

bahti

Updated on August 25, 2020

Comments

  • bahti
    bahti over 3 years

    I am trying to implement a program which will input two images one is an image of a box alone and one which includes the box in the scene. Basically, the program is supposed to find keypoints in these two images and will show the images with keypoints matched. That is in the end I expect to see an appended image of two input images together with their matched keypoints connected. My code is as follows:

    #include <opencv2\opencv.hpp>
    #include <iostream>
    
    int main(int argc, const char* argv[]) {
       cv::Mat input1 = cv::imread("input.jpg", 1); //Load as grayscale
       //cv::cvtColor(input1,input1,CV_BGR2GRAY);
       //second input load as grayscale
       cv::Mat input2 = cv::imread("input2.jpg",1);
       cv::SiftFeatureDetector detector;
       //cv::SiftFeatureDetector
       detector(
          1, 1,
          cv::SIFT::CommonParams::DEFAULT_NOCTAVES,
          cv::SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
          cv::SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
          cv::SIFT::CommonParams::FIRST_ANGLE );
       std::vector<cv::KeyPoint> keypoints1;
       detector.detect(input1, keypoints1);
       // Add results to image and save.
       cv::Mat output1;
       cv::drawKeypoints(input1, keypoints1, output1);
       cv::imshow("Sift_result1.jpg", output1);
       cv::imwrite("Sift_result1.jpg",output1);
       //keypoints array for input 2
       std::vector<cv::KeyPoint> keypoints2;
       //output array for ouput 2
       cv::Mat output2;
       //Sift extractor of opencv
       cv::SiftDescriptorExtractor extractor;
       cv::Mat descriptors1,descriptors2;
       cv::BruteForceMatcher<cv::L2<float>> matcher;
       cv::vector<cv::DMatch> matches;
       cv::Mat img_matches;
       detector.detect(input2,keypoints2);
       cv::drawKeypoints(input2,keypoints2,output2);
       cv::imshow("Sift_result2.jpg",output2);
       cv::imwrite("Sift_result2.jpg",output2);
       extractor.compute(input1,keypoints1,descriptors1);
       extractor.compute(input2,keypoints2,descriptors2);
       matcher.match(descriptors1,descriptors2,matches);
       //show result
       cv::drawMatches(input1,keypoints1,input2,keypoints2,matches,img_matches);
       cv::imshow("matches",img_matches);
       cv::imwrite("matches.jpg",img_matches);
       cv::waitKey();
       return 0;
    }
    

    The problem is there are two many many matches than expected. I tried to debug the program and looked what is inside the keypoints vectors and so on, everything looks to be fine, at least I think they are, the keypoints are detected with orientation etc.

    I am using OpenCV v2.3 and checked its documentation for the types of classes I am using and tried to solve the problem but that did not work. I am working on this for a 3 days did not make much of an improvement.

    Here is an output i get from my program.

    I should have remove the image.

    I know that should not give me too much matches, because I have tested the exact same images with another implemenation in matlab that was quite good.

  • bahti
    bahti about 12 years
    Thank you. The problem was as you said, with drawing all the matches but not only the good matches. Now that i am sorting matches and selecting the 15% with minimum distances.
  • MMH
    MMH about 12 years
    I hope you fixed the problem.
  • B.Kosmowski
    B.Kosmowski over 7 years