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;  

}

拼接后图像如下所示。

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-04-20 10:24:06       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-20 10:24:06       20 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-20 10:24:06       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-20 10:24:06       20 阅读

热门阅读

  1. 多语言vue-i18n (vue2,uniapp)

    2024-04-20 10:24:06       10 阅读
  2. 62、ARM/STM32开发板按键中断相关学习20240416

    2024-04-20 10:24:06       14 阅读
  3. 单例设计模式

    2024-04-20 10:24:06       17 阅读
  4. Linux配置为路由器

    2024-04-20 10:24:06       12 阅读
  5. Spring Boot 定时任务实现教程

    2024-04-20 10:24:06       13 阅读
  6. MyBatis

    MyBatis

    2024-04-20 10:24:06      10 阅读
  7. CDN的原理

    2024-04-20 10:24:06       15 阅读
  8. Git

    2024-04-20 10:24:06       11 阅读
  9. Python脚本传参 -h --help

    2024-04-20 10:24:06       14 阅读
  10. 【C++ 哈希应用】

    2024-04-20 10:24:06       17 阅读
  11. mysql根据datetime统计每日数据量

    2024-04-20 10:24:06       13 阅读