OpenCV drawMatches 错误

OpenCV drawMatches error

我的代码包含一个部分,我在其中对一组匹配项进行排序,并根据距离定义良好的匹配项。当我尝试 drawMatches 时,收到错误消息:

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 文件显示:

// 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 );
     }
}

我的 drawMatches 调用如下:

Mat matchesImage;

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

谁能帮我解释一下这个错误?

更新:

这是我的 good_matches 计算代码

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 );

更新二:

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

一般来说,good_matches是一个数组,绑定了keypoints1keypoints2数组中的点。所以点keypoints1[good_matches[m].queryIdx]对应点keypoints2[good_matches[m].trainIdx]. 如您所见,opencv 代码中的断言是有意义的。

看来,问题出在匹配数组中。

我认为你应该在每次迭代时使用 good_matches.clear() 命令清除 good_matches 向量的内容(如果你使用 while(1) 循环从相机获取帧,你将写good_matches.clear() 命令在 while(1) 循环之后:

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

问题与您匹配点的顺序有关。 如果你这样做了,例如:

match(right_desc, left_desc)

函数drawMatches 将必须遵循相同的顺序。这将起作用(考虑我的匹配示例):

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

这将产生您遇到的错误:

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

当您访问匹配的坐标时,顺序也会影响什么是查询和什么是训练(即 queryIdxtrainIdx)。注意right_ptsleft_pts分别是right_descleft_desc描述的关键点。

希望对大家有所帮助。

我不同意上面的回答。

你传入matcher.match(dscp1, dscp2, matches)drawMatch(img1, kp1, img2, kp2, good_matches)的参数是对应的(它们都匹配keypoints2keypoints1中的每一个描述符,keypoints1被称为query设置而 keypoints2 称为训练集。)

该错误可能是由于您将错误的keypoints1keypoints2传递给drawMatch()造成的。查看good_matches中的index是否对应keypoints1中的kp。 (如果您在挑选好的匹配项时减少 keypoints 的数量,则可能会发生这种情况。)