返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++ OpenCV如何进行图像全景拼接
  • 632
分享到

C++ OpenCV如何进行图像全景拼接

2023-06-22 08:06:12 632人浏览 独家记忆
摘要

c++ OpenCV如何进行图像全景拼接,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。前言下面将使用OpenCV C++ 进行图像全景拼接。目前使用OpenCV对两幅

c++ OpenCV如何进行图像全景拼接,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

    前言

    下面将使用OpenCV C++ 进行图像全景拼接。目前使用OpenCV对两幅图像进行拼接大致可以分为两类。

    一、使用OpenCV内置api Stitcher 进行拼接。

    二、使用特征检测算法匹配两幅图中相似的点、计算变换矩阵、最后对其进行透视变换就可以了。

    一、OpenCV Stitcher

    imageA

    C++ OpenCV如何进行图像全景拼接

    imageB

    C++ OpenCV如何进行图像全景拼接

    原图如图所示。本案例的需求是将上述两幅图片拼接成一幅图像。首先使用OpenCV提供的Stitcher进行拼接。关于Stitcher的具体原理请大家自行查找相关资料。

    1.功能源码

    bool OpenCV_Stitching(Mat imageA, Mat imageB){vector<Mat>images;images.push_back(imageA);images.push_back(imageB);Ptr<Stitcher>stitcher = Stitcher::create();Mat result;Stitcher::Status status = stitcher->stitch(images, result);// 使用stitch函数进行拼接if (status != Stitcher::OK) return false;imshow("OpenCV图像全景拼接", result);return true;}

    2.效果

    C++ OpenCV如何进行图像全景拼接

    这就是使用OpenCV 内置Stitcher拼接出来的效果。

    二、图像全景拼接

    1.特征检测

    使用方法二进行图像全景拼接。目前网上教程大致流程归为:

    使用特征检测算子提取两幅图像的关键点,然后进行特征描述子匹配。我这里使用的是SURF算子。当然SIFT等其他特征检测算子也可以。

    //创建SURF特征检测器int Hessian = 800;Ptr<SURF>detector = SURF::create(Hessian);//进行图像特征检测、特征描述vector<KeyPoint>keypointA, keypointB;Mat descriptorA, descriptorB;detector->detectAndCompute(imageA, Mat(), keypointA, descriptorA);detector->detectAndCompute(imageB, Mat(), keypointB, descriptorB);//使用FLANN算法进行特征描述子的匹配FlannBasedMatcher matcher;vector<DMatch>matches;matcher.match(descriptorA, descriptorB, matches);

    C++ OpenCV如何进行图像全景拼接

     如图为使用FLANN算法进行特征描述子匹配的结果。我们需要把那些匹配程度高的关键点筛选出来用以下面计算两幅图像的单应性矩阵。

    筛选出匹配程度高的关键点

    double Max = 0.0;for (int i = 0; i < matches.size(); i++){//float distance –>代表这一对匹配的特征点描述符(本质是向量)的欧氏距离,数值越小也就说明两个特征点越相像。double dis = matches[i].distance;if (dis > Max){Max = dis;}}//筛选出匹配程度高的关键点vector<DMatch>Goodmatches;vector<Point2f>goodkeypointA, goodkeypointB;for (int i = 0; i < matches.size(); i++){double dis = matches[i].distance;if (dis < 0.15*Max){//int queryIdx –>是测试图像的特征点描述符(descriptor)的下标,同时也是描述符对应特征点(keypoint)的下标。goodkeypointA.push_back(keypointA[matches[i].queryIdx].pt);//int trainIdx –> 是样本图像的特征点描述符的下标,同样也是相应的特征点的下标。goodkeypointB.push_back(keypointB[matches[i].trainIdx].pt);goodmatches.push_back(matches[i]);}}

    如图为imageA筛选出来的关键点。

    C++ OpenCV如何进行图像全景拼接

    如图为imageB筛选出来的关键点。

    C++ OpenCV如何进行图像全景拼接

    从上图可以看出,我们已经筛选出imageA,imageB共有的关键点部分。接下来,我们需要使用这两个点集计算两幅图的单应性矩阵。

    2.计算单应性矩阵

    计算单应性变换矩阵

        //获取图像A到图像B的投影映射矩阵,尺寸为3*3    Mat H = findHomography(goodkeypointA, goodkeypointB, RANSAC);    Mat M = (Mat_<double>(3, 3) << 1.0, 0, imageA.cols, 0, 1.0, 0, 0, 0, 1.0);    Mat Homo = M * H;

    3.透视变换

    根据计算出来的单应性矩阵对imageA进行透视变换

        //进行透视变换    Mat DstImg;    warpPerspective(imageA, DstImg, Homo, Size(imageB.cols + imageA.cols, imageB.rows));    imshow("透视变换", DstImg);

    C++ OpenCV如何进行图像全景拼接

    如图所示为imageA进行透视变换得到的结果。

    4.图像拼接

    根据上述操作,我们已经得到了经透视变换的imageA,接下来只需将imageA与imageB拼接起来就可以了。

        imageB.copyTo(DstImg(Rect(imageA.cols, 0, imageB.cols, imageB.rows)));    imshow("图像全景拼接", DstImg);

    5.功能源码

    bool Image_Stitching(Mat imageA, Mat imageB, bool draw){//创建SURF特征检测器int Hessian = 800;Ptr<SURF>detector = SURF::create(Hessian);//进行图像特征检测、特征描述vector<KeyPoint>keypointA, keypointB;Mat descriptorA, descriptorB;detector->detectAndCompute(imageA, Mat(), keypointA, descriptorA);detector->detectAndCompute(imageB, Mat(), keypointB, descriptorB);//使用FLANN算法进行特征描述子的匹配FlannBasedMatcher matcher;vector<DMatch>matches;matcher.match(descriptorA, descriptorB, matches);double Max = 0.0;for (int i = 0; i < matches.size(); i++){//float distance –>代表这一对匹配的特征点描述符(本质是向量)的欧氏距离,数值越小也就说明两个特征点越相像。double dis = matches[i].distance;if (dis > Max){Max = dis;}}//筛选出匹配程度高的关键点vector<DMatch>goodmatches;vector<Point2f>goodkeypointA, goodkeypointB;for (int i = 0; i < matches.size(); i++){double dis = matches[i].distance;if (dis < 0.15*Max){//int queryIdx –>是测试图像的特征点描述符(descriptor)的下标,同时也是描述符对应特征点(keypoint)的下标。goodkeypointA.push_back(keypointA[matches[i].queryIdx].pt);//int trainIdx –> 是样本图像的特征点描述符的下标,同样也是相应的特征点的下标。goodkeypointB.push_back(keypointB[matches[i].trainIdx].pt);goodmatches.push_back(matches[i]);}}if (draw){Mat result;drawMatches(imageA, keypointA, imageB, keypointB, goodmatches, result);imshow("特征匹配", result);Mat temp_A = imageA.clone();for (int i = 0; i < goodkeypointA.size(); i++){circle(temp_A, goodkeypointA[i], 3, Scalar(0, 255, 0), -1);}imshow("goodkeypointA", temp_A);Mat temp_B = imageB.clone();for (int i = 0; i < goodkeypointB.size(); i++){circle(temp_B, goodkeypointB[i], 3, Scalar(0, 255, 0), -1);}imshow("goodkeypointB", temp_B);}//findHomography计算单应性矩阵至少需要4个点if (goodkeypointA.size() < 4 || goodkeypointB.size() < 4) return false;//获取图像A到图像B的投影映射矩阵,尺寸为3*3Mat H = findHomography(goodkeypointA, goodkeypointB, RANSAC);Mat M = (Mat_<double>(3, 3) << 1.0, 0, imageA.cols, 0, 1.0, 0, 0, 0, 1.0);Mat Homo = M * H;//进行透视变换Mat DstImg;warpPerspective(imageA, DstImg, Homo, Size(imageB.cols + imageA.cols, imageB.rows));imshow("透视变换", DstImg);imageB.copyTo(DstImg(Rect(imageA.cols, 0, imageB.cols, imageB.rows)));imshow("图像全景拼接", DstImg);return true;}

    6.效果

    C++ OpenCV如何进行图像全景拼接

    最终拼接效果如图所示。

    三、源码

    #include<iOStream>#include<opencv2/opencv.hpp>#include<opencv2/xfeatures2d.hpp>#include<opencv2/stitching.hpp>using namespace std;using namespace cv;using namespace cv::xfeatures2d;//1、使用特征检测算法找到两张图像中相似的点,计算变换矩阵//2、将A透视变换后得到的图片与B拼接bool Image_Stitching(Mat imageA, Mat imageB, bool draw){//创建SURF特征检测器int Hessian = 800;Ptr<SURF>detector = SURF::create(Hessian);//进行图像特征检测、特征描述vector<KeyPoint>keypointA, keypointB;Mat descriptorA, descriptorB;detector->detectAndCompute(imageA, Mat(), keypointA, descriptorA);detector->detectAndCompute(imageB, Mat(), keypointB, descriptorB);//使用FLANN算法进行特征描述子的匹配FlannBasedMatcher matcher;vector<DMatch>matches;matcher.match(descriptorA, descriptorB, matches);double Max = 0.0;for (int i = 0; i < matches.size(); i++){//float distance –>代表这一对匹配的特征点描述符(本质是向量)的欧氏距离,数值越小也就说明两个特征点越相像。double dis = matches[i].distance;if (dis > Max){Max = dis;}}//筛选出匹配程度高的关键点vector<DMatch>goodmatches;vector<Point2f>goodkeypointA, goodkeypointB;for (int i = 0; i < matches.size(); i++){double dis = matches[i].distance;if (dis < 0.15*Max){//int queryIdx –>是测试图像的特征点描述符(descriptor)的下标,同时也是描述符对应特征点(keypoint)的下标。goodkeypointA.push_back(keypointA[matches[i].queryIdx].pt);//int trainIdx –> 是样本图像的特征点描述符的下标,同样也是相应的特征点的下标。goodkeypointB.push_back(keypointB[matches[i].trainIdx].pt);goodmatches.push_back(matches[i]);}}if (draw){Mat result;drawMatches(imageA, keypointA, imageB, keypointB, goodmatches, result);imshow("特征匹配", result);Mat temp_A = imageA.clone();for (int i = 0; i < goodkeypointA.size(); i++){circle(temp_A, goodkeypointA[i], 3, Scalar(0, 255, 0), -1);}imshow("goodkeypointA", temp_A);Mat temp_B = imageB.clone();for (int i = 0; i < goodkeypointB.size(); i++){circle(temp_B, goodkeypointB[i], 3, Scalar(0, 255, 0), -1);}imshow("goodkeypointB", temp_B);}//findHomography计算单应性矩阵至少需要4个点if (goodkeypointA.size() < 4 || goodkeypointB.size() < 4) return false;//获取图像A到图像B的投影映射矩阵,尺寸为3*3Mat H = findHomography(goodkeypointA, goodkeypointB, RANSAC);Mat M = (Mat_<double>(3, 3) << 1.0, 0, imageA.cols, 0, 1.0, 0, 0, 0, 1.0);Mat Homo = M * H;//进行透视变换Mat DstImg;warpPerspective(imageA, DstImg, Homo, Size(imageB.cols + imageA.cols, imageB.rows));imshow("透视变换", DstImg);imageB.copyTo(DstImg(Rect(imageA.cols, 0, imageB.cols, imageB.rows)));imshow("图像全景拼接", DstImg);return true;}bool OpenCV_Stitching(Mat imageA, Mat imageB){vector<Mat>images;images.push_back(imageA);images.push_back(imageB);Ptr<Stitcher>stitcher = Stitcher::create();Mat result;Stitcher::Status status = stitcher->stitch(images, result);// 使用stitch函数进行拼接if (status != Stitcher::OK) return false;imshow("OpenCV图像全景拼接", result);return true;}int main(){Mat imageA = imread("image1.jpg");Mat imageB = imread("image2.jpg");if (imageA.empty() || imageB.empty()){cout << "No Image!" << endl;system("pause");return -1;}if (!Image_Stitching(imageA, imageB, true)){cout << "can not stitching the image!" << endl;}if (!OpenCV_Stitching(imageA, imageB)){cout << "can not stitching the image!" << endl;}waiTKEy(0);system("pause");return 0;}

    小编使用OpenCV C++进行图像全景拼接,关键步骤有以下几点。

    使用特征检测算子提取两幅图像的关键点,然后进行特征描述子匹配。

    筛选出匹配程度高的关键点计算两幅图的单应性矩阵。

    利用计算出来的单应性矩阵对其中一张图片进行透视变换。

    将透视变换的图片与另一张图片进行拼接。

    看完上述内容,你们掌握C++ OpenCV如何进行图像全景拼接的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网其他教程频道,感谢各位的阅读!

    --结束END--

    本文标题: C++ OpenCV如何进行图像全景拼接

    本文链接: https://lsjlt.com/news/303508.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • C++ OpenCV如何进行图像全景拼接
      C++ OpenCV如何进行图像全景拼接,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。前言下面将使用OpenCV C++ 进行图像全景拼接。目前使用OpenCV对两幅...
      99+
      2023-06-22
    • C++OpenCV实战之图像全景拼接
      目录前言一、OpenCV Stitcher1.功能源码2.效果二、图像全景拼接1.特征检测2.计算单应性矩阵3.透视变换4.图像拼接5.功能源码6.效果三、源码总结前言 本文将使用O...
      99+
      2024-04-02
    • OpenCV全景图像拼接的实现示例
      本文主要介绍了OpenCV全景图像拼接的实现示例,分享给大家,具体如下: left_01.jpg right_01.jpg Stitcher.py import numpy ...
      99+
      2024-04-02
    • 使用OpenCV怎么实现全景图像拼接
      今天就跟大家聊聊有关使用OpenCV怎么实现全景图像拼接,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Stitcher.pyimport numpy as&nbs...
      99+
      2023-06-15
    • C++ OpenCV中如何进行图像像素值统计
      小编今天带大家了解C++ OpenCV中如何进行图像像素值统计,文中知识点介绍的非常详细。觉得有帮助的朋友可以跟着小编一起浏览文章的内容,希望能够帮助更多想解决这个问题的朋友找到问题的答案,下面跟着小编一起深入学习“C++&nbs...
      99+
      2023-06-28
    • 基于Python和openCV实现图像的全景拼接详细步骤
      基本介绍 图像的全景拼接,即“缝合”两张具有重叠区域的图来创建一张全景图。其中用到了计算机视觉和图像处理技术有:关键点检测、局部不变特征、关键点匹配、RANSAC(Random Sa...
      99+
      2024-04-02
    • OpenCV-Python 实现两张图片自动拼接成全景图
      目录背景介绍基本原理具体实现寻找相似点图片拼接Reference背景介绍 图片的全景拼接如今已不再稀奇,现在的智能摄像机和手机摄像头基本都带有图片自动全景拼接的功能,但是一般都会要求...
      99+
      2024-04-02
    • 使用c++实现OpenCV图像横向&纵向拼接
      功能函数 // 图像拼接 cv::Mat ImageSplicing(vector<cv::Mat> images,int type) { if (type != ...
      99+
      2024-04-02
    • OpenCV-Python怎么实现两张图片自动拼接成全景图
      这篇文章给大家分享的是有关OpenCV-Python怎么实现两张图片自动拼接成全景图的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。背景介绍图片的全景拼接如今已不再稀奇,现在的智能摄像机和手机摄像头基本都带有图片自...
      99+
      2023-06-15
    • 详解C++ OpenCV实现图像拼接的原理及方法
      目录前言一、图像拼接相关原理 图像特征采集特征提取算法透视变换透视矩阵图像拷贝二、案例实现Step1:导入目标图片Step2:特征点提取和匹配 Step3:图像配...
      99+
      2024-04-02
    • python计算机视觉实现全景图像拼接示例
      首先对图片进行预处理,是图片的分配率大小在合适的范围内,避免图片太大占满整个电脑屏幕。 from PIL import Image def produceImage(file_in,...
      99+
      2024-04-02
    • 如何进行Python OpenCV图像模糊处理分析
      这篇文章跟大家分析一下“如何进行Python OpenCV图像模糊处理分析”。内容详细易懂,对“如何进行Python OpenCV图像模糊处理分析”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有...
      99+
      2023-06-26
    • sql中如何进行拼接
      sql 中可使用多种方法进行字符串拼接,包括使用连接运算符 (+)、concat 函数、|| 运算符(oracle 和 mysql)、format 函数(sql server)和 stu...
      99+
      2024-05-09
      mysql oracle
    • Python如何使用OpenCV对图像进行缩放功能
      这篇文章主要介绍了Python如何使用OpenCV对图像进行缩放功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。OpenCV:图片缩放和图像金字塔对图像进行缩放的最简单方法...
      99+
      2023-06-29
    • C++ OpenCV如何生成蒙太奇图像
      这篇文章主要介绍“C++ OpenCV如何生成蒙太奇图像”,在日常操作中,相信很多人在C++ OpenCV如何生成蒙太奇图像问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++ ...
      99+
      2023-06-26
    • 如何利用Python和OpenCV对图像进行加水印详解
      目录前言🌌 第 1 步:导入 OpenCV 并读取logo和要应用水印的图像💨 第 2步:计算两个图像的高度和宽度🚀 第 3 步:将水...
      99+
      2024-04-02
    • css如何在页面上对背景图像进行平铺
      这篇文章主要为大家展示了“css如何在页面上对背景图像进行平铺”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“css如何在页面上对背景图像进行平铺”这篇文章吧。 ...
      99+
      2024-04-02
    • C++ OpenCV如何实现图像修复功能
      本篇文章给大家分享的是有关C++ OpenCV如何实现图像修复功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。前言下面将使用OpenCV C++ 对有瑕疵的图像进行...
      99+
      2023-06-26
    • 如何在C#项目中利用OpenCV对图片中人物的头像进行剪切
      这篇文章主要介绍了如何在C#项目中利用OpenCV对图片中人物的头像进行剪切,此处给大家介绍的非常详细,对大家的学习或工作具有一定的参考价值,需要的朋友可以参考下:准备工作首先创建一个Wpf项目——OpenCV_Face_Wpf,这里版本使...
      99+
      2023-06-06
    • css中如何在页面上对背景图像进行平铺
      小编给大家分享一下css中如何在页面上对背景图像进行平铺,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! 要是须要在页面上对背景...
      99+
      2024-04-02
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作