OpenCV开发笔记(七十九):基于Stitcher类实现全景图片拼接

news/2024/9/20 17:34:37/文章来源:https://www.cnblogs.com/qq21497936/p/18380860

前言

  一个摄像头视野不大的时候,我们希望进行两个视野合并,这样让正视的视野增大,从而可以看到更广阔的标准视野。拼接的方法分为两条路,第一条路是stitcher类,第二条思路是特征点匹配。
  本篇使用stitcher匹配,进行两张图来视野合并拼接。

 

Demo

  在这里插入图片描述

 

两张图拼接过程

步骤一:打开图片

  在这里插入图片描述

cv::Mat mat = cv::imread("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/29.jpg");
cv::Mat mat2 = cv::imread("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/30.jpg");

步骤二:加入图片进入队列

  在这里插入图片描述

std::vector<cv::Mat> vectorMat;
vectorMat.push_back(mat);
vectorMat.push_back(mat2);

步骤三:创建拼接类

  在这里插入图片描述

cv::Ptr<cv::Stitcher> pStitcher = cv::Stitcher::create(cv::Stitcher::PANORAMA, false);
//cv::Ptr<cv::Stitcher> pStitcher = cv::Stitcher::create(cv::Stitcher::SCANS, false);

步骤四:拼接

  在这里插入图片描述

cv::Ptr<cv::Stitcher> pStitcher = cv::Stitcher::create(cv::Stitcher::SCANS, false);
LOG;
cv::Stitcher::Status status = pStitcher->stitch(vectorMat, resultMat);
LOG;
if(status != cv::Stitcher::OK)
{std::cout << "Failed to stitch, status =" << status << std::endl;return;
}

  对拼接后显示所有:
  在这里插入图片描述

cv::namedWindow("mat", cv::WINDOW_NORMAL);
cv::imshow("mat", mat);
cv::resizeWindow("mat", cv::Size(400, 300));cv::namedWindow("mat2", cv::WINDOW_NORMAL);
cv::imshow("mat2", mat2);
cv::resizeWindow("mat2", cv::Size(400, 300));cv::namedWindow("resultMat", cv::WINDOW_NORMAL);
cv::imshow("resultMat", resultMat);
cv::resizeWindow("resultMat", cv::Size(400, 300));

步骤五:对图像进行宽高黑边裁剪(略)

  直接写个算法对周边黑色区域进行矩形探测,然后裁剪即可,方法很多,一般我们拍照的图片都不是全黑的,而黑边是全黑的,这个算法写起来有明显的特征。

 

耗时测试

原始图像1701x1280像素,耗时477ms左右

  在这里插入图片描述

  在这里插入图片描述

  原始图片1701x1280像素,拼接消耗的时间约477ms:

图像缩小至400x300像素,耗时390ms左右

  然后对其图片进行缩放后测试其耗时:
  在这里插入图片描述

  在这里插入图片描述

  将图片统一缩放为800x600分辨率,其拼接耗时在390ms左右。

图像放大至1920x1080像素,耗时530ms左右

  在这里插入图片描述

  在这里插入图片描述

  将图片放大至1920x1080分辨率,其拼接耗时在530ms左右

注意

  本次测试并不严谨,基于同样图的缩放,单纯控制像素缩放来比较,但是得出的结论可以反应图像大小的影响,最终的耗时是受多方因素影响,包括但不限于检测特征电的数量、重叠区域的大小、像素分辨率、多图。

结论

  这种方式适合对照片进行拼接,对黑边处理之后,效果很不错,但是,调用stitcher类实现时对图片的特征匹配有要求,一些特征点不够的图片无法拼接,并且,当图片较大或多张图片拼接时,速度慢。所以,倘若放到视频上,一秒钟25-60fps,那就肯定不行了。
  SIFT算法拼接,SIFT算法可以提供较高的准确率,得到的图片需要经过再次处理,才能得到相对较好的图片,
  ORB算法拼接,算法的速度非常快,但是最容易出现问题,且得到的图片需要经过再次处理,才能得到相对较好的图片,

 

函数原型

函数cv::Stitcher::create

static Ptr<Stitcher> create(Mode mode = PANORAMA, bool try_use_gpu = false);
  • 参数一:拼接模式枚举,只有2个值PANORAMA和SCANS
    PANORAMA:创建照片全景的模式,期望图像处于透视状态;
    SCANS:合成扫描的模式。期望仿射变换下的图像,默认情况下不补偿曝光。(由于咱们一般总归有角度偏移,所以这个方式对拼接图像有较高要求)
  • 参数二:是否使用gpu,这种方式编译opencv得带上gpu编译,编译opencv的时候开启支持gpu,在arm上的话,需要先确认芯片是否支持GPU,然后安装GPU驱动,然后编译opencv支持GPU选项,才可以。

函数cv::Stitcher:: stitch

CV_WRAP Status stitch(InputArrayOfArrays images, OutputArray pano);
  • 参数一:输入图像列表
  • 参数二:输出拼接结果
Status stitch(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois, OutputArray pano);
  • 参数一:输入图像列表
  • 参数二:输入图像列表依次需要拼接的区域
  • 参数三:输出拼接结果
 

Demo源码

void OpenCVManager::testStitchImages()
{cv::Mat mat = cv::imread("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/29.jpg");cv::Mat mat2 = cv::imread("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/30.jpg");#if 0// 拼接环视全景,特征点是完全不够,无法使用该方法,同时就算能拼也无法达到新能要求cv::Mat mat = cv::imread("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/front_2024-08-22_17-15-08_result.png");cv::Mat mat2 = cv::imread("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/left_2024-08-22_17-15-10_result.png");cv::Mat mat2 = cv::imread("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/right_2024-08-22_17-15-11_result.png");
#endif#if 1// 对图片进行缩放,测试其拼接耗时cv::resize(mat, mat, cv::Size(1920, 1080));cv::resize(mat2, mat2, cv::Size(1920, 1080));
#endifstd::vector<cv::Mat> vectorMat;vectorMat.push_back(mat);vectorMat.push_back(mat2);cv::Mat resultMat;cv::Ptr<cv::Stitcher> pStitcher = cv::Stitcher::create(cv::Stitcher::PANORAMA, false);
//    cv::Ptr<cv::Stitcher> pStitcher = cv::Stitcher::create(cv::Stitcher::SCANS, false);LOG;cv::Stitcher::Status status = pStitcher->stitch(vectorMat, resultMat);LOG;if(status != cv::Stitcher::OK){std::cout << "Failed to stitch, status =" << status << std::endl;return;}cv::namedWindow("mat", cv::WINDOW_NORMAL);cv::imshow("mat", mat);cv::resizeWindow("mat", cv::Size(400, 300));cv::namedWindow("mat2", cv::WINDOW_NORMAL);cv::imshow("mat2", mat2);cv::resizeWindow("mat2", cv::Size(400, 300));cv::namedWindow("resultMat", cv::WINDOW_NORMAL);cv::imshow("resultMat", resultMat);cv::resizeWindow("resultMat", cv::Size(400, 300));cv::waitKey(0);
}
 

对应工程模板v1.69.0

  在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/787502.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF 路由事件

一、什么是路由事件? 根据MSDN定义:功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。 实现定义:路由事件是由 类的实例支持的 CLR 事件, RoutedEvent 由事件 Windows Presentation Foundation (WPF) 系统处理。…

【转载】Win11优化大小核调度(无需重启)

出处:https://bbs.saraba1st.com/2b/thread-2140520-1-1.html 打开隐藏电源管理选项: 管理员模式运行cmd,分别输入: powercfg -attributes SUB_PROCESSOR 7f2f5cfa-f10c-4823-b5e1-e93ae85f46b5 -ATTRIB_HIDE powercfg -attributes SUB_PROCESSOR 93b8b6dc-0698-4d1c-9ee4-…

【Pytorch教程】迅速入门Pytorch深度学习框架

@目录前言1.tensor基础操作1.1 tensor的dtype类型1.2 创建tensor(建议写出参数名字)1.2.1 空tensor(无用数据填充)API示例1.2.2 全一tensor1.2.3 全零tensor1.2.4 随机值[0,1)的tensor1.2.5 随机值为整数且规定上下限的tensorAPI示例1.2.6 随机值均值0方差1的tensor1.2.7 从…

AMD显卡VGA转HDMI花屏或者雪花屏解决办法

本以为是显卡或者显示屏或者转接线有问题,查阅资料后得出VGA转HDMI花屏或者雪花屏解决办法: 进入AMD控制面板。点击设置 - > 显示器 - > 覆盖 - > 禁用HDCP 即可完美解决问题。

AIGC时代,如何为“数据飞轮”提速

本文从技术角度,具体拆解DataLeap-找数助手、开发助手的实现方式,详AIGC如何为企业数智化转型赋能。更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 企业通过数智化转型实现降本增效,已经成为行业共识。而随着AIGC时代到来,企业的…

windows 安装nginx

1.进入下载页面下载window版本 安装 2.解压, 直接运行 exe就行 3.使用nssm 将exe文件 作为服务运行 4.配置conf/nginx.conf 的配置文件

使用yum命令报错

报错如下Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=stock error was 14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown error"One of the configured repositories fai…

EXITS:基于极值点低标注成本弱监督实例分割 | CVPR 2024

EXITS将极值点视为真实实例掩模的一部分并将它们传播以识别潜在前景和背景点,所有这些都用于训练伪标签生成器,然后由生成器给出的伪标签反过来用于最终模型的监督学习。 来源:晓飞的算法工程笔记 公众号论文: Extreme Point Supervised Instance Segmentation论文地址:htt…

Swahili-text:华中大推出非洲语言场景文本检测和识别数据集 | ICDAR 2024

论文提出了一个专门针对斯瓦希里语自然场景文本检测和识别的数据集,这在当前研究中是一个未充分开发的语言领域。数据集包括976张带标注的场景图像,可用于文本检测,以及8284张裁剪后的图像用于识别。 来源:晓飞的算法工程笔记 公众号论文: The First Swahili Language Scen…

Codeforces Round 968 (Div. 2)

良心出题人给了中文题解!!! A. Turtle and Good Strings 长度为 \(n\) 的字符串至少分成两段,使 \(\forall i < j\) ,第 \(i\) 段的首字符不等于第 \(j\) 段的尾字符 第一个字符一定作为首字符,最后一个字符一定作为尾字符,只要判断这两个字符是否相等即可 相等的话一…

【日记】这个月花了好多钱(1317 字)

正文这几天都好热。热到人不想动,只想睡觉。今天写文章发现自己有个很显著的特点,就是在有个框架之后,具体细节完全没有预设。我只能像马尔可夫链一样,形成一个比较窄的窗口,接着这个窗口里的情节往下写,否则我就会宕机,写不出来。整个故事情节看起来也就比较散。马尔可…

个人博客导航如何创建更有个性化?

个人博客导航如何创建更有个性化?创建个性化博客导航是一个既实用又能体现个人风格的过程。以下是一些步骤和建议,帮助你完成这一过程:一、确定导航需求和内容明确目的:首先,你需要明确博客导航的主要目的是什么,比如是为了方便读者查找特定内容、展示你的博客结构,还是…