在这里先祝各位小伙伴端午节快乐,因工作需要,须使用QT+OpenCV处理显示图片,期间踩了一些坑、总结了一些经验,今天做下记录,希望可以帮助更多小伙伴,开搞!!
INCLUDEPATH += /usr/local/include \
/usr/local/include/opencv \
/usr/local/include/opencv2
LIBS += /usr/local/lib/libopencv_highgui.so \
/usr/local/lib/libopencv_core.so \
/usr/local/lib/libopencv_imgproc.so \
/usr/local/lib/libopencv_imgcodecs.so
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include //打开指定文件
#include
using namespace cv;
using namespace std;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QImage MatToQImageThreeAndSignalChannel(cv::Mat& mat, QImage& qimage);
QImage MatToQImageShallowCopy(cv::Mat &mat, QImage::Format format);
QImage MatToQImageDeepCopy(cv::Mat &mat, QImage::Format format);
QImage MatToQImageMultichannel(const cv::Mat &mat);
private slots:
void on_OpenImageButton_clicked();
void on_CloseImageButton_clicked();
private:
Ui::MainWindow *ui;
Mat srcImage, dstImage;
QImage qImage;
QString imageName;
};
#endif // MAINWINDOW_H
private slots:
void on_OpenImageButton_clicked();
imageName = QFileDialog::getOpenFileName(this, tr("打开图片"), ".", tr("所有格式(*.png *.jpg *.jpeg *.bmp)"));
if(imageName.length() <= 0) {
qDebug() << "读取图片错误" << endl;
return;
}
srcImage = imread(imageName.toUtf8().data());
因为我要显示的图片比较大,显示框显示不完整,需要先缩小(这一部分可选做)。
cv::resize(srcImage, dstImage, Size(), 0.25, 0.25);//缩小四倍
在QT label中显示图片需要进行OpenCV到QImage的格式转换,下面将介绍四种方法。
本人选择的图片默认为RGB三通道。
1、转换函数
QImage MainWindow::MatToQImageShallowCopy(cv::Mat &mat, QImage::Format format) {
return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
}
2、调用
qImage = MatToQImageShallowCopy(dstImage, qImage.Format_RGB888);
1、转换函数
QImage MainWindow::MatToQImageDeepCopy(cv::Mat &mat, QImage::Format format) {
return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
}
2、调用
qImage = MatToQImageDeepCopy(dstImage, qImage.Format_RGB888);
上面两种方法都默认图片格式为RGB三通道,那么有没有一种方式可以进行单通道和三通道判断呢?有的,下面将继续介绍。
1、转换函数
QImage MainWindow::MatToQImageThreeAndSignalChannel(cv::Mat &mat, QImage &qimage) {
//CV_8UC3 unsigned 型 3通道
//打开的图片是三通道的
if(mat.type() == CV_8UC3) {
qimage = QImage((const unsigned char*)(mat.data),
mat.cols, mat.rows, mat.step,
QImage::Format_RGB888).rgbSwapped();
}
else if(mat.type() == CV_8UC1) {
static QVector sColorTable;
if(sColorTable.isEmpty()) {
for(int i = 0; i < 256; ++i) {
sColorTable.push_back(qRgb(i, i, i)); //如果打开的图片是空的,就自己填充色彩
}
}
qimage = QImage((const unsigned char*)(mat.data),
mat.cols, mat.rows, mat.step,
QImage::Format_Indexed8);
qimage.setColorTable(sColorTable);//转换成qt调色板
}
return qimage;
}
2、调用
调用的时候就不用自己手动的写通道个数了。
qImage = MatToQImageThreeAndSignalChannel(dstImage, qImage);
这个方法对以上的三个方法进行了改进,添加了四通道判断功能。
1、转换函数
QImage MainWindow::MatToQImageMultichannel(const cv::Mat &mat) {
QImage image;
switch(mat.type()) {
//8bit,四通道
case CV_8UC4:{
image = QImage(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB32);//step:每一维元素的大小,单位字节
return image;
}
//8bit,三通道
case CV_8UC3:{
image = QImage(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);//step:每一维元素的大小,单位字节
return image;
}
//8bit,单通道
case CV_8UC1: {
static QVector sColorTable;
if(sColorTable.isEmpty()) {
for(int i = 0; i < 256; ++i) {
sColorTable.push_back(qRgb(i, i, i)); //如果打开的图片是空的,就自己填充色彩
}
}
image = QImage((const unsigned char*)(mat.data),
mat.cols, mat.rows, mat.step,
QImage::Format_Indexed8);
image.setColorTable(sColorTable);//转换成qt调色板
}
default:
qDebug("没有支持的图片格式: depth=%d 和 %d channels\n", mat.depth(), mat.channels());
break;
}
return QImage();
}
2、调用
qImage = MatToQImageMultichannel(dstImage);
好了,到这里你们是不是已经学会了QT 和 OpenCV混合使用显示图片了呢,下面我将代码贴上。
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow){
ui->setupUi(this);
}
MainWindow::~MainWindow(){
delete ui;
}
//方法一:浅拷贝
QImage MainWindow::MatToQImageShallowCopy(cv::Mat &mat, QImage::Format format) {
return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
}
//方法二:深拷贝
QImage MainWindow::MatToQImageDeepCopy(cv::Mat &mat, QImage::Format format) {
return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
}
//方法三:单通道和三通道选择
QImage MainWindow::MatToQImageThreeAndSignalChannel(cv::Mat &mat, QImage &qimage) {
//CV_8UC3 unsigned 型 3通道
//打开的图片是三通道的
if(mat.type() == CV_8UC3) {
qimage = QImage((const unsigned char*)(mat.data),
mat.cols, mat.rows, mat.step,
QImage::Format_RGB888).rgbSwapped();
}
else if(mat.type() == CV_8UC1) {
static QVector sColorTable;
if(sColorTable.isEmpty()) {
for(int i = 0; i < 256; ++i) {
sColorTable.push_back(qRgb(i, i, i)); //如果打开的图片是空的,就自己填充色彩
}
}
qimage = QImage((const unsigned char*)(mat.data),
mat.cols, mat.rows, mat.step,
QImage::Format_Indexed8);
qimage.setColorTable(sColorTable);//转换成qt调色板
}
return qimage;
}
//方法四:多通道和单通道选择
QImage MainWindow::MatToQImageMultichannel(const cv::Mat &mat) {
QImage image;
switch(mat.type()) {
//8bit,四通道
case CV_8UC4:{
image = QImage(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB32);//step:每一维元素的大小,单位字节
return image;
}
//8bit,三通道
case CV_8UC3:{
image = QImage(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);//step:每一维元素的大小,单位字节
return image;
}
//8bit,单通道
case CV_8UC1: {
static QVector sColorTable;
if(sColorTable.isEmpty()) {
for(int i = 0; i < 256; ++i) {
sColorTable.push_back(qRgb(i, i, i)); //如果打开的图片是空的,就自己填充色彩
}
}
image = QImage((const unsigned char*)(mat.data),
mat.cols, mat.rows, mat.step,
QImage::Format_Indexed8);
image.setColorTable(sColorTable);//转换成qt调色板
}
default:
qDebug("没有支持的图片格式: depth=%d 和 %d channels\n", mat.depth(), mat.channels());
break;
}
return QImage();
}
void MainWindow::on_OpenImageButton_clicked(){
imageName = QFileDialog::getOpenFileName(this, tr("打开图片"), ".", tr("所有格式(*.png *.jpg *.jpeg *.bmp)"));
if(imageName.length() <= 0) {
qDebug() << "读取图片错误" << endl;
return;
}
srcImage = imread(imageName.toUtf8().data());
cv::resize(srcImage, dstImage, Size(), 0.25, 0.25);
//方法一 浅拷贝
// qImage = MatToQImageShallowCopy(dstImage, qImage.Format_RGB888);
//方法二 深拷贝
// qImage = MatToQImageDeepCopy(dstImage, qImage.Format_RGB888);
//方法三 单通道和三通道选择
// qImage = MatToQImageThreeAndSignalChannel(dstImage, qImage);
//方法四 多通道和单通道选择改进
qImage = MatToQImageMultichannel(dstImage);
ui->labelShowImage->setPixmap(QPixmap::fromImage(qImage));
}
void MainWindow::on_CloseImageButton_clicked(){
close();
}
感谢大神:
http://www.jeepshoe.net/art/76964.html
https://blog.csdn.net/qq_27901091/article/details/75171378
https://www.cnblogs.com/grandyang/p/5602360.html