P3d0r
P3d0r

Reputation: 1099

OpenCV drawMatches error

My code consists of a section where I sort through a set of matches and define good matches based on distance. When I try to drawMatches, I receive an error:

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

draw.cpp file shows:

// draw matches
for( size_t m = 0; m < matches1to2.size(); m++ )
{
     if( matchesMask.empty() || matchesMask[m] )
     {
          int i1 = matches1to2[m].queryIdx;
          int i2 = matches1to2[m].trainIdx;
          CV_Assert(i1 >= 0 && i1 < static_cast<int>(keypoints1.size()));
          CV_Assert(i2 >= 0 && i2 < static_cast<int>(keypoints2.size()));
          const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2];
          _drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags );
     }
}

My drawMatches call follows:

Mat matchesImage;

drawMatches( im1, keypoints1, im2, keypoints2,
    good_matches, matchesImage, Scalar::all(-1), Scalar::all(-1),
    vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

Can anybody help explain this error to me?

Update:

Here is my code for the good_matches calculation

double min_dist = 10000;
double max_dist = 0;

//-- Quick calculation of max and min distances between keypoints
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;
}

printf("-- Max dist : %f \n", max_dist );
printf("-- Min dist : %f \n", min_dist );

//-- Draw only "good" matches
std::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]); 
    }
}

for( int i = 0; i < (int)good_matches.size(); i++ ) {
    printf( "-- Good Match [%d] Keypoint 1: %d  -- Keypoint 2: %d  \n", 
        i, good_matches[i].queryIdx, good_matches[i].trainIdx ); 
}

cout << "number of good matches: " << (int)good_matches.size() << endl;;

//Draw matches and save file
Mat matchesImage;

drawMatches( im1, keypoints1, im2, keypoints2,
    good_matches, matchesImage, Scalar::all(-1), Scalar::all(-1),
    vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

Update 2:

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

Upvotes: 6

Views: 13614

Answers (4)

GeneralShark
GeneralShark

Reputation: 1

I don't agree with answers above.

Parameters you pass into matcher.match(dscp1, dscp2, matches) and drawMatch(img1, kp1, img2, kp2, good_matches) are corresponding (they are both matching every descriptor in keypoints1 from keypoints2, keypoints1 is called query set while keypoints2 is called train set.)

The error might be caused by the wrong keypoints1 and keypoints2 you pass into drawMatch(). Check whether the index in good_matches correspond with kp in keypoints1. (If you reduce the number of keypoints while picking good matches, this occasion could happen.)

Upvotes: 0

Tony Power
Tony Power

Reputation: 1178

The problem has to do with the order you matched the points. If you did, e.g.:

match(right_desc, left_desc)

function drawMatches will have to follow the same order. This will work (considering my matching example):

drawMatches(right_rgb, right_pts, left_rgb, left_pts, matches)

this will produce the error you have:

drawMatches(left_rgb, left_pts, right_rgb, right_pts, matches)

The order will also affect what is query and what is train (i.e. queryIdx and trainIdx), when you access the coordinates of the matches. Note that right_pts and left_pts are the keypoints described by right_desc and left_desc respectively.

Hope it helps someone.

Upvotes: 5

Mehmet
Mehmet

Reputation: 48

I think you should clear the contents of the good_matches vector with the good_matches.clear() command for each iteration (if you use while(1) loop for get frame from camera, you will write good_matches.clear() command after while(1) loop:

while(1) {
     good_matches.clear();
     // other code ...
}

Upvotes: 2

Marcin Kolny
Marcin Kolny

Reputation: 633

In general, good_matches is an array, which binds points from both keypoints1 and keypoints2 array. So point keypoints1[good_matches[m].queryIdx] corresponds to point keypoints2[good_matches[m].trainIdx]. As you can see, assertions in opencv code have sense.

It seems, the problem is in matches array.

Upvotes: 0

Related Questions