赞
踩
本文主要讲述了在Qt下使用QImage和OpenCV实现图像的拼接与融合,并结合相应的示例进行讲解,以便大家学习,如有错误之处,欢迎大家批评指正。
项目效果
提示:以下是本篇文章正文内容,下面案例可供参考
这里新建了一个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); }
在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中的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_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
#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:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。