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

bahti picture bahti · Apr 4, 2012 · Viewed 20.1k times · Source

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.

Answer

MMH picture MMH · Apr 5, 2012

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.