文章目录
前言
本文主要讲述了在Qt下使用QImage和OpenCV实现图像的拼接与融合,并结合相应的示例进行讲解,以便大家学习,如有错误之处,欢迎大家批评指正。
项目效果
提示:以下是本篇文章正文内容,下面案例可供参考
一、使用QImage进行水平拼接
这里新建了一个QImage对象,然后通过QPainter来将两张图像绘制在一起,并且可以通过QImage的save函数来保存拼接后的图像:
c
//使用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来保存拼接图像:
c
//使用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函数来进行融合:
c
//使用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
c
#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_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
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
c
#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:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。