QImage与Mat的相互转换

前言

OpenCV毕竟只是一个库,希望OpenCV处理的图片能在Qt的界面程序中显示出来,比如Label控件,下面的程序就是实现将图片进行简单的边缘处理,再显示在label控件。

主程序

MainWindow.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
#include <QLabel>
#include <QImage>
#include <QFileDialog>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <QDebug>
#include <iostream>
using namespace cv;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QString openFileName;//保存图片路径
QImage img; //QImage存储图片
QImage scaleImg; //为了显示在label中压缩后的图片
private:
Ui::MainWindow *ui;
private slots:
void openFileSlot();//qt打开图片
void cannySlot();//执行canny算子并显示
Mat QImage2cvMat(QImage image);//QImage转Mat
QImage cvMat2QImage(const Mat& mat);//Mat转QImage
};
#endif // MAINWINDOW_H

MainWindow.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QObject::connect(ui->openButton,SIGNAL(clicked()),this,SLOT(openFileSlot()));
QObject::connect(ui->cannyButton,SIGNAL(clicked()),this,SLOT(cannySlot()));
}
MainWindow::~MainWindow()
{
delete ui;
}
//打开图片按钮对应功能
void MainWindow::openFileSlot()
{
//得到文件名
openFileName=QFileDialog::getOpenFileName(this,"打开文件",QDir::currentPath());
if(! ( img.load(openFileName) ) ) //加载图像
{
QMessageBox::information(this,
"打开图像失败",
"打开图像失败!");
return;
}
//使图片合适地放到label中
if((img.width()/img.height())>(ui->srcLabel->width()/ui->srcLabel->height()))
scaleImg = img.scaledToWidth(ui->srcLabel->width(),Qt::FastTransformation);
else
scaleImg = img.scaledToHeight(ui->srcLabel->height(),Qt::FastTransformation);
ui->srcLabel->setPixmap(QPixmap::fromImage(scaleImg));
}
//canny算子按钮对应功能
void MainWindow::cannySlot()
{
if(openFileName.isEmpty())//检测是否选中了文件
{
QMessageBox::information(this,"警告!","没图片算个卵!");
return;
}
Mat matImg = QImage2cvMat(img);
Mat matImgGray,edge;
cvtColor(matImg,matImgGray,COLOR_RGB2GRAY);
//3*3降噪
blur(matImgGray,edge,Size(3,3));
// GaussianBlur(matImgGray,edge,Size(3,3),0,0);//高斯降噪
//边缘处理20,60可变
Canny(edge,edge,20,60,3);
//使图片合适地放到label中
if((img.width()/img.height())>(ui->dstLabel->width()/ui->dstLabel->height()))
scaleImg = img.scaledToWidth(ui->dstLabel->width(),Qt::FastTransformation);
else
scaleImg = img.scaledToHeight(ui->dstLabel->height(),Qt::FastTransformation);
ui->dstLabel->setPixmap(QPixmap::fromImage(scaleImg));
}
//QImage转Mat
Mat MainWindow::QImage2cvMat(QImage image)
{
cv::Mat mat;
qDebug() << image.format();
switch(image.format())
{
case QImage::Format_ARGB32:
case QImage::Format_RGB32:
case QImage::Format_ARGB32_Premultiplied:
mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
break;
case QImage::Format_RGB888:
mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
cv::cvtColor(mat, mat, CV_BGR2RGB);
break;
case QImage::Format_Indexed8:
mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
break;
}
return mat;
}
//Mat转QImage
QImage MainWindow::cvMat2QImage(const cv::Mat& mat)
{
// 8-bits unsigned, NO. OF CHANNELS = 1
if(mat.type() == CV_8UC1)
{
QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
// Set the color table (used to translate colour indexes to qRgb values)
image.setColorCount(256);
for(int i = 0; i < 256; i++)
{
image.setColor(i, qRgb(i, i, i));
}
// Copy input Mat
uchar *pSrc = mat.data;
for(int row = 0; row < mat.rows; row ++)
{
uchar *pDest = image.scanLine(row);
memcpy(pDest, pSrc, mat.cols);
pSrc += mat.step;
}
return image;
}
// 8-bits unsigned, NO. OF CHANNELS = 3
else if(mat.type() == CV_8UC3)
{
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return image.rgbSwapped();
}
else if(mat.type() == CV_8UC4)
{
qDebug() << "CV_8UC4";
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
return image.copy();
}
else
{
qDebug() << "ERROR: Mat could not be converted to QImage.";
return QImage();
}
}

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器