热门标签 | HotTags
当前位置:  开发笔记 > 程序员 > 正文

opencv基于sift的多张图片全景图拼接

这里是基于sift来寻找特征点经行图像的匹配的原理来进行图像拼接的,具体步骤如下:1、利用sift特征探测器来检测出两幅图片的sift特征点2、根据上一步提取到的特征点来提取特征

这里是基于sift来寻找特征点经行图像的匹配的原理来进行图像拼接的,具体步骤如下:

1、利用sift特征探测器来检测出两幅图片的sift特征点

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
Mat Stitched(Mat img1, Mat img2) {
Mat g1(img1, Rect(0, 0, img1.cols, img1.rows));
Mat g2(img2, Rect(0, 0, img2.cols, img2.rows));
cvtColor(g1, g1, CV_BGR2GRAY);
cvtColor(g2, g2, CV_BGR2GRAY);
SiftFeatureDetector siftdet;
vectorkp1, kp2;
//SIFT sift;
SiftDescriptorExtractor extractor;
Mat descriptor1, descriptor2;
FlannBasedMatcher matcher;
vector matches, goodmatches;
/*进行特征点提取*/
siftdet.detect(g1, kp1);
siftdet.detect(g2, kp2);
/* 进行特征向量提取 */
extractor.compute(g1, kp1, descriptor1);
extractor.compute(g2, kp2, descriptor2);
/* 进行特征向量临近匹配 */
matcher.match(descriptor1, descriptor2, matches);
Mat firstmatches;
/*画出第一次匹配的结果*/
drawMatches(img1, kp1, img2, kp2,
matches, firstmatches, Scalar::all(-1), Scalar::all(-1),
vector(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
imshow("first_matches", firstmatches);
/* 下面计算向量距离的最大值与最小值 */
double max_dist = 0; double min_dist = 1000;
for (int i = 0; i if (matches[i].distance > max_dist) {
max_dist = matches[i].distance;
}
if (matches[i].distance min_dist = matches[i].distance;
}
}
cout <<"The max distance is: " < cout <<"The min distance is: " < for (int i = 0; i if (matches[i].distance <2 * min_dist) {
goodmatches.push_back(matches[i]);
}
}
Mat img_matches;
/*第二次筛选后的结果*/
drawMatches(img1, kp1, img2, kp2,
goodmatches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
imshow("good_matches", img_matches);
vector keypoints1, keypoints2;
for (int i = 0; i keypoints1.push_back(kp1[goodmatches[i].queryIdx].pt);
keypoints2.push_back(kp2[goodmatches[i].trainIdx].pt);
}
/*计算单应矩阵*/
Mat H = findHomography(keypoints1, keypoints2, CV_RANSAC);
Mat stitchedImage;
int mRows = img2.rows;
if (img1.rows> img2.rows)
{
mRows = img1.rows;
}
/*判断图像在左边还是在右边*/
int propimg1 = 0, propimg2 = 0;
for (int i = 0; i if (kp1[goodmatches[i].queryIdx].pt.x > img1.cols / 2) {
propimg1++;
}
if (kp2[goodmatches[i].trainIdx].pt.x > img2.cols / 2) {
propimg2++;
}
}
bool flag = false;
Mat imgright;
Mat imgleft;
if ((propimg1 / (goodmatches.size() + 0.0)) > (propimg2 / (goodmatches.size() + 0.0))) {
imgleft = img1.clone();
flag = true;
}
else {
imgleft = img2.clone();
flag = false;
}
if (flag) {
imgright = img2.clone();
flag = false;
}
else {
imgright = img1.clone();
}
/*把上边求得的右边的图像经过矩阵H转换到stitchedImage中对应的位置*/
warpPerspective(imgright, stitchedImage, H, Size(img2.cols + img1.cols, mRows));
/*把左边的图像放进来*/
Mat half(stitchedImage, Rect(0, 0, imgleft.cols, imgleft.rows));
imgleft.copyTo(half);
return stitchedImage;
}
int main() {
Mat img1 = imread("1.jpg");
Mat stitchedImage;
int n;
cout <<"Dataset2" < cout <<"请输入想拼接的图片数量(大于1小于18)" < cin >> n;
cout <<"输入成功,开始计时" < clock_t start,finish;
double totaltime;
start=clock();
resize(img1, img1, Size(img1.cols / 4, img1.rows / 4));
for (int k = 2; k <= n; k++) {
stringstream stream;
string str;
stream < stream >> str;
string filename = str + ".jpg";
cout <<"正在拼接......." < Mat img = imread(filename);
resize(img, img, Size(img.cols / 4, img.rows / 4));
stitchedImage = Stitched(img1, img);
img1 = stitchedImage;
}
finish = clock();
totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
cout <<"拼接成功" < cout <<"拼接花费总时间为:" < imshow("ResultImage", stitchedImage);
imwrite("ResultImage.jpg", stitchedImage);
waitKey(0);
return 0;
}


推荐阅读
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • RT,个人博客图片管理(方便管理,大家 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • 帝国CMS多图上传插件详解及使用指南
    本文介绍了一款用于帝国CMS的多图上传插件,该插件通过Flash技术实现批量图片上传功能,显著提升了多图上传效率。文章详细说明了插件的安装、配置和使用方法。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 百度服务再次遭遇技术问题,疑似DNS解析故障
    近日晚间,百度多项在线服务出现加载异常,包括移动端搜索在内的多个功能受到影响。初步迹象表明,问题可能与DNS服务器解析有关。 ... [详细]
  • 本文详细介绍了《问道》手游在2020年12月31日进行的服务器维护情况,以及此次更新中新增的跨年狂欢活动和寒假活动等内容。同时,文章还涵盖了其他重要的系统优化与修复信息。 ... [详细]
  • Win11扩展卷无法使用?解决扩展卷灰色问题的指南
    本文详细介绍了在Windows 11中遇到扩展卷灰色无法使用时的解决方案,帮助用户快速恢复磁盘扩展功能。 ... [详细]
  • 掌握 Photoshop 是学习网页设计的重要一步。本文将详细介绍 Photoshop 的基础与进阶功能,帮助您更好地进行图像处理和网页设计。推荐使用最新版本的 Photoshop,以体验更强大的功能和更高的效率。 ... [详细]
  • 本文介绍如何使用Python进行文本处理,包括分词和生成词云图。通过整合多个文本文件、去除停用词并生成词云图,展示文本数据的可视化分析方法。 ... [详细]
  • Python实现照片磨皮效果
    本文介绍如何使用Python和OpenCV库来实现照片的磨皮效果,使图片更加平滑并提升整体美感。 ... [详细]
  • 深入解析三大范式与JDBC集成
    本文详细探讨了数据库设计中的三大范式,并结合Java数据库连接(JDBC)技术,讲解如何在实际开发中应用这些概念。通过实例和图表,帮助读者更好地理解范式理论及其在数据操作中的重要性。 ... [详细]
author-avatar
我就是个2丶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有