OpenCV杂记(2):图像拼接(hconcat, vconcat)

OpenCV杂记(1):绘制OSD(cv::getTextSize, cv::putText)icon-default.png?t=N7T8https://blog.csdn.net/tecsai/article/details/137872058

 

1. 简述

        做图像处理或计算机视觉技术的同学都知道,我们在工作中会经常遇到需要将两幅图像拼接成为一幅图像,或者将四幅图像拼接成为一个2*2马赛克图像的需求。

        OpenCV提供了多种图像拼接的API,包括水平拼接cv:hconcat,垂直拼接cv::vconcat。此外,还可以通过创建一张大图,然后使用copyTo接口将小图像依次覆盖的形式进行拼接。

        假设我们有四张图,我们想对他们执行垂直拼接、水平拼接以及Mosaic拼接,接下来我们将依次进行讲解。

2. API原型

(1)垂直拼接

void cv::vconcat(InputArray src1, InputArray src2, OutoutArray dst)

该API接口接收两幅图像src1和src2,输出经过拼接后的图像dst。

cv::vconcat还有另外一个接口,接收多张图像进行垂直拼接。

void cv::vconcat(const Mat* src, size_t nsrc, OutputArray dst);

此处的src是一个Mat列表。

(2)水平拼接

void cv::hconcat(InputArray src1, InputArray src2, OutoutArray dst)

void cv::hconcat(const Mat* src, size_t nsrc, OutputArray dst)

3. 垂直拼接

OpenCV提供了快速垂直拼接接口cv::vconcat,该接口接受两个宽度相同的子图像进行拼接,拼接后的高度是两幅子图像的高度和。

如下代码演示了如何调用cv::vconcat进行图像拼接操作。

#include <iostream>

#include <sstream>

#include <fstream>


#include <opencv2/core/core.hpp>

#include <opencv2/imgproc/imgproc.hpp>    

#include <opencv2/imgproc/types_c.h>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/highgui/highgui_c.h>

using namespace std;

int main(int argc, char* argv[])

{

    cv::Mat img_0 = cv::imread("000001.jpg", cv::IMREAD_UNCHANGED);

    cv::Mat img_1 = cv::imread("000002.jpg", cv::IMREAD_UNCHANGED);

    cv::Mat img_2 = cv::imread("000003.jpg", cv::IMREAD_UNCHANGED);

    cv::Mat img_3 = cv::imread("000004.jpg", cv::IMREAD_UNCHANGED);

    if (img_0.empty() || img_1.empty() || img_2.empty() || img_3.empty()){

        cout << "Error: Could not load image." << endl;

        return 0;

    }

   

    /** 图像竖向拼接. */

    cv::Mat vconcat_mat_0;

    cv::vconcat(img_0, img_1, vconcat_mat_0);

    std::cout << "img_0.size: (" << img_0.cols << ", " << img_0.rows << ")" << std::endl;

    std::cout << "img_1.size: (" << img_1.cols << ", " << img_1.rows << ")" << std::endl;

    std::cout << "vconcat_mat_0.size: (" << vconcat_mat_0.cols << ", " << vconcat_mat_0.rows << ")" << std::endl;

    cv::imwrite("./vconcat_mat_0.jpg", vconcat_mat_0);

    /**

     * img_0.size: (1920, 1080)

     * img_1.size: (1920, 1080)

     * vconcat_mat_0.size: (1920, 2160)

    */

    return 0;

}

经过垂直拼接后的图像如下。

4. 水平拼接

水平拼接接收两幅高度相同的子图像,拼接后的图像宽度等于两幅子图像的宽度和。

#include <iostream>

#include <sstream>

#include <fstream>


#include <opencv2/core/core.hpp>

#include <opencv2/imgproc/imgproc.hpp>    

#include <opencv2/imgproc/types_c.h>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/highgui/highgui_c.h>


using namespace std;

int main(int argc, char* argv[])

{

    cv::Mat img_0 = cv::imread("000001.jpg", cv::IMREAD_UNCHANGED);

    cv::Mat img_1 = cv::imread("000002.jpg", cv::IMREAD_UNCHANGED);

    cv::Mat img_2 = cv::imread("000003.jpg", cv::IMREAD_UNCHANGED);

    cv::Mat img_3 = cv::imread("000004.jpg", cv::IMREAD_UNCHANGED);

    if (img_0.empty() || img_1.empty() || img_2.empty() || img_3.empty()){

        cout << "Error: Could not load image." << endl;

        return 0;

    }

    /** 图像横向拼接. */

    cv::Mat hconcat_mat_0;

    cv::hconcat(img_2, img_3, hconcat_mat_0);

    std::cout << "img_2.size: (" << img_2.cols << ", " << img_2.rows << ")" << std::endl;

    std::cout << "img_3.size: (" << img_3.cols << ", " << img_3.rows << ")" << std::endl;

    std::cout << "hconcat_mat_0.size: (" << hconcat_mat_0.cols << ", " << hconcat_mat_0.rows << ")" << std::endl;

    cv::imwrite("./hconcat_mat_0.jpg", hconcat_mat_0);

    /**

     * img_0.size: (1920, 1080)

     * img_1.size: (1920, 1080)

     * hconcat_mat_0.size: (1920, 2160)

    */

    return 0;

}

拼接后的图像如下所示。

5. 灵活拼接

有时候我们并不想在cv::hconcat和cv::vconcat的限制下进行图像拼接,而是想灵活的自定义拼接,此时我们可以使用先构建大图,再粘贴小图的方式。

#include <opencv2/opencv.hpp>  

#include <iostream>  

 

int main(int argc, char* argv[])

{

    /** 读取两张要拼接的图像. */

    cv::Mat img_0 = cv::imread("000001.jpg", cv::IMREAD_UNCHANGED);

    cv::Mat img_1 = cv::imread("000002.jpg", cv::IMREAD_UNCHANGED);

 

    if (img_0.empty() || img_1.empty()) {  

        std::cerr << "Error loading images!" << std::endl;  

        return -1;  

    }  

 

    /** 以水平拼接为例. */

    int height = std::max(img_0.rows, img_1.rows);  

    int width = img_0.cols + img_1.cols;  

 

    /** 创建一个新的空白图像(底图). */

    cv::Mat result(height, width, CV_8UC3, cv::Scalar(255, 255, 255)); // 白色背景  

 

    /** 粘贴第一幅图像. */

    img_0.copyTo(result(cv::Rect(0, 0, img_0.cols, img_0.rows)));  

 

    /** 粘贴第二幅图像. */  

    img_1.copyTo(result(cv::Rect(img_0.cols, 0, img_1.cols, img_1.rows)));  

   

    cv::imwrite("FlexibleMosaic.jpg", result);  

 

    return 0;  

}

拼接后图像如下所示。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot中判断轨迹数据是否经过设置的打卡点,且在PGSQL中把点拼接成线,判断某个点是否在线上或在线的50米范围内

问题描述 轨迹数据判断是否经过打卡点&#xff0c;轨迹数据太多&#xff0c;循环判断的话非常消耗内存。解决办法只需要把所有轨迹数据点拼成了一条线&#xff0c;然后只需要循环打卡点即可&#xff0c;打卡点不多&#xff0c;一般不会超过100个&#xff0c;如果多的话&#x…

苹果手机远程打卡教程

关于苹果手机远程打卡教程之——有电脑零成本版 &#x1f4ce;个人主页&#xff1a;我的主页 &#x1f4ce;小白一枚&#xff0c;欢迎指教&#x1f44f; 嗨嗨嗨&#xff0c;今天来出一期iPhone实现远程打卡的教程&#xff0c;让我们可以随时随地的打卡wherever&#xff5e; 准…

shell进阶之正则表达式:字符转义(十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【深度学习】烟雾和火焰数据集,野外数据集,超大量数据集,目标检测,YOLOv5

标注了2w张数据集&#xff0c;是目标检测yolo格式的&#xff0c;有火焰、烟雾两个目标。 训练方法看这里&#xff1a; https://qq742971636.blog.csdn.net/article/details/138097481 打包 依据不一样的需求&#xff0c; 详情请查看 https://docs.qq.com/sheet/DUEdqZ2l…

在windows系统中安装kafka配置全步骤记录

在windows系统中安装kafka配置全步骤记录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可…

软考高级架构师:AI 通俗讲解负载测试、压力测试、强度测试、容量测试和可靠性测试

在软件工程领域&#xff0c;测试是一个确保软件质量和性能的关键步骤。负载测试、压力测试、强度测试、容量测试和可靠性测试都是性能测试的不同类型&#xff0c;它们的目的和方法有所不同。 下面我将通过简单的比喻和解释&#xff0c;帮助您理解这些测试之间的区别。 负载测试…

Vue阶段练习:tab栏、进度条、

阶段练习旨在学习完Vue 指令、计算属性、侦听器-CSDN博客后&#xff0c;进行自我检测&#xff0c;每个练习分为效果显示、需求分析、静态代码、完整代码、总结 四个部分&#xff0c;效果显示和准备代码已给出&#xff0c;我们需要完成“完整代码”部分。 练习1&#xff1a;tab栏…

3Darray 修改array值然后保存图片

from PIL import Image import numpy as np img_path ./000001.jpg # 读取图片 image Image.open(img_path) width, height image.size print("图片的宽度为{},高度为{}".format(width,height)) print("图片的mode为{}".format(image.mode)) print(&quo…

arm编译、u-boot编译过程、linux内核编译

arm编译 我们之前在linux编译时使用gcc就行,但是在arm中我们需使用arm-linux-gcc 我们需安装交叉编译工具,地址就在119行 若没有,可自行在网上下载 u-boot编译过程 u-boot作为开源项目,可在其官网下载源码,官网 但在实际开发过程中,我们不会直接去u-boot官网下载源码…

STM32F103ZET6 封装 LQFP-144 ST意法 单片机芯片

STM32F103ZET6 是意法半导体&#xff08;STMicroelectronics&#xff09;生产的一款基于 ARM Cortex-M3 内核的 32 位微控制器。它具有高性能、低功耗的特点&#xff0c;广泛应用于各种嵌入式系统和工业应用中。STM32F103ZET6 的主要特点如下&#xff1a; 内核&#xff1a;ARM…

QA测试开发工程师面试题满分问答19: url请求到响应整个过程,涉及到什么技术细节

概述 当你点击鼠标发起一个请求&#xff0c;直到页面显示响应数据&#xff0c;整个过程可以详细展开为以下步骤&#xff1a; 用户点击鼠标&#xff1a;用户在浏览器中点击某个链接或按钮&#xff0c;触发请求的发起。 URL 解析&#xff1a;浏览器解析点击的链接中的 URL&…

力扣数据库题库学习

577. 员工奖金 问题链接 思路分析 Employee表与Bonus表通过empId字段可以连接&#xff0c;需求是查出奖金少于1000的员工名和奖金值。 这里奖金少于1000的情况就是没有奖金有奖金但少于1000 这里我给出的解决方案就是使用左连接&#xff0c;将Employee表作为左表&#xff…

LoRa-Kit 开发板使用介绍

文章目录 前言一、准备二、连接1. 将Ra-03SCH模组焊接到转接板上2. 将转接板插到开发板上3. 将ST-Link v2烧录器与开发板连接4. 将ST-Link v2烧录器和开发板连接到电脑 三、烧录1. 打开STM32烧录工具2. 连接开发板 四、使用步骤1. 打开串口调试助手2. 按下复位键后模组绿色指示…

医学影像图像去噪:滤波器方法、频域方法、小波变换、非局部均值去噪、深度学习与稀疏表示和字典学习

医学影像图像去噪是指使用各种算法从医学成像数据中去除噪声,以提高图像质量和对疾病的诊断准确性。MRI(磁共振成像)和CT(计算机断层扫描)是两种常见的医学成像技术,它们都会受到不同类型噪声的影响。 在医学影像中,噪声可能来源于多个方面,包括成像设备的电子系统、患…

使用Jest测试框架测试JS项目

前言 JavaScript的测试框架有很多&#xff0c;这里主要记录一些自己在初次使用jest时遇到的一些问题。详细使用文档可以参照官方说明文档。 简介 Jest 是一款优雅、简洁的 JavaScript 测试框架。 Jest 支持 Babel、TypeScript、Node、React、Angular、Vue 等诸多框架&#…

使用LVGL提升交互效率:基于启明智显Model3A方案的7寸智能屏用户界面(UI)设计介绍

项目概述&#xff1a; 【启明智显】&#xff0c;作为一家专注于HMI和AIoT解决方案的公司&#xff0c;我们致力于为用户提供创新、可靠且高效的产品和解决方案。近日我们推出了高性能及高性价比的HMI芯片——Model3A。芯片搭载了强大的2D图形加速引擎&#xff0c;能够提供高达7…

Redis入门到通关之Redis数据结构-Hash篇

文章目录 ☃️ 概述☃️底层实现☃️源码☃️其他 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间与空间的平衡&#xff0c;0与1的延伸的后…

书生·浦语大模型-第四节课笔记/作业

笔记 作业 xtuner train ./config/internlm2_chat_7b_qlora_alpaca_e3_copy.py --work-dir ./train微调前效果 微调后效果 微调过程-transformer-lora

C代码求 MD5 值

MD5值常被用于验证数据的完整性&#xff0c;嵌入式开发时经常用到。md5sum命令可以求MD5码&#xff0c;下面介绍如何用C语言实现MD5功能。 一、求字符串MD5值 1、md5sum命令 $ echo -n "12345678" | md5sum //获取"12345678"字符串的md5值 结果&…

(九)Pandas表格样式 学习简要笔记 #Python #CDA学习打卡

目录 一. Pandas表格样式 1&#xff09;举例数据 2&#xff09;字体颜色 3&#xff09;背景高亮 4&#xff09;极值背景高亮 &#xff08;a&#xff09;高亮最大值 highlight_max() &#xff08;b&#xff09;高亮最小值 highlight_min() &#xff08;c&#xff09;同时…