2

I'm currently working on real-time feature matching using OpenCV3.4.0, c++ in QT creator.

My code matches features between the first frame that I got by webcam and current frame input from webcam.

Mat frame1, frame2, img1, img2, img1_gray, img2_gray;
int n = 0;
VideoCapture cap1(0);
namedWindow("Video Capture1", WINDOW_NORMAL);
namedWindow("Reference img", WINDOW_NORMAL);
namedWindow("matches1", WINDOW_NORMAL);

moveWindow("Video Capture1",50, 0);
moveWindow("Reference img",50, 100);
moveWindow("matches1",100,100);



while((char)waitKey(1)!='q'){
       //raw image saved in frame
       cap1>>frame1;

       n=n+1;
       if (n ==1){
           imwrite("frame1.jpg",  frame1);
           cout<<"First frame saved as 'frame1'!!"<<endl;
       }
       if(frame1.empty())
       break;


       imshow("Video Capture1",frame1);

       img1 = imread("frame1.jpg");
       img2 = frame1;

       cvtColor(img1, img1_gray, cv::COLOR_BGR2GRAY);
       cvtColor(img2, img2_gray, cv::COLOR_BGR2GRAY);

       imshow("Reference img",img1);

       // detecting keypoints
       int minHessian = 400;
       Ptr<Feature2D> detector = xfeatures2d::SurfFeatureDetector::create();
       vector<KeyPoint> keypoints1, keypoints2;
       detector->detect(img1_gray,keypoints1);
       detector->detect(img2_gray,keypoints2);

       // computing descriptors
       Ptr<DescriptorExtractor> extractor = xfeatures2d::SurfFeatureDetector::create();
       Mat descriptors1, descriptors2;
       extractor->compute(img1_gray,keypoints1,descriptors1);
       extractor->compute(img2_gray,keypoints2,descriptors2);

       // matching descriptors
       BFMatcher matcher(NORM_L2);
       vector<DMatch> matches;
       matcher.match(descriptors1, descriptors2, matches);

       // drawing the results

       Mat img_matches;
       drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
       imshow("matches1", img_matches);

But the code returns so many matched points that I cannot distinguish which one matches which.

So, are there any methods to get high-quality matched points only?

And how can I get each matched point's pixel coordinates in QT creator just like MATLAB?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Hyunjun
  • 37
  • 4

1 Answers1

0

So, are there any methods to get high-quality matched points only?

I bet there are a lot of different methods. I am using e.g. a symmetry test. So matches from img1 to img2 also have to exist when matching from img2 to img1. I am using the test of Improve matching of feature points with OpenCV. Multiple other tests are shown there.

void symmetryTest(const std::vector<cv::DMatch> &matches1,const std::vector<cv::DMatch> &matches2,std::vector<cv::DMatch>& symMatches)
{
    symMatches.clear();
    for (vector<DMatch>::const_iterator matchIterator1= matches1.begin();matchIterator1!= matches1.end(); ++matchIterator1)
    {
        for (vector<DMatch>::const_iterator matchIterator2= matches2.begin();matchIterator2!= matches2.end();++matchIterator2)
        {
            if ((*matchIterator1).queryIdx ==(*matchIterator2).trainIdx &&(*matchIterator2).queryIdx ==(*matchIterator1).trainIdx)
            {
                symMatches.push_back(DMatch((*matchIterator1).queryIdx,(*matchIterator1).trainIdx,(*matchIterator1).distance));
                break;
            }
        }
    }
}

Like András Kovács says in the related answer you can also calculate a Fundamental Matrix with RANSAC to eliminate outliers using cv::findFundamentalMat.

And how can I get each matched point's pixel coordinates in QT creator just like MATLAB?

I hope I understood it right that you want to have the point coordinates of homologue points that match. I am extracting the coordinates of the points after the symmetryTest. The coordinates are inside the keypoints.

for (size_t rows = 0; rows < sym_matches.size(); rows++) {

        float x1 = keypoints_1[sym_matches[rows].queryIdx].pt.x;
        float y1 = keypoints_1[sym_matches[rows].queryIdx].pt.y;        

        float x2 = keypoints_2[sym_matches[rows].trainIdx].pt.x;
        float y2 = keypoints_2[sym_matches[rows].trainIdx].pt.y;

        // Push the coordinates in a vector e.g. std:vector<cv::Point2f>>
    }

You can do the same with your matches, keypoints1 and keypoint2.

Grillteller
  • 891
  • 10
  • 26