Ask Your Question

Drawmatches throws error when trying to use only good matches

asked 2015-06-24 19:44:41 -0500

Banquin gravatar image

updated 2015-06-25 16:48:31 -0500

Hi! Im trying to track and object through feature detection. The code of example I have works very well using all the matches. But, to make it "better", i would like to use only the best matches. Then I select them, but when I use drawMatches the program doesnt work. Here is my code:

#include <stdio.h>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
    VideoCapture cap(0); // open the video camera no. 0

    if (!cap.isOpened())  // if not success, exit program
    cout << "Cannot open the video cam" << endl;
    return -1;

       double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
       double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

        cout << "Frame size : " << dWidth << " x " << dHeight << endl;

        namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"

    Mat img1 = imread( "ake.jpg", CV_LOAD_IMAGE_GRAYSCALE );
    OrbFeatureDetector detector;
        vector<KeyPoint> keypoints1, keypoints2;
        detector.detect(img1, keypoints1);
        // computing descriptors
       OrbDescriptorExtractor extractor(32);
        Mat descriptors1, descriptors2;
        extractor.compute(img1, keypoints1, descriptors1);
        BFMatcher matcher(NORM_L2,true);
            vector<DMatch> matches;
    while (1)
        Mat img2;
        cap >> img2;
        detector.detect(img2, keypoints2);
            // computing descriptors
            extractor.compute(img2, keypoints2, descriptors2);
        //FlannBasedMatcher matcher;
        //std::vector< DMatch > matches;

            matcher.match(descriptors1, descriptors2, matches);
        double max_dist = 0; double min_dist = 100;
        for( int i = 0; i < descriptors1.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 2*min_dist,
          //-- or a small arbitary value ( 0.02 ) in the event that min_dist is very
          //-- small)
          //-- PS.- radiusMatch can also be used here.
          vector< DMatch > good_matches;
          for( int i = 0; i < descriptors1.rows; i++ )
        { if( matches[i].distance <= max(2*min_dist, 0.02) )
            { good_matches.push_back( matches[i]); }

          Mat img_matches;
        drawMatches( img1, keypoints1, img2, keypoints2,good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
           vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
            imshow("MyVideo", img_matches); //show the frame in "MyVideo" window

            if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
                cout << "esc key is pressed by user" << endl;
    return 0;


And this is the error:

 OpenCV Error: Assertion failed (i1 >= 0 && i1 < static_cast<int>(keypoints1.size())) in drawMatches, file /home/edrone/Documents/OpenCV/opencv-2.4.9/modules/features2d/src/draw.cpp, line 207
terminate called after throwing an instance of 'cv::Exception'
  what():  /home/edrone/Documents/OpenCV/opencv-2.4.9/modules/features2d/src/draw.cpp:207: error: (-215) i1 >= 0 && i1 < static_cast<int>(keypoints1.size()) in function drawMatches

However, if i dont use good_matches but matches, it works.

I hope someone can help me Thanks!

Edit 1: I kinda solved the problem. I wasnt clearing the good_matches vector, so it was growing and growing, then eventually gets to core dumped.

Now the problem that I have is that when it doesnt get good matches, shows me that error ... (more)

edit retag flag offensive close merge delete


Mmmm sorry that I don't have much time at hand right now, but it seems that you are confusing between a vector of vector of keypoints and a plain simple vector of keypoints. But I am unsure, if somebody else could check it would be great!

Doomb0t gravatar imageDoomb0t ( 2015-06-26 12:41:15 -0500 )edit

Vector of Vector and Vector are both allowed. The matchMask just needs to match. He is using a matcher that generates Vector so it is correct.

VoteCoffee gravatar imageVoteCoffee ( 2020-10-04 18:51:00 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2020-10-04 18:58:48 -0500

VoteCoffee gravatar image

For me, it happened because the keypoints were swapped from the expected between the matcher and the drawMatches. But it can also occur in your case because you have a loop but keypoints2 and matches are reused but not cleared. You should move the keypoints2/descriptors2/matches declarations inside of the loop and also clear those same vectors at the end of the while loop.

For both matcher and drawMatches, Query/Scene comes first, then Train/Object. In your case, descriptors1 is the trained keypoint set and descriptors2 is the query. You need to swap the order in the matcher and drawMatches functions.

Change this:

matcher.match(descriptors1, descriptors2, matches);

to this:

matcher.match(descriptors2, descriptors1, matches);

Also change this:

drawMatches( img1, keypoints1, img2, keypoints2,good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
           vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

to this:

drawMatches( img2, keypoints2, img1, keypoints1,good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
           vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
edit flag offensive delete link more

Question Tools

1 follower


Asked: 2015-06-24 19:44:41 -0500

Seen: 2,969 times

Last updated: Oct 04 '20