Qt下使用QImage和OpenCV实现图像的拼接与融合

文章目录

  • 前言
  • 一、使用QImage进行水平拼接
  • 二、使用OpenCV进行水平拼接
  • 三、使用OpenCV进行图像融合
  • 四、示例完整代码
  • 总结


前言

本文主要讲述了在Qt下使用QImage和OpenCV实现图像的拼接与融合,并结合相应的示例进行讲解,以便大家学习,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、使用QImage进行水平拼接

这里新建了一个QImage对象,然后通过QPainter来将两张图像绘制在一起,并且可以通过QImage的save函数来保存拼接后的图像:
请添加图片描述

//使用QImage进行水平拼接
QPixmap Widget::imageMosaic(const QImage &image1,const QImage &image2)
{//检查图像是否有效if(image1.isNull() || image2.isNull()){return QPixmap();}//计算拼接后的图像尺寸int newWidth = image1.width() + image2.width();int newHeight = std::max(image1.height(),image2.height());//创建一个新的QImage对象QImage newImage(newWidth,newHeight,QImage::Format_RGB32);newImage.fill(Qt::transparent);   //填充为透明,如果背景不是透明的则可以选择其他颜色//使用QPainter来绘制图像QPainter painter(&newImage);painter.drawImage(0,0,image1);   //在新图像的(0,0)位置绘制第一张图像painter.drawImage(image1.width(),0,image2);   //在新图像的(image1.width(),0)位置绘制第二张图像//结束绘制painter.end();//保存拼接图像newImage.save("E:/myPhoto/imageMosaic.jpg");//返回拼接图像return QPixmap::fromImage(newImage);
}

二、使用OpenCV进行水平拼接

在Qt中配置好OpenCV环境后,就可以使用OpenCV中的hconcat函数来进行图像的拼接了,同时可以使用imwrite来保存拼接图像:
请添加图片描述

//使用OpenCV进行水平拼接
QPixmap Widget::opencvMosaic(const cv::Mat &mat1,const cv::Mat &mat2)
{//检查图像是否有效if(mat1.empty() || mat2.empty()){return QPixmap();}//判断两张图像的高度if(mat1.rows != mat2.rows){return QPixmap();}//水平拼接图像cv::Mat resultMat;cv::hconcat(mat1,mat2,resultMat);//将OpenCV的Mat转换为QImage//cv::cvtColor(resultMat,resultMat,cv::COLOR_BGR2RGB);QImage newImage((const unsigned char*)(resultMat.data),resultMat.cols,resultMat.rows,resultMat.step,QImage::Format_RGB888);//QImage的save保存拼接图像//newImage.save("E:/myPhoto/opencvMosaic.jpg");//OpenCV的imwrite保存拼接图像cv::imwrite("E:/myPhoto/opencvMosaic.jpg",resultMat);//返回拼接图像return QPixmap::fromImage(newImage.rgbSwapped());
}

三、使用OpenCV进行图像融合

这个示例的图像融合比较简单,使用了OpenCV中的addWeighted函数来进行融合:
请添加图片描述

//使用OpenCV进行图像融合
QPixmap Widget::opencvMerge(const cv::Mat &mat1,const cv::Mat &mat2)
{//检查图像是否有效if(mat1.empty() || mat2.empty()){return QPixmap();}//图像融合(这里只是一个简单的示例,使用加权平均)cv::Mat resultMat;double alpha = 0.5;   //融合系数,可以根据需要调整cv::addWeighted(mat1,alpha,mat2,1.0 - alpha,0.0,resultMat);//将OpenCV的Mat转换为QImage//cv::cvtColor(resultMat,resultMat,cv::COLOR_BGR2RGB);QImage newImage((const unsigned char*)(resultMat.data),resultMat.cols,resultMat.rows,resultMat.step,QImage::Format_RGB888);//QImage的save保存拼接图像//newImage.save("E:/myPhoto/opencvMerge.jpg");//OpenCV的imwrite保存拼接图像cv::imwrite("E:/myPhoto/opencvMerge.jpg",resultMat);//返回拼接图像return QPixmap::fromImage(newImage.rgbSwapped());}

四、示例完整代码

1.widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QImage>
#include <QPixmap>
#include <QPainter>
#include <QMessageBox>
#include <QFileDialog>
#include <QDebug>
#include "opencv2/opencv.hpp"using namespace cv;
using namespace std;QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();QPixmap imageMosaic(const QImage &image1,const QImage &image2);QPixmap opencvMosaic(const cv::Mat &mat1,const cv::Mat &mat2);QPixmap opencvMerge(const cv::Mat &mat1,const cv::Mat &mat2);void setShowImage(int index);private slots:void on_pb_image_1_clicked();void on_pb_image_2_clicked();void on_pb_imageMosaic_clicked();void on_pb_opencvMosaic_clicked();void on_pb_opencvMerge_clicked();void on_pb_keep_clicked();void on_pb_fill_clicked();private:Ui::Widget *ui;//QImage对象QImage m_image_1;QImage m_image_2;QPixmap m_showPixmap;//CV::Mat对象cv::Mat m_mat_1;cv::Mat m_mat_2;};
#endif // WIDGET_H

2.widget.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}//使用QImage进行水平拼接
QPixmap Widget::imageMosaic(const QImage &image1,const QImage &image2)
{//检查图像是否有效if(image1.isNull() || image2.isNull()){return QPixmap();}//计算拼接后的图像尺寸int newWidth = image1.width() + image2.width();int newHeight = std::max(image1.height(),image2.height());//创建一个新的QImage对象QImage newImage(newWidth,newHeight,QImage::Format_RGB32);newImage.fill(Qt::transparent);   //填充为透明,如果背景不是透明的则可以选择其他颜色//使用QPainter来绘制图像QPainter painter(&newImage);painter.drawImage(0,0,image1);   //在新图像的(0,0)位置绘制第一张图像painter.drawImage(image1.width(),0,image2);   //在新图像的(image1.width(),0)位置绘制第二张图像//结束绘制painter.end();//保存拼接图像newImage.save("E:/myPhoto/imageMosaic.jpg");//返回拼接图像return QPixmap::fromImage(newImage);
}//使用OpenCV进行水平拼接
QPixmap Widget::opencvMosaic(const cv::Mat &mat1,const cv::Mat &mat2)
{//检查图像是否有效if(mat1.empty() || mat2.empty()){return QPixmap();}//判断两张图像的高度if(mat1.rows != mat2.rows){return QPixmap();}//水平拼接图像cv::Mat resultMat;cv::hconcat(mat1,mat2,resultMat);//将OpenCV的Mat转换为QImage//cv::cvtColor(resultMat,resultMat,cv::COLOR_BGR2RGB);QImage newImage((const unsigned char*)(resultMat.data),resultMat.cols,resultMat.rows,resultMat.step,QImage::Format_RGB888);//QImage的save保存拼接图像//newImage.save("E:/myPhoto/opencvMosaic.jpg");//OpenCV的imwrite保存拼接图像cv::imwrite("E:/myPhoto/opencvMosaic.jpg",resultMat);//返回拼接图像return QPixmap::fromImage(newImage.rgbSwapped());
}//使用OpenCV进行图像融合
QPixmap Widget::opencvMerge(const cv::Mat &mat1,const cv::Mat &mat2)
{//检查图像是否有效if(mat1.empty() || mat2.empty()){return QPixmap();}//图像融合(这里只是一个简单的示例,使用加权平均)cv::Mat resultMat;double alpha = 0.5;   //融合系数,可以根据需要调整cv::addWeighted(mat1,alpha,mat2,1.0 - alpha,0.0,resultMat);//将OpenCV的Mat转换为QImage//cv::cvtColor(resultMat,resultMat,cv::COLOR_BGR2RGB);QImage newImage((const unsigned char*)(resultMat.data),resultMat.cols,resultMat.rows,resultMat.step,QImage::Format_RGB888);//QImage的save保存拼接图像//newImage.save("E:/myPhoto/opencvMerge.jpg");//OpenCV的imwrite保存拼接图像cv::imwrite("E:/myPhoto/opencvMerge.jpg",resultMat);//返回拼接图像return QPixmap::fromImage(newImage.rgbSwapped());}//设置显示图像
void Widget::setShowImage(int index)
{QPixmap showPixmap;if(index == 0){//使用QImage水平拼接showPixmap = imageMosaic(m_image_1,m_image_2);}else if(index == 1){//使用OpenCV水平拼接showPixmap = opencvMosaic(m_mat_1,m_mat_2);}else if(index == 2){//使用OpenCV图像融合showPixmap = opencvMerge(m_mat_1,m_mat_2);}//更新显示m_showPixmap = showPixmap;if(!m_showPixmap.isNull()){ui->lb_imageShow->setPixmap(showPixmap.scaled(ui->lb_imageShow->size(),Qt::KeepAspectRatio));   //保持比例}else{QMessageBox::warning(this,"警告","图像显示失败!");}
}//选择图像1
void Widget::on_pb_image_1_clicked()
{//打开文件对话框,选择图像文件QString fileName = QFileDialog::getOpenFileName(this,"选择图像文件","E:/myPhoto/","Image Files(*.png *.jpg)");if(!fileName.isEmpty()){//赋值Mat图像m_mat_1 = cv::imread(fileName.toStdString(),cv::IMREAD_COLOR);//读取图像文件QImage image(fileName);if(!image.isNull()){//赋值QImage图像m_image_1 = image;//将QImage转换为QPixmap以在QLabel上显示QPixmap pixmap = QPixmap::fromImage(m_image_1);ui->lb_image_1->setPixmap(pixmap.scaled(ui->lb_image_1->size(),Qt::KeepAspectRatio));   //保持比例}else{//图像文件无效或无法读取QMessageBox::warning(this,"警告","图像文件打开失败!");}}
}//选择图像2
void Widget::on_pb_image_2_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,"选择图像文件","E:/myPhoto/","Image Files(*.png *.jpg)");if(!fileName.isEmpty()){m_mat_2 = cv::imread(fileName.toStdString(),cv::IMREAD_COLOR);QImage image(fileName);if(!image.isNull()){m_image_2 = image;QPixmap pixmap = QPixmap::fromImage(m_image_2);ui->lb_image_2->setPixmap(pixmap.scaled(ui->lb_image_2->size(),Qt::KeepAspectRatio));   //保持比例}else{QMessageBox::warning(this,"警告","图像文件打开失败!");}}
}//使用QImage拼接
void Widget::on_pb_imageMosaic_clicked()
{setShowImage(0);
}//使用OpenCV拼接
void Widget::on_pb_opencvMosaic_clicked()
{setShowImage(1);
}//使用OpenCV进行图像融合
void Widget::on_pb_opencvMerge_clicked()
{setShowImage(2);
}//保持比例显示图像
void Widget::on_pb_keep_clicked()
{if(!m_showPixmap.isNull()){ui->lb_imageShow->setPixmap(m_showPixmap.scaled(ui->lb_imageShow->size(),Qt::KeepAspectRatio));   //保持比例}else{QMessageBox::warning(this,"警告","图像显示失败!");}
}//填充显示图像
void Widget::on_pb_fill_clicked()
{if(!m_showPixmap.isNull()){ui->lb_imageShow->setPixmap(m_showPixmap.scaled(ui->lb_imageShow->size(),Qt::IgnoreAspectRatio));   //自由缩放}else{QMessageBox::warning(this,"警告","图像显示失败!");}
}

3.widget.ui
请添加图片描述


总结

Qt中的图像类有QImage和QPixmap等,并且一般会与QPainter类结合起来使用,这些在Qt中是常见且常用的,我们要熟悉相关的函数接口然后灵活使用。另外涉及图像的操作我们还可以调用OpenCV这个图像库,这个能够实现更加复杂的图像变换操作,在Qt下使用也是比较好用呢。


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

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

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

相关文章

光速入门python的OpenCV

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理python的OpenCV模块的关键知识点 争取用最短的时间入门OpenCV 并且做到笔记功能直接复制使用 OpenCV简介 不浪费时间的介绍: 就是类似于ps操作图片。 至于为什么不直接用ps&#xff0c;因为只有程序能…

JAVA -- > 初识JAVA

初始JAVA 第一个JAVA程序详解 public class Main {public static void main(String[] args) {System.out.println("Hello world");} }1.public class Main: 类型,作为被public修饰的类,必须与文件名一致 2.public static 是JAVA中main函数准写法,记住该格式即可 …

碌时刻必备!微信自动回复让你告别消息堆积

在忙碌的时候&#xff0c;我们往往会面临消息堆积如山的情况。无法及时回复消息不仅容易造成交流障碍&#xff0c;还可能错过重要的机会。 但是现在&#xff0c;有一个神奇的工具——个微管理系统&#xff0c;可以帮助我们轻松应对这个问题 &#xff0c;实现微信自动回复。 首…

【DZ模板】价值288克米设计APP手机版DZ模板 数据本地化+完美使用

模版介绍 【DZ模板】价值288克米设计APP手机版DZ模板 数据本地化完美使用 腾讯官方出品discuz论坛DIY的后台设置&#xff0c;功能齐全&#xff0c;论坛功能不亚于葫芦侠&#xff0c;自定义马甲&#xff0c;自定义认证&#xff0c;自定义广告&#xff0c;完全可以打造出自己想…

【手把手带你搓组件库】从零开始实现Element Plus

从零开始实现Element Plus 前言亮点项目搭建1、创建项目初始化monorepo创建 .gitignore目录结构安装基础依赖配置文件创建各个分包入口utilscomponentscoreplaytheme 2、创建VitePress文档3、部署到Github Actions生成 GH_TOKENGitHub Page 演示 4、总结 前言 在本文中&#xf…

《计算机网络微课堂》3-11 虚拟局域网 VLAN

本节课我们介绍虚拟局域网 VLAN 的基本概念。 ‍ 3.11.1 虚拟局域网 VLAN 概述 在之前课程中我们已经介绍过了以太网交换机自学习和转发帧的流程&#xff0c;‍‍以及为避免网络环路而产生的生成树协议。 以太网交换机工作在数据链路层&#xff0c;‍‍也包括物理层&#xf…

ftp是什么,ftp能做什么,ftp有什么用 -----ftp介绍

大家好&#xff0c;我是风屿&#xff0c;今天开始我会给大家介绍一些关于网络方面的配置以及介绍等等&#xff0c;今天是ftp FTP中文名字叫做文件传输协议&#xff0c;英文名字叫做File Transfer Protocol&#xff08;简称为ftp&#xff09; FTP 是因特网网络上历史最悠久的网…

Textual for Mac:轻量级IRC客户端

在寻找一款高效、轻量级的IRC客户端时&#xff0c;Textual for Mac无疑是你的不二之选。它集成了众多现代技术&#xff0c;如本机IPv6、最新的IRCv3规范&#xff0c;以及客户端证书身份验证&#xff0c;让你的聊天体验更加顺畅和安全。 Textual for Mac v7.2.2免激活版下载 Tex…

4、PHP的xml注入漏洞(xxe)

青少年ctf&#xff1a;PHP的XXE 1、打开网页是一个PHP版本页面 2、CTRLf搜索xml&#xff0c;发现2.8.0版本&#xff0c;含有xml漏洞 3、bp抓包 4、使用代码出发bug GET /simplexml_load_string.php HTTP/1.1 补充&#xff1a; <?xml version"1.0" encoding&quo…

【C++】深入解析C++智能指针:从auto_ptr到unique_ptr与shared_ptr

文章目录 前言&#xff1a;1. 智能指针的使用及原理2. C 98 标准库中的 auto_ptr:3. C 11 中的智能指针循环引用&#xff1a;shared_ptr 定制删除器 4. 内存泄漏总结&#xff1a; 前言&#xff1a; 随着C语言的发展&#xff0c;智能指针作为现代C编程中管理动态分配内存的一种…

Win32 API

个人主页&#xff1a;星纭-CSDN博客 系列文章专栏 : C语言 踏上取经路&#xff0c;比抵达灵山更重要&#xff01;一起努力一起进步&#xff01; 一.Win32 API 1.Win32 API介绍 Windows这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外&#xff0c;它同时也是…

python中的线程并行

文章目录 1. 单线程2. 线程池ThreadPoolExecutor 1. 单线程 现在有1154张图片需要顺时针旋转后保存到本地&#xff0c;一般使用循环1154次处理&#xff0c;具体代码如下所示&#xff0c;img_paths中存储1154个图片路径&#xff0c;该代码段耗时约用97ms。 t1time.time() for …

Windows安装VMware(Broadcom)

1.安装前提 1.检查BIOS中是否开启了虚拟化技术。1.1 打开任务管理器&#xff0c;查看性能&#xff0c;CPU部分&#xff0c;虚拟化处于“已启用”状态。1.2 如果没有开启&#xff0c;则需要进入BIOS系统&#xff0c;将 Intel Virtualization Technology改为Enalble。2.下载VMwa…

ROS2入门21讲__第19讲__Rviz:三维可视化显示平台

目录 前言 Rviz三维可视化平台 Rviz介绍 运行方法 彩色相机仿真与可视化 仿真插件配置 运行仿真环境 图像数据可视化 三维相机仿真与可视化 仿真插件配置 运行仿真环境 点云数据可视化 激光雷达仿真与可视化 仿真插件配置 运行仿真环境 点云数据可视化 Rviz v…

【HCIP学习】RSTP和MSTP

一、RSTP&#xff08;Rapid Spanning Tree Protocol&#xff0c;快速生成树&#xff09; 1、背景&#xff1a;RSTP从STP发展而来&#xff0c;具备STP的所有功能&#xff0c;可以兼容stp运行 2、RSTP与STP不同点 &#xff08;1&#xff09;减少端口状态 STP:disabled\blockin…

【Python搞定车载自动化测试】——Python实现CAN总线Bootloader刷写(含Python源码)

系列文章目录 【Python搞定车载自动化测试】系列文章目录汇总 文章目录 系列文章目录&#x1f4af;&#x1f4af;&#x1f4af; 前言&#x1f4af;&#x1f4af;&#x1f4af;一、环境搭建1.软件环境2.硬件环境 二、目录结构三、源码展示1.诊断基础函数方法2.诊断业务函数方法…

《最新出炉》系列入门篇-Python+Playwright自动化测试-40-录制生成脚本

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 各种自动化框架都会有脚本录制功能&#xff0c; playwright这么牛叉当然也不例外。很早之前的selenium、Jmeter工具&#xff0c;发展到每种浏览器都有对应的录制插件。今天我们…

python机器学习及深度学习在空间模拟与时间预测

原文链接https://mp.weixin.qq.com/s?__bizMzUyNzczMTI4Mg&mid2247628504&idx2&sn6fe3aeb9f63203cfe941a6bb63b49b85&chksmfa77a9e5cd0020f3aa4f01887e75b15096a182c2b5b42c1044787aa285c650f1469a0ef28aec&token2124656491&langzh_CN&scene21#we…

C++语法|虚函数与多态详细讲解(六)|如何解释多态?(面试向)

系列汇总讲解&#xff0c;请移步&#xff1a; C语法&#xff5c;虚函数与多态详细讲解系列&#xff08;包含多重继承内容&#xff09; 多态分为了两种&#xff0c;一种是静态的多态&#xff0c;一种是动态的多态。 静态&#xff08;编译时期&#xff09;的多态 函数重载 boo…

基于51单片机温度报警系统—数码管显示

基于51单片机温度报警系统 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.DS18B20采集温度&#xff0c;数码管显示温度&#xff1b; 2.温度测量范围&#xff1a;0-99度&#xff1b; 3.当温度低于…