使用C/C++和OpenCV实现图像拼接

news2025/6/7 11:31:36

使用 C++ 和 OpenCV 实现图像拼接

本文将详细介绍如何利用 OpenCV 库,在 C++ 环境中实现图像拼接。图像拼接技术可以将多张具有重叠区域的图像合成为一张高分辨率的全景图。OpenCV 提供了一个功能强大的 Stitcher 类,它封装了从特征点检测、匹配到图像融合的完整流程,使我们能够用非常简洁的代码实现复杂的拼接功能。

准备工作

在开始编码之前,请确保您的开发环境满足以下条件:

  • C++ 编译器: 例如 G++, Clang, 或 MSVC (Visual Studio)。
  • OpenCV 库: 确保已在您的系统中成功安装并配置好。本文示例代码基于 OpenCV 3.x 或更高版本。您需要包含 stitching 模块,在某些预编译版本中,它可能位于 opencv_contrib 中。
  • 一组用于拼接的图像: 准备一组从同一视点拍摄、有重叠区域的图像。将它们按顺序(例如,从左到右)命名并放置在项目文件夹中(例如 1.jpg, 2.jpg, 3.jpg)。

包含头文件和命名空间

首先,我们需要在 C++ 源文件中包含必要的头文件。核心功能位于 opencv2/stitching.hpp

#include <iostream>
#include <vector>
#include "opencv2/opencv.hpp"
#include "opencv2/stitching.hpp"

// 使用 OpenCV 和 std 命名空间
using namespace std;
using namespace cv;

拼接流程详解

整个拼接过程可以分解为以下几个核心步骤。Stitcher 类为我们自动处理了这些步骤。

1. 读取输入图像

第一步是将所有待拼接的图像加载到一个 std::vector<Mat> 容器中。Mat 是 OpenCV 中用于表示图像的核心数据结构。

int main(int argc, char* argv[]) {
    // 检查命令行参数,确保至少有两张输入图像
    if (argc < 3) {
        cout << "用法: ./stitcher <图片1> <图片2> [图片3] ..." << endl;
        return -1;
    }

    // 创建一个 Mat 向量来存储所有待拼接的图像
    vector<Mat> imgs;
    for (int i = 1; i < argc; ++i) {
        Mat img = imread(argv[i]);
        // 检查图像是否成功加载
        if (img.empty()) {
            cout << "无法读取图像: " << argv[i] << endl;
            return -1;
        }
        imgs.push_back(img);
    }

    // 用于存储最终拼接结果的 Mat 对象
    Mat pano;

2. 创建 Stitcher 并执行拼接

这是整个流程的核心。我们通过 Stitcher::create 工厂方法创建一个 Stitcher 对象。然后,只需调用其 stitch 方法,并将图像向量和用于接收结果的 Mat 对象作为参数传入即可。

stitch 方法会返回一个状态码,我们可以通过它来判断拼接是否成功。

    // 创建 Stitcher 类的实例
    // Stitcher::PANORAMA 是为创建全景图优化的模式
    Ptr<Stitcher> stitcher = Stitcher::create(Stitcher::PANORAMA);

    // 调用 stitch 方法执行拼接
    cout << "开始拼接..." << endl;
    Stitcher::Status status = stitcher->stitch(imgs, pano);

    // 检查拼接是否成功
    if (status != Stitcher::OK) {
        cout << "拼接失败,错误码 = " << int(status) << endl;
        return -1;
    }
    cout << "拼接成功!" << endl;

Stitcher::create 的模式参数可以是 Stitcher::PANORAMA(适用于旋转相机拍摄的全景图,最常用)或 Stitcher::SCANS(适用于扫描文档等平面场景)。

stitch 方法可能返回的错误码包括:

  • OK: 拼接成功。
  • ERR_NEED_MORE_IMGS: 输入图像不足(少于2张)。
  • ERR_HOMOGRAPHY_EST_FAIL: 无法计算单应性矩阵。这通常意味着图像之间的重叠区域太小,或者特征点无法有效匹配。
  • ERR_CAMERA_PARAMS_ADJUST_FAIL: 相机参数调整失败。

3. 保存并显示结果

如果拼接成功,一张完整的全景图就会被存储在 pano 这个 Mat 对象中。我们可以使用 imwrite 将它保存为图片文件,并使用 imshow 在窗口中显示它。

    // 将结果图像写入文件
    imwrite("panorama_result.jpg", pano);
    cout << "结果已保存至 panorama_result.jpg" << endl;

    // 为了方便在屏幕上显示,可以先将结果缩放
    Mat pano_show;
    // 按比例缩放,例如缩放到原图的 50%
    resize(pano, pano_show, Size(), 0.5, 0.5); 
    
    // 显示结果
    imshow("全景拼接结果 (按任意键退出)", pano_show);

    // 等待用户按键
    waitKey(0);
    destroyAllWindows();

    return 0;
}

完整示例代码

下面是整合了以上所有步骤的完整 C++ 源代码。

#include <iostream>
#include <vector>
#include "opencv2/opencv.hpp"
#include "opencv2/stitching.hpp"

using namespace std;
using namespace cv;

int main(int argc, char* argv[]) {
    // 1. 检查并读取输入图像
    if (argc < 3) {
        cout << "用法: ./stitcher <图片1> <图片2> [图片3] ..." << endl;
        return -1;
    }

    vector<Mat> imgs;
    for (int i = 1; i < argc; ++i) {
        Mat img = imread(argv[i]);
        if (img.empty()) {
            cout << "无法读取图像: " << argv[i] << endl;
            return -1;
        }
        imgs.push_back(img);
    }

    // 用于存储最终拼接结果的 Mat 对象
    Mat pano;

    // 2. 创建 Stitcher 并执行拼接
    cout << "开始拼接..." << endl;
    Ptr<Stitcher> stitcher = Stitcher::create(Stitcher::PANORAMA);
    Stitcher::Status status = stitcher->stitch(imgs, pano);

    if (status != Stitcher::OK) {
        cout << "拼接失败,错误码 = " << int(status) << endl;
        return -1;
    }

    cout << "拼接成功!" << endl;

    // 3. 保存并显示结果
    imwrite("panorama_result.jpg", pano);
    cout << "结果已保存至 panorama_result.jpg" << endl;
    
    // 为了更好地显示,可以先将图像缩放到合适的尺寸
    Mat pano_show;
    // 将宽度调整为1024,高度按比例缩放
    int target_width = 1024;
    double scale = (double)target_width / pano.cols;
    resize(pano, pano_show, Size(target_width, pano.rows * scale));
    
    imshow("全景拼接结果 (按任意键退出)", pano_show);

    waitKey(0);
    destroyAllWindows();

    return 0;
}

如何编译和运行

假设您的源文件名为 stitcher.cpp,并且已经正确配置了 OpenCV 环境。您可以使用以下 g++ 命令进行编译(以 Linux/macOS 为例):

g++ stitcher.cpp -o stitcher `pkg-config --cflags --libs opencv4`

注意: 如果您使用的是 OpenCV 3,请将命令中的 opencv4 改为 opencv。在 Windows + Visual Studio 中,您需要在项目属性中配置包含目录和库目录。

编译成功后,准备好您的图像(例如 img1.jpg, img2.jpg, img3.jpg),然后通过命令行运行程序:

./stitcher img1.jpg img2.jpg img3.jpg

程序执行后,您将在终端看到处理信息。如果一切顺利,拼接后的全景图 panorama_result.jpg 将会保存在当前目录,并弹出一个窗口实时预览结果。

结论

通过使用 OpenCV 的 Stitcher 类,我们可以轻松地实现高质量的图像拼接,而无需深入研究特征匹配、单应性估计和图像融合等底层算法的复杂细节。这使得开发者可以将更多精力集中在应用逻辑上。希望这篇指南能帮助您快速入门并成功构建自己的图像拼接项目。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MATLAB去噪算法】基于ICEEMDAN联合小波阈值去噪算法

ICEEMDAN联合小波阈值去噪算法相关文献 &#xff08;注&#xff1a;目前相关论文较少&#xff0c;应用该套代码可发直接一些水刊&#xff09; 一、CEEMDAN的局限性 模式残留噪声问题&#xff1a;原始CEEMDAN在计算每个IMF时直接对噪声扰动的信号进行模态分解并平均。 后果&a…

XXTEA,XTEA与TEA

TEA、XTEA和XXTEA都是分组加密算法&#xff0c;它们在设计、安全性、性能等方面存在显著区别。以下是它们的主要区别&#xff1a; 密钥长度 TEA&#xff1a;使用128位密钥。 XTEA&#xff1a;通常使用128位或256位密钥。 XXTEA&#xff1a;密钥长度更灵活&#xff0c;可以使用任…

机器人玩转之---嵌入式开发板基础知识到实战选型指南(包含ORIN、RDK X5、Raspberry pi、RK系列等)

1. 基础知识讲解 1.1 什么是嵌入式开发板&#xff1f; 嵌入式开发板是一种专门设计用于嵌入式系统开发的硬件平台&#xff0c;它集成了微处理器、内存、存储、输入输出接口等核心组件于单块印刷电路板上。与传统的PC不同&#xff0c;嵌入式开发板具有体积小、功耗低、成本适中…

腾讯云国际版和国内版账户通用吗?一样吗?为什么?

在当今全球化的数字化时代&#xff0c;云计算服务成为众多企业和个人拓展业务、存储数据的重要选择。腾讯云作为国内领先的云服务提供商&#xff0c;其国际版和国内版备受关注。那么&#xff0c;腾讯云国际版和国内版账户是否通用&#xff1f;它们究竟一样吗&#xff1f;背后又…

OrCAD X Capture CIS设计小诀窍系列第二季--03.如何在Capture中输出带有目录和元器件信息的PDF

背景介绍&#xff1a;我们在进行原理图设计时&#xff0c;经常需要输出PDF来查看或评审&#xff0c;但通过”Print”功能导出的PDF较为简单&#xff0c;只能查看设计视图&#xff1b;而通过使用Ghostscript软件可以输出带有目录和元器件信息的PDF&#xff0c;让设计师可以直接在…

汽车的安全性能测试:试验台铁地板的重要性

汽车的安全性能测试是非常重要的&#xff0c;其中试验台铁地板的设计和材料选择起着至关重要的作用。试验台铁地板是指在进行汽车碰撞、侧翻等试验时&#xff0c;用于支撑汽车底部和提供稳定支撑的重要部件。 在进行汽车碰撞试验时&#xff0c;试验台铁地板的设计和材料需要具…

实践指南:从零开始搭建RAG驱动的智能问答系统

LLM 赋能的最强大的应用之一是复杂的问答 (Q&A) 聊天机器人。这些是可以回答关于特定来源信息问题的应用程序。这些应用程序使用一种称为检索增强生成的技术&#xff0c;或 RAG。本文将展示如何基于 LangChain 构建一个简单的基于非结构化数据文本数据源的问答应用程序。 温…

边缘计算服务器

边缘计算服务器的核心要点解析&#xff0c;综合技术架构、应用场景与部署方案&#xff1a; 一、核心定义与技术特性‌ 本质定位‌ 部署在网络边缘侧的专用计算设备&#xff08;如工厂车间、智慧路灯等&#xff09;&#xff0c;直接处理终端设备&#xff08;传感器、摄像头等…

第R9周:阿尔茨海默病诊断(优化特征选择版)

文章目录 1. 导入数据2. 数据处理2.1 患病占比2.2 相关性分析2.3 年龄与患病探究 3. 特征选择4. 构建数据集4.1 数据集划分与标准化4.2 构建加载 5. 构建模型6. 模型训练6.1 构建训练函数6.2 构建测试函数6.3 设置超参数 7. 模型训练8. 模型评估8.1 结果图 8.2 混淆矩阵9. 总结…

电动螺丝刀-多实体拆图建模案例

多实体建模要注意下面两点&#xff1a; 多实体建模的合并结果一定要谨慎在实际工作中多实体建模是一个非常好的思路&#xff0c;先做产品的整体设计&#xff0c;再将个体零件导出去做局部细节设计 电动螺丝刀模型动图展示 爆炸视图动图展示 案例素材点击此处获取 建模步骤 1. …

当丰收季遇上超导磁测量:粮食产业的科技新征程

麦浪藏光阴&#xff0c;心田种丰年&#xff01;又到了一年中最令人心潮澎湃的粮食丰收季。金色的麦浪随风翻滚&#xff0c;沉甸甸的稻穗谦逊地低垂着&#xff0c;处处洋溢着丰收的喜悦。粮食产业&#xff0c;无疑是国家发展的根基与命脉&#xff0c;是民生稳定的压舱石。在现代…

电子电气架构 --- 什么是功能架构?

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

AudioRelay 0.27.5 手机充当电脑音响

—————【下 载 地 址】——————— 【​本章下载一】&#xff1a;https://pan.xunlei.com/s/VOS4MvfPxrnfS2Zu_YS4egykA1?pwdi2we# 【​本章下载二】&#xff1a;https://pan.xunlei.com/s/VOS4MvfPxrnfS2Zu_YS4egykA1?pwdi2we# 【百款黑科技】&#xff1a;https://uc…

NVIDIA Dynamo:数据中心规模的分布式推理服务框架深度解析

NVIDIA Dynamo&#xff1a;数据中心规模的分布式推理服务框架深度解析 摘要 NVIDIA Dynamo是一个革命性的高吞吐量、低延迟推理框架&#xff0c;专为在多节点分布式环境中服务生成式AI和推理模型而设计。本文将深入分析Dynamo的架构设计、核心特性、代码实现以及实际应用示例&…

第十三节:第四部分:集合框架:HashMap、LinkedHashMap、TreeMap

Map集合体系 HashMap集合的底层原理 HashMap集合底层是基于哈希表实现的 LinkedHashMap集合的底层原理 TreeMap集合的底层原理 代码&#xff1a; Student类 package com.itheima.day26_Map_impl;import java.util.Objects;public class Student implements Comparable<Stu…

Spring AI之RAG入门

目录 1. 什么是RAG 2. RAG典型应用场景 3. RAG核心流程 3.1. 检索阶段 3.2. 生成阶段 4. 使用Spring AI实现RAG 4.1. 创建项目 4.2. 配置application.yml 4.3. 安装ElasticSearch和Kibana 4.3.1. 安装并启动ElasticSearch 4.3.2. 验证ElasticSearch是否启动成功 …

应用案例 | 设备分布广, 现场维护难? 宏集Cogent DataHub助力分布式锅炉远程运维, 让现场变“透明”

在日本&#xff0c;能源利用与环保问题再次成为社会关注的焦点。越来越多的工业用户开始寻求更高效、可持续的方式来运营设备、管理能源。而作为一家专注于节能与自动化系统集成的企业&#xff0c;日本大阪的TESS工程公司给出了一个值得借鉴的答案。 01 锅炉远程监控难题如何破…

LINUX 66 FTP 2 ;FTP被动模式;FTP客户服务系统

19&#xff0e; 在vim中将所有 abc 替换为 def&#xff0c;在底行模式下执行©&#xff1f;D A、s/abc/def B、s/abc/def/g C、%s/abc/def D、%s/abc/def/g FTP连接 用户名应该填什么 [rootcode ~]# grep -v ^# /etc/vsftpd/vsftpd.conf anonymous_enableNO local_enab…

网心云 OEC/OECT 笔记(2) 运行RKNN程序

目录 网心云 OEC/OECT 笔记(1) 拆机刷入Armbian固件网心云 OEC/OECT 笔记(2) 运行RKNN程序 RKNN OEC/OEC-Turbo 使用的芯片是 RK3566/RK3568, 这个系列是内建神经网络处理器 NPU 的, 利用 RKNN 可以部署运行 AI 模型利用 NPU 硬件加速模型推理. 要使用 NPU, 首先需要在电脑使…

灵活控制,modbus tcp转ethernetip的 多功能水处理方案

油田自动化和先进的油气行业软件为油气公司带来了诸多益处。其中包括&#xff1a; 1.自动化可以消除多余的步骤、减少人为错误并降低运行设备所需的能量&#xff0c;从而降低成本。 2.油天然气行业不断追求高水平生产。自动化可以更轻松地减少计划外停机时间&#xff0c;从而…