编译环境及配置
QT版本:5.14.4
opencv:3.4.5
整体代码是在qt creator 中编写
opencv请自行使用cmake编译并且配置。
Main Window的创建
第一步:点击new创建一个Main window项目文件
会出现以下选项,qt creator 使用的是C++语言,这里我们选择第一个Qt Widget Application
点击下方的选择。
会出现以下的选项,名称中就是编写我们项目的名称,这里我们是需要设计一个图像处理的界面,名称改为image_process 点击下一步。
这里的我们选择qmake作为我们的构建工具
在Qt中,qmake是一个构建工具,用于管理Qt项目的构建过程。当您在Qt Creator中创建新的文件时,选择"qmake"意味着您正在为您的Qt项目创建新的源文件,并且这些文件将被包含在您的项目的.pro文件中。
在Qt中,.pro文件是项目文件,它包含了项目的配置信息、源文件列表、依赖关系等。qmake工具会根据.pro文件来生成适合您的平台和编译器的Makefile或者Visual Studio项目文件。
这里会选择类名,这里有三个选择:
1.QWidget
是Qt中所有用户界面类的基类。它提供了创建窗口、按钮、标签等基本控件的功能。QWidget
可以作为应用程序中的一个独立窗口,也可以作为其他容器窗口中的子组件来使用。
2.QDialog
是QWidget
的子类,它通常用于创建对话框窗口,比如提示框、消息框、输入框等。QDialog
具有一些额外的功能,使得它更适合作为对话框窗口使用,例如它可以有模态(阻塞程序执行)和非模态(不阻塞程序执行)的状态。
3.MainWindow
通常是应用程序的主窗口,它也是QWidget
的子类。MainWindow
通常包含应用程序的主要功能和布局,可能包括菜单栏、工具栏、状态栏等。它是应用程序的主界面,通常会包含其他QWidget
或QDialog
作为子组件。
我们这里选择Mainwindow就可以了。
"kits"(工具集)是一组工具和库的组合,用于构建和运行Qt应用程序。
这里需要选择相应的kits这里在下载qt是会选择性的下载,根据自己电脑配置是配置进行选择。
我这里就是MinGW 64 位的。
最后一个选项会显示创建时自动生成的文件。(包括.pro.cpp.h.ui文件等)
点击完成就ok。
opencv的配置
在我们的.pro 文件中需要添加以下opencv编译好的路径。
新建文件内容
.pro 文件
.pro
文件是项目文件,使用Qt的qmake构建系统来管理项目的构建过程。.pro
文件是一个文本文件,其中包含了项目的配置信息和构建规则。
一个典型的.pro
文件通常包含以下内容:
1.TEMPLATE
:指定项目的类型,例如应用程序(app
)或库(lib
)。
2.TARGET
:指定生成的可执行文件或库的名称。
3.CONFIG
:指定项目的配置选项,例如调试模式(debug
)或发布模式(release
)。
4.QT
:指定项目所依赖的Qt模块。可以使用core
、gui
、widgets
等模块。
5.INCLUDEPATH
:指定项目的头文件搜索路径。
6.SOURCES
:指定项目的源代码文件。
7.HEADERS
:指定项目的头文件。
8.LIBS
:指定项目所依赖的外部库。
9.FORMS
:指定项目使用的Qt Designer表单文件。
10.RESOURCES
:指定项目使用的资源文件。
具体内容不过多介绍。
.h文件
.cpp文件
第一个是main.cpp文件
第二个是mainwindow.cpp文件,主要的代码编译在这个文件中。
.ui 文件
这里生成的ui文件是可以在ui的界面设计中拖动控件去设计我们的界面的。
界面设计(ui控件)
我们先来设计一个界面。实现我们需要的图片读取功能。
pushbutton(按钮控件)label(面板显示图像的控件)
这里简单的布局了一个label和一个pushbutton(读取图像)
这里添加label的时候将其设置成Panel。
连接控件
先做pushbutton的槽函数的编写
在ui界面设计时右键点击设计的按钮控件点击转到槽函数
选择第一个点击信号就可以了。
它会自动在.cpp文件中生成这个槽函数的定义,我们功能逻辑的实现代码就是在这里编写。
在我们的.h文件中也会出现槽函数的私有函数的定义。
主题:图像的读取
void MainWindow::on_pushButton_clicked()
{
QString imagePath = QFileDialog::getOpenFileName(this,"打开图片","D:","(打开(*.png *.jpg *.bmp))");
Mat cvImage = imread(imagePath.toStdString());
if (cvImage.empty()) {
qDebug() << "Failed to load image";
return;
}
QImage image((const unsigned char*)(cvImage.data), cvImage.cols, cvImage.rows, cvImage.step, QImage::Format_RGB888);
// 调整label的大小
QSize labelSize(300, 200);
// 设置label的大小为300x200
ui->label->setFixedSize(labelSize);
// 在label上显示图像并填充
ui->label->setPixmap(QPixmap::fromImage(image));
ui->label->setScaledContents(true);
ui->label->setAlignment(Qt::AlignCenter);
}
这里就是槽函数的读取图像的实现
1.图像文件路径获取
QString imagePath = QFileDialog::getOpenFileName(this,"打开图片","D:","(打开(*.png *.jpg *.bmp))");
定义字符串类型的变量imagePath获取图像的路径。
这里使用到了qt中处理文件对话框的类:QFileDialog;
使用其中的静态函数getOpenFileName函数:打开文件对话框选择其中一个文件,获取其路径。
QFileDialog还有一些其他的静态函数这里做简单介绍:
getOpenFileNames:打开文件对话框选择打开多个文件;
getSaveFileNames:打开文件对话框选择文件保存路径;
getExistingDirectory:打开文件对话框选择一个目录。
静态函数的参数通常包括:
1.parent
:表示父对象,通常是指向当前窗口或者当前的上下文的指针。这个参数用于确定文件对话框的父窗口,以及对话框的模态性质。this表示在这个窗口界面。
2.caption
:对话框的标题,会显示在对话框的标题栏上,用于指示用户选择文件的目的。
对话框标题为”打开图片“
3.directory
:对话框打开时默认显示的路径,可以是一个文件夹的路径。”默认文件对话框打开的文件夹“我这里是D:
4.filter
:文件过滤器,用于限制用户可以选择的文件类型。过滤器可以是一种文件类型,也可以是多种文件类型的组合。其实就可以打开的图像文件的格式这里(.png.jpg.bmp)。自行设定
2.图像文件的读取
Mat cvImage = imread(imagePath.toStdString());
定义一个图像类型的变量cvImage
使用的是opencv库中的函数imread函数,它可以加载各种常见的图像文件格式,如JPEG、PNG、BMP等,并将其作为多维数组(Mat对象)存储在内存中供后续处理和分析。
我这是在上述代码中加入了
using namespace cv;
所以省略了命名空间cv::
头文件的添加见上.cpp文件图
.toStdString()函数是将获取的图像路径转换为标准的C++字符串。
然后是使用了判断语句确保图像文件不为空。为空时会Qdebug出字符串”加载图像失败“
这里和上述的QFileDialog类的使用相同也是需要添加一个头文件。
#include<QFileDialog>
#include<QDebug>
读取功能到这里就结束了。
3.控件显示图像
在label控件上显示图像
在Qt 中, QImage 对象可以用来显示图像。
QImage image((const unsigned char*)(cvImage.data), cvImage.cols, cvImage.rows, cvImage.step, QImage::Format_RGB888);
创建QImage对象其中参数为:
1.(const unsigned char*)(cvImage.data)
: 这部分将 OpenCV 的图像数据指针转换为 const unsigned char*
类型,以便能够被 QImage 正确地解释和处理。
2.cvImage.cols
和 cvImage.rows
: 这两个参数分别表示图像的宽度和高度。
3.cvImage.step
: 这是图像数据的步长,表示每一行像素数据的字节数。这对于处理不同类型的图像数据非常重要。
4.QImage::Format_RGB888
: 这表示图像数据的格式,这里是 RGB888 格式,它与 OpenCV 的图像数据格式相对应。
设置label的大小
QSize labelSize(300, 200);
ui->label->setFixedSize(labelSize);
也可以让其跟随label大小变化
想要在label显示还需要转换QPixmap
ui->label->setPixmap(QPixmap::fromImage(image));
ui->label->setScaledContents(true);
ui->label->setAlignment(Qt::AlignCenter);
ui->label->setPixmap(QPixmap::fromImage(image));:这一行将QImage对象转换为QPixmap,并将其设置为QLabel的pixmap,从而在界面上显示图像。
ui->label->setScaledContents(true);:这一行设置了QLabel的scaledContents属性为true,这意味着当QLabel的大小改变时,图像会自动缩放以适应QLabel的大小。
ui->label->setAlignment(Qt::AlignCenter);:这一行设置了QLabel中图像的对齐方式,这里设置为居中对齐。
效果展示
我们突然发现显示出来的图像色彩不是很对,
这是因为在Qt中,QImage
默认使用RGB格式来表示图像数据,而不是BGR格式。这意味着当使用QImage
加载图像数据时,它会将图像数据解释为RGB格式。
所以我们需要加入一些格式转换的操作
Mat image;
cvtColor(cvImage,image,COLOR_BGR2RGB);
使用的是opencv库中的函数cvtColor函数第一个参数是我们读取的图像,第二个是新创建的图像变量,最后一个是格式的转换。
最后附一张效果图
附一下修改后的代码
void MainWindow::on_pushButton_clicked()
{
QString imagePath = QFileDialog::getOpenFileName(this,"打开图片","D:","(打开(*.png *.jpg *.bmp))");
Mat cvImage = imread(imagePath.toStdString());
if (cvImage.empty()) {
qDebug() << "Failed to load image";
return;
}
Mat image1;
cvtColor(cvImage,image1,COLOR_BGR2RGB);
QImage image((const unsigned char*)(image1.data), image1.cols, image1.rows, image1.step, QImage::Format_RGB888);
QSize labelSize(600, 400);
ui->label->setFixedSize(labelSize);
ui->label->setPixmap(QPixmap::fromImage(image));
ui->label->setScaledContents(true);
ui->label->setAlignment(Qt::AlignCenter);
}