qt入门(4):按钮触发读取输入路径图片数据并在窗口中展示demo

QT+OPENCV简单demo

目录

1 demo功能简介
2 实现过程的难点和要注意的地方
··2.1 制作的UI界面
··2.2 代码实现
··2.3 库的添加
··2.4 自定义函数方法多文件编译
3 代码
4 文件包

1 demo功能简介

制作一个简易的界面软件,人为输入一个路径(如D:\qq.jpg),按下按钮后,通过opencv函数读取图片数据,然后在软件窗口中进行展示
演示效果如下,可以看到,在右边输入路径后,按下按钮即可读取图片并且在窗口中显示
在这里插入图片描述

2 实现过程

2.1 制作的UI界面

使用LineEdit来输入路径,使用PushButton来触发读取,在Label中展示图片。
在这里插入图片描述
相关的框架与命名如下,左边那个是我自己直接设定好了路径进行加载的,右边是要输入名字之后再进行读取。
在这里插入图片描述

2.2 代码实现

lineedit读取数据可以使用

//LineEdit部分
ui->lineEdit_ImagePath_2->text();//lineedit中读取Qstring
ui->lineEdit_ImagePath_2->text().toStdString();//lineedit中读取Qstring并转换为StdString

在Label中显示对应的图片
注意Label中只能显示Qpixmap格式的图片,而我们只能对QImage格式进行像素操作因此我们在展示之前需要将opencv的Mat格式转换为QImage格式

//在label窗口中进行展示QPixmap
ui->label_ShowImage_2->setScaledContents(true);//设定比例
ui->label_ShowImage_2->setPixmap(QSrcPixmap);//Label中只能显示Qpixmap格式

opencv读取照片并转换
注意,opencv用imread读取到的照片是Mat格式的,并且opencv是默认的BGR格式,但是使用QImage的构造函数的话默认是RGB格式的,因此我们需要把Mat从BGR格式转换为RGB格式,因此这里使用了opencv自带的cvtColor函数。

后面的转换函数mat2qimage_ref的本质就是使用qimage构造函数进行转换。然后使用fromImage可以将QImage转换为Pixmap,这样就可以在Label中进行显示了

std::string ImagePath=ui->lineEdit_ImagePath_2->text().toStdString();//读取路径
cv::Mat CVSrcImage=cv::imread(ImagePath,1);
cv::cvtColor(CVSrcImage, CVSrcImage, CV_BGR2RGB);//将opencv的图转换为RGB,这样才方便在QT中展示

QImage QSrcImage;
QSrcImage=StructureLine::mat2qimage_ref(CVSrcImage,QImage::Format_RGB888);
//将Qimage转化为QPixmap格式,方便展示
QPixmap QSrcPixmap = QPixmap::fromImage(QSrcImage,Qt::AutoColor);

2.3 库的添加

使用cvtColor函数要使用imgproc这个文件,如果一开始没有添加的话,要在pro中添加库文件的时候添加进去。如果没有添加的话,编译的时候会显示报错,类似于“找不到XXX,或者XXX不存在这种”。添加的方法在前面的文章“不使用cmake配置qt+opencv环境”里面已经提到了。

2.4 自定义函数方法多文件编译

本demo的文件架构如下所示,其中mat2qtformat自定义的函数方法文件,它用来实现cv::mat到QImage的转换函数
在这里插入图片描述
其中mat2qtformat.h的文件代码如下所示,在头文件中添加< QImage >以及< opencv2/opencv.hpp >能够帮助在文件中进行写代码时候的补全,如果这里不进行include相关头文件的话,那么在mat2qtformat.cpp中就必须进行include相关头文件。

mat2qtformat.h
#ifndef MATTOQTFORMAT_H
#define MATTOQTFORMAT_H
#include <QImage>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
namespace StructureLine {
//##### cv::Mat ---> QImage #####
// Shallow copy
QImage mat2qimage_ref(cv::Mat &m, QImage::Format format);

// Deep copy
QImage mat2qimage_cpy(cv::Mat &m, QImage::Format format);

//##### QImage ---> cv::Mat #####

// Shallow copy
cv::Mat qimage2mat_ref(QImage &img, int format) ;

// Deep copy
//cv::Mat qimage2mat_ref(QImage &img, int format);
//
}
#endif // MATTOQTFORMAT_H
mat2qtformat.cpp

这个文件中不在包含opencv的头文件,因为直接写在了mat2qtformat.h文件中了

#include "mat2qtformat.h"
namespace StructureLine {
//##### cv::Mat ---> QImage #####
// Shallow copy
QImage mat2qimage_ref(cv::Mat &m, QImage::Format format) {
    return QImage(m.data, m.cols, m.rows, m.step, format);
}

// Deep copy
QImage mat2qimage_cpy(cv::Mat &m, QImage::Format format) {
    return QImage(m.data, m.cols, m.rows, m.step, format).copy();
}

//##### QImage ---> cv::Mat #####
// Shallow copy
cv::Mat qimage2mat_ref(QImage &img, int format) {
    return cv::Mat(img.height(), img.width(), format, img.bits(), img.bytesPerLine());
}

// Deep copy
//cv::Mat qimage2mat_ref(QImage &img, int format) {
//    return cv::Mat(img.height(), img.width(), format, const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
//}
}

3 代码

cvdemo.pro
#-------------------------------------------------
#
# Project created by QtCreator 2019-12-14T11:12:11
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = cvdemo
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp \
    mat2qtformat.cpp

HEADERS += \
        mainwindow.h \
    mat2qtformat.h

FORMS += \
        mainwindow.ui


CONFIG +=C++11

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_core2413
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_core2413d
else:unix: LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_core2413

INCLUDEPATH += $$PWD/../../cvpack/package/opencv/build/include
DEPENDPATH += $$PWD/../../cvpack/package/opencv/build/include


win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_highgui2413
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_highgui2413d
else:unix: LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_highgui2413

INCLUDEPATH += $$PWD/../../cvpack/package/opencv/build/include
DEPENDPATH += $$PWD/../../cvpack/package/opencv/build/include



win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_imgproc2413
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_imgproc2413d
else:unix: LIBS += -L$$PWD/../../cvpack/package/opencv/build/x64/vc14/lib/ -lopencv_imgproc2413

INCLUDEPATH += $$PWD/../../cvpack/package/opencv/build/include
DEPENDPATH += $$PWD/../../cvpack/package/opencv/build/include
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_ReadImagePath_clicked();

    void on_pushButton_ReadImagePath_2_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
mat2qtformat.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_ReadImagePath_clicked();

    void on_pushButton_ReadImagePath_2_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <string>
#include <opencv2/highgui.hpp>
#include <opencv/cv.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>

#include <QPixmap>
#include <QImage>
#include <QPainter>
#include <QString>
#include <QLabel>
#include <QMessageBox>
#include <QDebug>
#include "mat2qtformat.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_ReadImagePath_clicked()
{
    //这个函数没有使用opencv的函数,单纯使用了qt的函数进行加载
    QString filename("D:\\qq.jpg");
    QImage* img=new QImage;
    if(! ( img->load(filename) ) ) //加载图像
    {
        QMessageBox::information(this,
                     tr("打开图像失败"),
                     tr("打开图像失败!"));
        delete img;
        return;
    }
    ui->label_ShowImage->setScaledContents(true);
    ui->label_ShowImage->setPixmap(QPixmap::fromImage(*img));
}

void MainWindow::on_pushButton_ReadImagePath_2_clicked()
{
    qDebug()<<ui->lineEdit_ImagePath_2->text();//这里的地址只需要写D:\qq.jpg即可,因为下面转换为std::string会直接扩充为D:\\qq.jpg,但是opencv都能读出来
    std::string ImagePath=ui->lineEdit_ImagePath_2->text().toStdString();//读取路径
    cv::Mat CVSrcImage=cv::imread(ImagePath,1);
    cv::cvtColor(CVSrcImage, CVSrcImage, CV_BGR2RGB);//将opencv的图转换为RGB,这样才方便在QT中展示

    QImage QSrcImage;
    QSrcImage=StructureLine::mat2qimage_ref(CVSrcImage,QImage::Format_RGB888);
    //将Qimage转化为QPixmap格式,方便展示
    QPixmap QSrcPixmap = QPixmap::fromImage(QSrcImage,Qt::AutoColor);
    //在label窗口中进行展示QPixmap
    ui->label_ShowImage_2->setScaledContents(true);
    ui->label_ShowImage_2->setPixmap(QSrcPixmap);

    /*
    QImage QSrcImage;
    if(QSrcImage.load(ui->lineEdit_ImagePath_2->text(),nullptr)){//如果成功加载
    //将Qimage转化为QPixmap格式,方便展示
    QPixmap QSrcPixmap = QPixmap::fromImage(QSrcImage,Qt::AutoColor);
    //在label窗口中进行展示QPixmap
    ui->label_ShowImage_2->setScaledContents(true);
    ui->label_ShowImage_2->setPixmap(QSrcPixmap);
    }
    */
}
mat2qtformat.cpp
#include "mat2qtformat.h"

namespace StructureLine {
//##### cv::Mat ---> QImage #####
// Shallow copy
QImage mat2qimage_ref(cv::Mat &m, QImage::Format format) {
    return QImage(m.data, m.cols, m.rows, m.step, format);
}

// Deep copy
QImage mat2qimage_cpy(cv::Mat &m, QImage::Format format) {
    return QImage(m.data, m.cols, m.rows, m.step, format).copy();
}

//##### QImage ---> cv::Mat #####
// Shallow copy
cv::Mat qimage2mat_ref(QImage &img, int format) {
    return cv::Mat(img.height(), img.width(), format, img.bits(), img.bytesPerLine());
}

// Deep copy
//cv::Mat qimage2mat_ref(QImage &img, int format) {
//    return cv::Mat(img.height(), img.width(), format, const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
//}

}
UI框架

在这里插入图片描述

文件下载

链接:https://pan.baidu.com/s/1CSdjAoCvfdbSExjOosLzuA
提取码:4bjl

2019-12-16更新

新增加了第二种cvMat转换为Qpixmap的函数,鲁棒性更强,其余文件相同,因此这里不再重复

mainwindow.cpp

将一开始的那种方法给隐藏掉了,使用第二种方法

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <string>
#include <opencv2/highgui.hpp>
#include <opencv/cv.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>

#include <QPixmap>
#include <QImage>
#include <QPainter>
#include <QString>
#include <QLabel>
#include <QMessageBox>
#include <QDebug>
#include "mat2qtformat.h"
#include "mat2qtformatmethod2.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_ReadImagePath_clicked()
{
    //这个函数没有使用opencv的函数,单纯使用了qt的函数进行加载
    QString filename("D:\\qq.jpg");
    QImage* img=new QImage;
    if(! ( img->load(filename) ) ) //加载图像
    {
        QMessageBox::information(this,
                     tr("打开图像失败"),
                     tr("打开图像失败!"));
        delete img;
        return;
    }
    ui->label_ShowImage->setScaledContents(true);
    ui->label_ShowImage->setPixmap(QPixmap::fromImage(*img));
}

void MainWindow::on_pushButton_ReadImagePath_2_clicked()
{
    qDebug()<<ui->lineEdit_ImagePath_2->text();//这里的地址只需要写D:\qq.jpg即可,因为下面转换为std::string会直接扩充为D:\\qq.jpg,但是opencv都能读出来
    std::string ImagePath=ui->lineEdit_ImagePath_2->text().toStdString();//读取路径
    cv::Mat CVSrcImage=cv::imread(ImagePath,1);
    //cv::cvtColor(CVSrcImage, CVSrcImage, CV_BGR2RGB);//将opencv的图转换为RGB,这样才方便在QT中展示

    /*
    QImage QSrcImage;
    QSrcImage=StructureLine::mat2qimage_ref(CVSrcImage,QImage::Format_RGB888);
    //将Qimage转化为QPixmap格式,方便展示
    QPixmap QSrcPixmap = QPixmap::fromImage(QSrcImage,Qt::AutoColor);
    //在label窗口中进行展示QPixmap
    ui->label_ShowImage_2->setScaledContents(true);
    ui->label_ShowImage_2->setPixmap(QSrcPixmap);
    */

    /*
    //这一部分是直接使用QT自带的load来读取图片
    QImage QSrcImage;
    if(QSrcImage.load(ui->lineEdit_ImagePath_2->text(),nullptr)){//如果成功加载
    //将Qimage转化为QPixmap格式,方便展示
    QPixmap QSrcPixmap = QPixmap::fromImage(QSrcImage,Qt::AutoColor);
    //在label窗口中进行展示QPixmap
    ui->label_ShowImage_2->setScaledContents(true);
    ui->label_ShowImage_2->setPixmap(QSrcPixmap);
    }
    */

    //使用第二种接口来读取图片
    QPixmap QSrcPixmap2=CV2QTFORMAT::cvMatToQPixmap(CVSrcImage);
    ui->label_ShowImage_2->setScaledContents(true);
    ui->label_ShowImage_2->setPixmap(QSrcPixmap2);
}
mat2qtformatmethod2.h

// 第二种转换函数头文件

#ifndef MAT2QTFORMATMETHOD2_H
#define MAT2QTFORMATMETHOD2_H
#include <QDebug>
#include <QImage>
#include <QPixmap>
#include <QtGlobal>

#include <opencv2/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
// 这是第二种将CV::mat转化为Qimage的函数方法
// 这种方法能够直接识别读入的mat的类型,并且进行相应的转换为Qimage和Qpixmap
// 使用这种方法不需要额外调用cvtColor函数来进行BGR转换为RGB

namespace CV2QTFORMAT {
   QImage  cvMatToQImage( const cv::Mat &inMat );//cvMat转换为QImage
   QPixmap cvMatToQPixmap( const cv::Mat &inMat );//cvMat转换为Qpixmap
}

#endif // MAT2QTFORMATMETHOD2_H

mat2qtformatmethod2.cpp

// 第二种转换函数方法文件

#include "mat2qtformatmethod2.h"
namespace CV2QTFORMAT {
   // NOTE: This does not cover all cases - it should be easy to add new ones as required.
   QImage  cvMatToQImage( const cv::Mat &inMat )
   {
      switch ( inMat.type() )
      {
         // 8-bit, 4 channel
         case CV_8UC4:
         {
            QImage image( inMat.data,
                          inMat.cols, inMat.rows,
                          static_cast<int>(inMat.step),
                          QImage::Format_ARGB32 );

            return image;
         }

         // 8-bit, 3 channel
         case CV_8UC3:
         {
            QImage image( inMat.data,
                          inMat.cols, inMat.rows,
                          static_cast<int>(inMat.step),
                          QImage::Format_RGB888 );

            return image.rgbSwapped();
         }

         // 8-bit, 1 channel
         case CV_8UC1:
         {
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
            QImage image( inMat.data,
                          inMat.cols, inMat.rows,
                          static_cast<int>(inMat.step),
                          QImage::Format_Grayscale8 );
#else
            static QVector<QRgb>  sColorTable;

            // only create our color table the first time
            if ( sColorTable.isEmpty() )
            {
               sColorTable.resize( 256 );

               for ( int i = 0; i < 256; ++i )
               {
                  sColorTable[i] = qRgb( i, i, i );
               }
            }

            QImage image( inMat.data,
                          inMat.cols, inMat.rows,
                          static_cast<int>(inMat.step),
                          QImage::Format_Indexed8 );

            image.setColorTable( sColorTable );
#endif

            return image;
         }

         default:
            qWarning() << "ASM::cvMatToQImage() - cv::Mat image type not handled in switch:" << inMat.type();
            break;
      }

      return QImage();
   }

   QPixmap cvMatToQPixmap( const cv::Mat &inMat )
   {
      return QPixmap::fromImage( CV2QTFORMAT::cvMatToQImage( inMat ) );
   }
}

更新后文件下载

链接:https://pan.baidu.com/s/1-v-zfueMFYdPrK8KxpVymw
提取码:395j

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值