【问题标题】:How to stitch two images after calculating their homography计算单应性后如何拼接两个图像
【发布时间】:2017-07-11 09:31:42
【问题描述】:

我正在尝试在 opencv c++ 中拼接两个重叠的图像。我使用 ORB 进行特征匹配,并计算了两个图像之间的 Homography。现在使用这个 Homography 矩阵我想进一步添加两个图像。但我不知道如何更进一步。谁能告诉我接下来的步骤。 到目前为止我写的代码是:

detector->detect(img1, kp1,descriptors_img1);
detector->detect(img2, kp2,descriptors_img2);


Ptr<DescriptorExtractor> extractor = ORB::create();
extractor->compute(img1, kp1, descriptors_img1 );
extractor->compute(img2, kp2, descriptors_img2 );

if ( descriptors_img1.empty() )
    cvError(0,"MatchFinder","1st descriptor empty",__FILE__,__LINE__);
if ( descriptors_img2.empty() )
    cvError(0,"MatchFinder","2nd descriptor empty",__FILE__,__LINE__);
descriptors_img1.convertTo(descriptors_img1, CV_32F);
descriptors_img2.convertTo(descriptors_img2, CV_32F);
FlannBasedMatcher matcher;
std::vector<DMatch> matches;
matcher.match(descriptors_img1,descriptors_img2,matches);
double max_dist = 0; double min_dist = 100;

//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_img1.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 (i.e. whose distance is less than 3*min_dist )
std::vector< DMatch > good_matches;

for( int i = 0; i < descriptors_img1.rows; i++ )
{
    if( matches[i].distance < 3*min_dist )
    {
        good_matches.push_back( matches[i]);
    }
}
Mat img_matches;
drawMatches(img1,kp1,img2,kp2,good_matches,img_matches,Scalar::all(-1),
        Scalar::all(-1),vector<char>(),DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- Localize the object
std::vector<Point2f> obj;
std::vector<Point2f> scene;
for( int i = 0; i < good_matches.size(); i++ )
{
    //-- Get the keypoints from the good matches
    obj.push_back( kp1[ good_matches[i].queryIdx ].pt );
    scene.push_back( kp2[ good_matches[i].trainIdx ].pt );
}

Mat H = findHomography( obj, scene, CV_RANSAC );

【问题讨论】:

  • Richard Szilesk 的“计算机视觉:算法和应用”的第 9 章和第 10 章应该为您提供了足够的信息。基本上,您需要将两个图像之一的所有像素的坐标转换为其他图像。通常两个图像中只有一部分重叠,因此生成的图像会更大,以便同时包含两者。您可以根据两个图像的角计算新的宽度和高度。
  • 使用 warpImage 您可以将两个图像带到同一个坐标系,但是您必须决定为结果选择哪个图像的哪个像素。通常这是通过一些混合机制完成的,例如 alpha 混合/线性交叉混合,但最终取决于图像的同质性(亮度、运动视差等)

标签: c++ opencv orb


【解决方案1】:

计算出单应矩阵后,您只需要将图像变形并将它们混合在一起。这可以使用warpPerspective 函数来完成,如下所示。

cv::Mat result;

warpPerspective( img1, result, H, cv::Size( img1.cols+img2.cols, img1.rows) );
cv::Mat half(result, cv::Rect(0, 0, img2.cols, img2.rows) );
img2.copyTo(half);

结果是您最终拼接的图像。希望这能解决您的问题。

【讨论】:

  • 这是一个很好的方法,只需注意一件事。通过只做一个warpPerspective,你会做到这一点,所以拼接的图像是依赖于顺序的。这意味着如果您尝试颠倒两个图像的顺序,只会出现一个。要纠正这一点,您只需计算需要映射的额外单应性(我们称之为 htr)。这意味着您将有两个经线视角。一个带有 warpPerspective(htr) 和一个 warpPerspective(homography*htr)
  • 我尝试了上面的代码,但是当我打印结果时,输出只有img2,而不是img1和img2的拼接图像。
  • 由于您没有显示您的图像,我建议您尝试将img1img2 交换,然后运行整个代码。
  • 我尝试在您提供的上述解决方案中将 img2 与 img1 交换,反之亦然。现在结果只有 img1 而不是拼接图像
猜你喜欢
  • 2020-07-23
  • 2015-02-23
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-07
相关资源
最近更新 更多