这个题目的内容已经有很多博客写过了,但是我这里为纪念自己的第一篇博客,简单写一个在QT5.8下用Opencv的函数进行图像显示操作。如有和别人的雷同,那纯属巧合(也很容易相同,毕竟这个操作很简单);
作者才疏学浅,如有不对,请多指教。
环境:QtCreator 5.8(我没有在VS用QT插件,VS在编码兼容性上更好一下,但是我VS有问题,等重装个系统再去配置)
opencv 版本是2.4.13,是之前师兄拷贝给我的,就没有用新的3.3版本的,不过2.4.13也差不多。前提是你的电脑配置好的Opencv。
本文要做的内容:
1:新建一个Qt工程
2:创建界面,按键导入图片,显示在主界面上,并用户自定义是否缩放。
3:鼠标追踪,追踪鼠标在图像显示区域内的位置,并在UI上显示出来。
Step 1:
Qt主界面新建一个Qt Widget Application,名字随便取,我取的ImageProcess。
编译器选择(这个视状况自定):
step 2:
UI界面制作成这样的,现在我们只用“打开图片”按钮,其余先暂时忽略,中间显示图片用的控件是Graphic View,也可以用Label,自定,只是需要修改代码而已。
step 3:
在pro文件中,先导入opencv2的库,注意,各方配置不同,这里可能不同,如果你的电脑配置好的,不用这样的操作,请忽略这步
INCLUDEPATH += D:\opencv\opencv\build\include
CONFIG(debug, debug|release): {
LIBS += -LD:\opencv\opencv\build\x86\vc12\lib\
-lopencv_core2413d \
-lopencv_imgproc2413d \
-lopencv_highgui2413d \
-lopencv_ml2413d \
-lopencv_video2413d \
-lopencv_features2d2413d \
-lopencv_calib3d2413d \
-lopencv_objdetect2413d \
-lopencv_contrib2413d \
-lopencv_legacy2413d \
-lopencv_flann2413d
} else:CONFIG(release, debug|release): {
LIBS += -LD:\opencv\opencv\build\x86\vc12\lib\
-lopencv_core2413 \
-lopencv_imgproc2413 \
-lopencv_highgui2413 \
-lopencv_ml2413 \
-lopencv_video2413 \
-lopencv_features2d2413 \
-lopencv_calib3d2413 \
-lopencv_objdetect2413 \
-lopencv_contrib2413 \
-lopencv_legacy2413 \
-lopencv_flann2413
}
step 4:
打开图片按钮命名为 OpenImage_Button,然后右键转到Clicked()槽函数,写入如下代码:
此处需要注意,opencv的Mat数据要显示到Qt需要进行转换,我这里是先把转换到QImage图像,再转Qpixmap,Graphicview即可进行显示,相应转换的函数,可以用这篇博客的:
http://blog.csdn.net/liyuanbhu/article/details/46662115,如果是用Label显示的话,则是直接ui.Label.setpixmap(pixmap)的方法即可显示了。
Fileadd.replace("/","\\");
此句是对文件路径的修改,mat和Qimage读取格式不一样,注意,路径不能有中文,否则读取是空的。
int ImageProcess::on_OpenImage_Button_clicked()
{
QString Fileadd=QFileDialog::getOpenFileName(NULL,"openfile",QDir::currentPath());
if(Fileadd.isEmpty())
{
QMessageBox::information(NULL,"notice","not opened");
return -1;
}
Fileadd.replace("/","\\");
std::string ImagePath=Fileadd.toStdString();
LoadImage=cv::imread(ImagePath,1);
if(!LoadImage.data)
{
QMessageBox::information(NULL,"Error","No file loaded or File name error!");
return -1;
}
float Scales;
if(Ori_ImageHeight>ui->graphicsView->height()||Ori_ImageWidth>ui->graphicsView->width())
{
QMessageBox msgBox;
msgBox.setText("Size Warning");
msgBox.setInformativeText("This Image is too big ,need to clip it to property size?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
// Get the scales according to the size of image
if(float(Ori_ImageHeight)/float(ui->graphicsView->height())>
float(Ori_ImageWidth)/float(ui->graphicsView->width()))
{
Scales=1/ (float(Ori_ImageHeight)/float(ui->graphicsView->height()));
}
else
{
Scales=1/ (float(Ori_ImageWidth)/float(ui->graphicsView->width()));
}
switch (ret) {
case QMessageBox::Yes; cv::resize(LoadImage,LoadImage,cv::Size(Ori_ImageWidth*Scales,Ori_ImageHeight*Scales),0,0);
break;
default:
break;
}
}
ImagePixmap=QPixmap::fromImage(cvMat2QImage(LoadImage));
QGraphicsScene *scene = new QGraphicsScene;
scene->addPixmap(ImagePixmap);
ui->graphicsView->setScene(scene);
ui->graphicsView->show();
ui->Width_Image_LineEdit->setText(QString::number(LoadImage.cols));
ui->Height_Image_LineEdit->setText(QString::number(LoadImage.rows));
}
上面代码中,这段,是对输入的图像进行测试,是否尺寸大于了显示的graphicview,如果大于,就计算长宽比例,取大的那个scales,进行缩小,让图像刚好可以显示在graphicview中。
if(Ori_ImageHeight>ui->graphicsView->height()||Ori_ImageWidth>ui->graphicsView->width())
{
QMessageBox msgBox;
msgBox.setText("Size Warning");
msgBox.setInformativeText("This Image is too big ,need to clip it to property size?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
// Get the scales according to the size of image
if(float(Ori_ImageHeight)/float(ui->graphicsView->height())>
float(Ori_ImageWidth)/float(ui->graphicsView->width()))
{
Scales=1/ (float(Ori_ImageHeight)/float(ui->graphicsView->height()));
}
else
{
Scales=1/ (float(Ori_ImageWidth)/float(ui->graphicsView->width()));
}
switch (ret) {
case QMessageBox::Yes; cv::resize(LoadImage,LoadImage,cv::Size(Ori_ImageWidth*Scales,Ori_ImageHeight*Scales),0,0);
break;
default:
break;
}
}
测试:
读取一个桌面上的图像,该图像尺寸超过graphicview,graphicviews尺寸800*600 效果如图:鼠标追踪(用于后续鼠标选中图像或者画图等操作):
在构造函数中加入,激活控件的鼠标追踪:
ui(new Ui::ImageProcess)
{
ui->setupUi(this);
ui->graphicsView->setMouseTracking(true);
setMouseTracking(true);
ImageProcess::centralWidget()->setMouseTracking(true);
}
在头文件中,添加函数头。
void mousePressEvent(QMouseEvent* event);
鼠标按下 函数体:
此处,鼠标的追踪是相对于整个窗口的,我们只需要显示在graphicview中的鼠标位置,需要用直接追踪出的鼠标位置减去graphicview的位置,就得到在graphicview中的鼠标位置,鼠标位置用event下的pos()方法获取。头文件记得include QCursor
void ImageProcess::mousePressEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton)
{
setCursor(QCursor(Qt::ClosedHandCursor));
QPoint MouseMainPos=event->pos();
if(MouseMainPos.x()>=ui->graphicsView->x()&&
MouseMainPos.x()<=ui->graphicsView->x()+ui->graphicsView->width()&&
MouseMainPos.y()>=ui->graphicsView->y()&&
MouseMainPos.y()<=ui->graphicsView->y()+ui->graphicsView->height())
{
QPoint Mouse_In_Graphic_pos(MouseMainPos.x()-ui->graphicsView->pos().x(),
MouseMainPos.y()-ui->graphicsView->pos().y());
MousePosUpdate(Mouse_In_Graphic_pos);
}
}
}
效果如下,点击的是图中红色方点位置。鼠标位置被追踪显示在了主界面:
附上代码:
代码中有一些函数还没做,先放在这里了的,起作用的暂时是上面写的部分。
头文件:
#ifndef IMAGEPROCESS_H
#define IMAGEPROCESS_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace Ui {
class ImageProcess;
}
class ImageProcess : public QMainWindow
{
Q_OBJECT
public:
explicit ImageProcess(QWidget *parent = 0);
~ImageProcess();
QImage cvMat2QImage(const cv::Mat& mat);
cv::Mat QImage2cvMat(QImage image);
void GetOriginalDataOfTheImage();
protected:
void mousePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent *event);
void paintEvent(QPaintEvent* event);
void MousePosUpdate(QPoint mp);
private slots:
int on_OpenImage_Button_clicked();
void on_Exit_Button_clicked();
private:
Ui::ImageProcess *ui;
cv::Mat LoadImage;
QPixmap ImagePixmap;
int Ori_ImageHeight;
int Ori_ImageWidth;
int Ori_ImageDeepth;
int Ori_ImageChannel;
int ImageHeight;
int ImageWidth;
int ImageChannel;
};
#endif // IMAGEPROCESS_H
cpp:
#include "imageprocess.h"
#include "ui_imageprocess.h"
ImageProcess::ImageProcess(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ImageProcess)
{
ui->setupUi(this);
ui->graphicsView->setMouseTracking(true);//when this is open the graphics view widget can traking mouse
setMouseTracking(true);
ImageProcess::centralWidget()->setMouseTracking(true);
}
ImageProcess::~ImageProcess()
{
delete ui;
}
int ImageProcess::on_OpenImage_Button_clicked()
{
QString Fileadd=QFileDialog::getOpenFileName(NULL,"openfile",QDir::currentPath());
if(Fileadd.isEmpty())
{
QMessageBox::information(NULL,"notice","not opened");
return -1;
}
Fileadd.replace("/","\\");
std::string ImagePath=Fileadd.toStdString();
LoadImage=cv::imread(ImagePath,1);
if(!LoadImage.data)
{
QMessageBox::information(NULL,"Error","No file loaded or File name error!");
return -1;
}
float Scales;
GetOriginalDataOfTheImage();
if(Ori_ImageHeight>ui->graphicsView->height()||Ori_ImageWidth>ui->graphicsView->width())
{
QMessageBox msgBox;
msgBox.setText("Size Warning");
msgBox.setInformativeText("This Image is too big ,need to clip it to property size?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
// Get the scales according to the size of image
if(float(Ori_ImageHeight)/float(ui->graphicsView->height())>
float(Ori_ImageWidth)/float(ui->graphicsView->width()))
{
Scales=1/ (float(Ori_ImageHeight)/float(ui->graphicsView->height()));
}
else
{
Scales=1/ (float(Ori_ImageWidth)/float(ui->graphicsView->width()));
}
// cv::Size toSize(ui->graphicsView->width(),ui->graphicsView->height());
switch (ret) {
case QMessageBox::Yes: cv::resize(LoadImage,LoadImage,cv::Size(Ori_ImageWidth*Scales,Ori_ImageHeight*Scales),0,0);
break;
default:
break;
}
}
ImagePixmap=QPixmap::fromImage(cvMat2QImage(LoadImage));
QGraphicsScene *scene = new QGraphicsScene;
scene->addPixmap(ImagePixmap);
ui->graphicsView->setScene(scene);
ui->graphicsView->show();
ui->Width_Image_LineEdit->setText(QString::number(LoadImage.cols));
ui->Height_Image_LineEdit->setText(QString::number(LoadImage.rows));
}
QImage ImageProcess::cvMat2QImage(const cv::Mat& mat)
{
if(mat.type() == CV_8UC1)
{
QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
image.setColorCount(256);
for(int i = 0; i < 256; i++)
{
image.setColor(i, qRgb(i, i, i));
}
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;
}
else if(mat.type() == CV_8UC3)
{
const uchar *pSrc = (const uchar*)mat.data;
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return image.rgbSwapped();
}
else if(mat.type() == CV_8UC4)
{
const uchar *pSrc = (const uchar*)mat.data;
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();
}
}
cv::Mat ImageProcess:: QImage2cvMat(QImage image)
{
cv::Mat mat;
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;
default:
QMessageBox::warning(NULL,"warning","format is not right");
exit(0);
}
return mat;
}
void ImageProcess:: GetOriginalDataOfTheImage()
{
Ori_ImageHeight=LoadImage.rows;
Ori_ImageWidth=LoadImage.cols;
Ori_ImageDeepth=LoadImage.depth();
Ori_ImageChannel=LoadImage.channels();
}
void ImageProcess::on_Exit_Button_clicked()
{
QMessageBox msgBox;
msgBox.setText("The Image has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
exit(0);
/* switch (ret) {
case QMessageBox::Save:
this->savefileslot();//turn to save slot
// Save was clicked
break;
case QMessageBox::Discard:
event->accept();
// Don't Save was clicked
break;
case QMessageBox::Cancel:
event->ignore();
// Cancel was clicked
break;
default:
// should never be reached
break;
}
} else {
event->accept();
}*/
}
void ImageProcess::mousePressEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton)
{
setCursor(QCursor(Qt::ClosedHandCursor));
QPoint MouseMainPos=event->pos();
if(MouseMainPos.x()>=ui->graphicsView->x()&&
MouseMainPos.x()<=ui->graphicsView->x()+ui->graphicsView->width()&&
MouseMainPos.y()>=ui->graphicsView->y()&&
MouseMainPos.y()<=ui->graphicsView->y()+ui->graphicsView->height())
{
QPoint Mouse_In_Graphic_pos(MouseMainPos.x()-ui->graphicsView->pos().x(),
MouseMainPos.y()-ui->graphicsView->pos().y());
MousePosUpdate(Mouse_In_Graphic_pos);
}
}
}
void ImageProcess::mouseMoveEvent(QMouseEvent *event)
{
/* QPoint MouseMainPos=event->pos();
if(MouseMainPos.x()>=ui->graphicsView->x()&&
MouseMainPos.x()<=ui->graphicsView->x()+ui->graphicsView->width()&&
MouseMainPos.y()>=ui->graphicsView->y()&&
MouseMainPos.y()<=ui->graphicsView->y()+ui->graphicsView->height())
{
QPoint Mouse_In_Graphic_pos(MouseMainPos.x()-ui->graphicsView->pos().x(),
MouseMainPos.y()-ui->graphicsView->pos().y());
MousePosUpdate(Mouse_In_Graphic_pos);
}*/ //这个函数取消注释会一直追踪显示鼠标位置,此处没有设置采样时间,会很卡,如果要启用,请设置时间,不然也显示不好
}
void ImageProcess::mouseReleaseEvent(QMouseEvent *event)
{
setCursor(QCursor(Qt::ArrowCursor));
}
void ImageProcess::paintEvent(QPaintEvent* event)
{
}
void ImageProcess::MousePosUpdate(QPoint mp)
{
ui->MousePos_X->setText(QString::number(mp.x()));
ui->MousePosY->setText(QString::number(mp.y()));
}