图像全景拼接

博客介绍了多个国外开源的图像拼接相关链接,包括代码和博客。还阐述了图像全景拼接中Homographies的概念,通过特征点检测(如SIFT)获取对应点,计算单应性矩阵,将源图像透视扭曲后与目标图像合并,完成图像拼接。

这个效果待测:

https://github.com/balancehy/Computer-vision/blob/master/image-stitching/src/stitch.py

 

这个也待测:

https://github.com/AVINASH793/Video-Stabilization-and-image-mosaicing

opencv+MFC实现图像拼接

https://download.csdn.net/download/weixin_37753215/10727499

https://github.com/ferdyandannes/Video-Stitching-OpenCV-CUDA

 

这个无代码:

https://download.csdn.net/download/qq_28901541/10747238

sift特征:

https://github.com/royangkr/Video-stitching-python

 

image stitch(国外开源的图像拼接)

https://blog.csdn.net/yangpan011/article/details/81387299

 

https://blog.csdn.net/red_ear/article/details/81566252

图像全景拼接--Using Homographies

这里总结一下Homographies:

      假设我们有两个相同平面对象的图像,它们之间有一些重叠(存在对应点)。让P1成为第一图像中的点的像素坐标[P1x,P1y,1 ],P2是第二图像中的点的像素坐标[P2X,P2Y,1 ]。我们将第一图像称为目的图像,第二图像称为源图像。单应性1H2是将第二图像中的每个像素坐标与第一图像中的像素坐标映射关系。

P1 = 1H2 * P2

获取对应点

可以使用特征点检测,如 SIFT,SURF,ORB等,这里,我们使用sift,虽然慢,但是相比于其他,这个是最准确的。

1,两张有重叠部分的图

2 如果我们想把源图像的像素粘贴在一个大的画布上,我们需要考虑在更大的画布上的目标图像。

int offsetx = 800;

int offsety = 1000;

Mat trans_mat = (Mat_<double>(2, 3) << 1, 0, offsetx, 0, 1, offsety);

warpAffine(im1, im1, trans_mat, Size(3 * im1.cols, 3 * im1.rows));

结果

SIFT特征检测

 
  1. cv::Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();

  2.  
  3. // Step 1: Detect the keypoints:

  4. std::vector<KeyPoint> keypoints_1, keypoints_2;

  5. f2d->detect( im_1, keypoints_1 );

  6. f2d->detect( im_2, keypoints_2 );

  7.  
  8. // Step 2: Calculate descriptors (feature vectors)

  9. Mat descriptors_1, descriptors_2;

  10. f2d->compute( im_1, keypoints_1, descriptors_1 );

  11. f2d->compute( im_2, keypoints_2, descriptors_2 );

  12.  
  13. // Step 3: Matching descriptor vectors using BFMatcher :

  14. BFMatcher matcher;

  15. std::vector< DMatch > matches;

  16. matcher.match( descriptors_1, descriptors_2, matches );

  17.  
  18. // Keep 200 best matches only.

  19. // We sort distance between descriptor matches

  20. Mat index;

  21. int nbMatch = int(matches.size());

  22. Mat tab(nbMatch, 1, CV_32F);

  23. for (int i = 0; i < nbMatch; i++)

  24. tab.at<float>(i, 0) = matches[i].distance;

  25. sortIdx(tab, index, SORT_EVERY_COLUMN + SORT_ASCENDING);

  26. vector<DMatch> bestMatches;

  27.  
  28. for (int i = 0; i < 200; i++)

  29. bestMatches.push_back(matches[index.at < int > (i, 0)]);

匹配对应点

计算单应性矩阵

 
  1. // 1st image is the destination image and the 2nd image is the src image

  2. std::vector<Point2f> dst_pts; //1st

  3. std::vector<Point2f> source_pts; //2nd

  4.  
  5. for (vector<DMatch>::iterator it = bestMatches.begin(); it != bestMatches.end(); ++it) {

  6. //-- Get the keypoints from the good matches

  7. dst_pts.push_back( keypoints_1[ it->queryIdx ].pt );

  8. source_pts.push_back( keypoints_2[ it->trainIdx ].pt );

  9. }

  10.  
  11. Mat H = findHomography( source_pts, dst_pts, CV_RANSAC );

  12. cout << H << endl;

输出H为

 
  1. [0.119035947337248, -0.04651626756941147, 1700.852494625838;

  2. -0.5652916039380339, 0.9340629651977271, 1045.011078408947;

  3. -0.0004251711674909509, 1.783961055570689e-05, 1]

现在我们有单应性。我们只需要将ima2上的透视扭曲应用于IMA1大小的空白黑色画布上。

 
  1. Mat wim_2;

  2. warpPerspective(im_2, wim_2, H, im_1.size());

im_2经过H 变换,变为wim_2,

效果图如下:

      大部分事情现在都完成了。我们只需要把这两个图像合并在一起。这一粗暴和简单的方法是:复制所有这些像素的wim_2到im_1是黑色的im_1。

 
  1. // We can do this since im_1 and wim_2 have the same size.

  2. for (int i = 0; i < im_1.cols; i++)

  3. for (int j = 0; j < im_1.rows; j++) {

  4. Vec3b color_im1 = im_1.at<Vec3b>(Point(i, j));

  5. Vec3b color_im2 = wim_2.at<Vec3b>(Point(i, j));

  6. if (norm(color_im1) == 0)

  7. im_1.at<Vec3b>(Point(i, j)) = color_im2;

  8. }

展示im_1:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值