opencv2基于SURF特征提取实现两张图像拼接融合

 更新时间:2020年03月05日 13:39:28   作者:米姒翰  
这篇文章主要为大家详细介绍了opencv2基于SURF特征提取实现两张图像拼接融合,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了opencv2实现两张图像拼接融合的具体代码,供大家参考,具体内容如下

要用到两个文件,estimate.cpp和matcher.h(在有关鲁棒匹配这篇博文中有)

estimate.cpp的头文件也需要添加一些东西才行,以下是对的,已经成功运行。

加了using namespace std;之后,cv::可以去掉了。

estimate.cpp:

#include <iostream>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include<opencv2/nonfree/nonfree.hpp>
#include<opencv2\legacy\legacy.hpp> 
#include "matcher.h"
using namespace std;
using namespace cv;
int main()
{
// Read input images读入图像
cv::Mat image1= cv::imread("parliament1.bmp",0);
cv::Mat image2= cv::imread("parliament2.bmp",0);
if (!image1.data || !image2.data)
return 0; 


  // Display the images显示图像
cv::namedWindow("Image 1");
cv::imshow("Image 1",image1);
cv::namedWindow("Image 2");
cv::imshow("Image 2",image2);


// Prepare the matcher准备匹配
RobustMatcher rmatcher;
rmatcher.setConfidenceLevel(0.98);
rmatcher.setMinDistanceToEpipolar(1.0);
rmatcher.setRatio(0.65f);
cv::Ptr<cv::FeatureDetector> pfd= new cv::SurfFeatureDetector(10); 
rmatcher.setFeatureDetector(pfd);


// Match the two images
std::vector<cv::DMatch> matches;
std::vector<cv::KeyPoint> keypoints1, keypoints2;
cv::Mat fundemental= rmatcher.match(image1,image2,matches, keypoints1, keypoints2);


// draw the matches画匹配结果
cv::Mat imageMatches;
cv::drawMatches(image1,keypoints1, // 1st image and its keypoints第一张图像及其关键点
      image2,keypoints2, // 2nd image and its keypoints第二张图像及其关键点
matches, // the matches匹配结果
imageMatches, // the image produced产生的图像
cv::Scalar(255,255,255)); // color of the lines线的颜色
cv::namedWindow("Matches");
cv::imshow("Matches",imageMatches);

// Convert keypoints into Point2f将关键点转换为Point2f
std::vector<cv::Point2f> points1, points2;
for (std::vector<cv::DMatch>::const_iterator it= matches.begin();
it!= matches.end(); ++it) {H


// Get the position of left keypoints得到左图关键点位置
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints得到右图关键点位置
x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
}


std::cout << points1.size() << " " << points2.size() << std::endl; 


// Find the homography between image 1 and image 2找到图像1和图像2之间的单应性矩阵
std::vector<uchar> inliers(points1.size(),0);
cv::Mat homography= cv::findHomography(
cv::Mat(points1),cv::Mat(points2), // corresponding points对应点
inliers, // outputed inliers matches 输出内点匹配
CV_RANSAC, // RANSAC method   RANSAC 方法
1.);  // max distance to reprojection point到对应点的最大距离


// Draw the inlier points画内点
std::vector<cv::Point2f>::const_iterator itPts= points1.begin();
std::vector<uchar>::const_iterator itIn= inliers.begin();
while (itPts!=points1.end()) {


// draw a circle at each inlier location在每一个内点画一个圈
if (*itIn) 
 cv::circle(image1,*itPts,3,cv::Scalar(255,255,255),2);

++itPts;
++itIn;
}


itPts= points2.begin();
itIn= inliers.begin();
while (itPts!=points2.end()) {


// draw a circle at each inlier location在每一个内点画一个圈
if (*itIn) 
cv::circle(image2,*itPts,3,cv::Scalar(255,255,255),2);

++itPts;
++itIn;
}


  // Display the images with points显示画点的图像
cv::namedWindow("Image 1 Homography Points");
cv::imshow("Image 1 Homography Points",image1);
cv::namedWindow("Image 2 Homography Points");
cv::imshow("Image 2 Homography Points",image2);


// Warp image 1 to image 2变形图像1到图像2
cv::Mat result;
cv::warpPerspective(image1, // input image输入的图像
result, // output image输出的图像
homography, // homography单应性矩阵
cv::Size(2*image1.cols,image1.rows)); // size of output image输出图像的大小


// Copy image 1 on the first half of full image复制图像1的上一部分
cv::Mat half(result,cv::Rect(0,0,image2.cols,image2.rows));
image2.copyTo(half);


  // Display the warp image显示变形后图像
cv::namedWindow("After warping");
cv::imshow("After warping",result);


cv::waitKey();
return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Qt使用Quazip解压缩、压缩文件的实现

    Qt使用Quazip解压缩、压缩文件的实现

    Quazip是在zlib基础上进行了简单封装的开源库,利用它可以很方便将单个或多个文件打包为zip文件,本文主要介绍了Qt使用Quazip解压缩、压缩文件的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • Qt生成随机数的方法

    Qt生成随机数的方法

    本文主要介绍了Qt生成随机数,生成随机数主要用到了函数qsrand和qrand,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • 浅析C++中boost.variant的几种访问方法

    浅析C++中boost.variant的几种访问方法

    variant类型在C++14并没有加入,若想在不支持C++17的编译器上使用variant类型,我们可以通过boost的variant类型,variant类型可以表示任意一种类型和any类型有些相似,但还是有些区别下面将浅谈variant的几种访问方法,感兴趣的朋友们下面来一起看看吧。
    2016-10-10
  • 举例说明自定义C++异常处理的实例

    举例说明自定义C++异常处理的实例

    这篇文章主要介绍了举例说明自定义C++异常处理的实例的相关资料,这里举例说明该如何使用C++ 的异常,需要的朋友可以参考下
    2017-10-10
  • C++ 17转发一个函数调用的完美实现

    C++ 17转发一个函数调用的完美实现

    这篇文章主要给大家介绍了关于C++ 17如何转发一个函数调用的完美实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用C++17具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧。
    2017-08-08
  • C语言memset函数使用方法详解

    C语言memset函数使用方法详解

    这篇文章主要介绍了C语言memset函数使用方法详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下
    2017-10-10
  • C++实现LeetCode(108.将有序数组转为二叉搜索树)

    C++实现LeetCode(108.将有序数组转为二叉搜索树)

    这篇文章主要介绍了C++实现LeetCode(108.将有序数组转为二叉搜索树),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言求逆矩阵案例详解

    C语言求逆矩阵案例详解

    这篇文章主要介绍了C语言求逆矩阵案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++内存管理详解使用方式

    C++内存管理详解使用方式

    内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能更大的自由,C++菜鸟的收获则是一遍—遍的检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存泄漏几乎在每个C++程序中都会发生,要想成为C++高手,内存管理这关是必须过的
    2022-04-04
  • C++ 流插入和流提取运算符的重载的实现

    C++ 流插入和流提取运算符的重载的实现

    这篇文章主要介绍了C++ 流插入和流提取运算符的重载的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12

最新评论