首先,导入初始图像显示在QLabel上,但是后续对图像的一系列处理操作必须使用OpenCV来,因此存在各种图像格式转换。这里分为六种情况,能满足大部分需求情况。
1 QPixmap–>QImage:
QPixmap pix(path);
QImage img = pix.toImage();
2 QImage–>QPixmap:
QImage img(path);
QPixmap pix = QPixmap::fromImage(img);
3 Mat–>QImage:
4 Mat–>QPixmap:
5 QImage–>Mat:
6 QPixmap–>Mat:
后面四种情况整合起来写成一个类OpenCVtoQt,感谢前辈的奉献。
opencvtoqt.h
#ifndef OPENCVTOQT_H
#define OPENCVTOQT_H
#include <QLabel>
#include <QDebug>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <QDebug>
#include <QImage>
#include <QPixmap>
class OpenCVtoQt
{
public:
OpenCVtoQt();
static void LabeltoMat(QLabel *label, cv::Mat &mat);
static QImage cvMatToQImage( const cv::Mat &inMat );
static QPixmap cvMatToQPixmap( const cv::Mat &inMat);
static cv::Mat QImageToCvMat( const QImage &inImage, bool inCloneImageData = true );
static cv::Mat QPixmapToCvMat( const QPixmap &inPixmap, bool inCloneImageData = true );
~OpenCVtoQt();
};
#endif // OPENCVTOQT_H
opencvtoqt.cpp
#include "opencvtoqt.h"
OpenCVtoQt::OpenCVtoQt()
{
}
//参数1-显示图像的Label,参数2-要显示的Mat
//void LabelDisplayMat::LabeltoMat(QLabel *label, cv::Mat &mat)
//{
// cv::Mat Rgb;
// QImage Img;
// if (mat.channels() == 3)//RGB Img
// {
// cv::cvtColor(mat, Rgb, cv::COLOR_BGR2RGB);//颜色空间转换
// Img = QImage((const uchar*)(Rgb.data), Rgb.cols, Rgb.rows, Rgb.cols * Rgb.channels(), QImage::Format_RGB888);
// }
// else//Gray Img
// {
// Img = QImage((const uchar*)(mat.data), mat.cols, mat.rows, mat.cols*mat.channels(), QImage::Format_Indexed8);
// }
// label->setPixmap(QPixmap::fromImage(Img));
//}
// 将Mat转化位QImage
QImage OpenCVtoQt:: 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 );//Format_Alpha8 and Format_Grayscale8 were added in Qt 5.5
#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() << "CVS::cvMatToQImage() - cv::Mat image type not handled in switch:" << inMat.type();
break;
}
return QImage();
}
//将Mat转化为QPixmap
QPixmap OpenCVtoQt:: cvMatToQPixmap( const cv::Mat &inMat )
{
return QPixmap::fromImage( cvMatToQImage( inMat ) );
}
//将QImage转化为Mat
cv::Mat OpenCVtoQt:: QImageToCvMat( const QImage &inImage, bool inCloneImageData)
{
switch ( inImage.format() )
{
// 8-bit, 4 channel
case QImage::Format_ARGB32:
case QImage::Format_ARGB32_Premultiplied:
{
cv::Mat mat( inImage.height(), inImage.width(),
CV_8UC4,
const_cast<uchar*>(inImage.bits()),
static_cast<size_t>(inImage.bytesPerLine())
);
return (inCloneImageData ? mat.clone() : mat);
}
// 8-bit, 3 channel
case QImage::Format_RGB32:
case QImage::Format_RGB888:
{
if ( !inCloneImageData )
{
qWarning() << "CVS::QImageToCvMat() - Conversion requires cloning because we use a temporary QImage";
}
QImage swapped = inImage;
if ( inImage.format() == QImage::Format_RGB32 )
{
swapped = swapped.convertToFormat( QImage::Format_RGB888 );
}
swapped = swapped.rgbSwapped();
return cv::Mat( swapped.height(), swapped.width(),
CV_8UC3,
const_cast<uchar*>(swapped.bits()),
static_cast<size_t>(swapped.bytesPerLine())
).clone();
}
// 8-bit, 1 channel
case QImage::Format_Indexed8:
{
cv::Mat mat( inImage.height(), inImage.width(),
CV_8UC1,
const_cast<uchar*>(inImage.bits()),
static_cast<size_t>(inImage.bytesPerLine())
);
return (inCloneImageData ? mat.clone() : mat);
}
default:
qWarning() << "CVS::QImageToCvMat() - QImage format not handled in switch:" << inImage.format();
break;
}
return cv::Mat();
}
//将QPixmap转化为Mat
cv::Mat OpenCVtoQt:: QPixmapToCvMat( const QPixmap &inPixmap, bool inCloneImageData)
{
return QImageToCvMat( inPixmap.toImage(), inCloneImageData );
}
OpenCVtoQt::~OpenCVtoQt()
{};
测试之前在主函数中包含头文件
#include "opencvtoqt.h"
//获取QLabel上的图像
QImage pix;
pix=ui->label_2->pixmap()->toImage();
//
//测试按钮触发信号和槽函数
connect(ui->actiontest,&QAction::triggered,[=](){
//将QLabel上的图像提取出来。
QImage src=ui->label->pixmap()->toImage();
//QImage--->Mat格式转换
Mat img=OpenCVtoQt::QImageToCvMat(src);
//对Mat格式的图像文件进行各种图像处理操作,如灰度处理,二值化等
Mat img2;
//BGR图像转化灰度图像
cvtColor(img,img2,COLOR_BGR2GRAY);
//阈值分割(二值化)
threshold(img2,img2,100,250,THRESH_BINARY);
//Mat格式的图像转化为QPixmap格式
QPixmap temp=OpenCVtoQt::cvMatToQPixmap(img2);
//显示在QLabel_2上
ui->label_2->setPixmap(temp);
});
整个流程下来就是将QLabel上的图像提取出来,格式为QPixmap,然后再转化为OpenCV处理的Mat矩阵格式,进行各种图像处理操作,二值化,滤波,形态学处理等等;最后再转化为QLabel能显示的格式,达到界面交互的作用,软件的交互界面。
参考文献:
QT图片格式转换(QImage和QPixmap、QImage和Mat互转)
QT QImage、QPixmap与Opencv 中的Mat相互转化