Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Drawmatches throws error when trying to use only good matches

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;
                break; 
            }
    }
    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!

Drawmatches throws error when trying to use only good matches

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;
                break; 
            }
    }
    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. I tried the following solution, but it doesnt work:

 if(good_matches.size()>=0)
    {
          drawMatches( img1, keypoints1, img2, keypoints2,
             good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
              vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
    good_matches.clear();
}
else
{
    drawMatches( img1, keypoints1, img2, keypoints2,
          matches, img_matches, Scalar::all(-1), Scalar::all(-1),
           vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
    good_matches.clear();   
}

When the good_matches is empty, just print matches instead. But, it doesnt work. Hope someone could help me Thanks