qt学习笔记(3)Qt、opencv、vs2010本地读取图像、反转图像并显示



配置环境:qt5.2,opencv 2.4.8,vs2010,win8.1 32

http://download.csdn.net/detail/cy_543/7113933

注:读取图片的路径一定不要包含中文

Qt是跨平台C++图形用户界面应用程序开发框架。主要包括以下几个部分:(1)跨平台的IDE,被称为Qt Creater;(2)一系列Qt类库和开发工具。使用Qt SDK 开发C++应用有很多好处:

  1. Qt团队开发的开源代码,让你接触不同Qt组件的源代码、。

  2. 跨平台,意味着开一在不同的操作系统上开发,比如Windows,Linux,Mac OS X等。

  3. 包括了完整的跨平台GUI库,提供有效的面向对象和事件驱动的模型。

  4. Qt包括不同的跨平台库来发展多媒体、图形、数据库,多线程,web应用以及其对先进设计有用的模块。

上面这段话是从英文上翻译过来的,主要就是说可以跨多个平台。

尽管之前看了浅墨的文章,对于opencv的内容不再陌生,但是qt依然是自己的弱点。这篇文章就归类在qt里面了。因为我觉得,Qt的问题比较多,而涉及opencv的内容比较少。

这次要做的就是实现从本地读取图像,在Qt设计师中显示。然后反转再现实。打开图像显示如下:

qt学习笔记(3)Qt、opencv、vs2010本地读取图像、反转图像并显示_第1张图片

点击处理图像之后,显示如下:

qt学习笔记(3)Qt、opencv、vs2010本地读取图像、反转图像并显示_第2张图片


首先建立一个qt解决方案,命名为 imagprocess

步骤如下:

1、在Qt设计师中选择push_botton。显示的名字分别显示为打开图像、处理图像,objective_name分别为 open,process.

qt学习笔记(3)Qt、opencv、vs2010本地读取图像、反转图像并显示_第3张图片

2、梳理下本文的思路:点击打开图像,要在本地选择一张图像并输出;点击处理图像,图像被旋转,然后输出。主要就是为了实现这两个内容。

声明:由于在自己学习的时候,遇到了两个版本,一个简单,一个复杂。所以说,这里将会分成两块来说。为了不显得太复杂,就不用加标注的方法来说,就单独来说。

简单的显示:

31imagprocess.h内容填写,加粗的部分是需要我们填写的。在类的声明中,需要将用到的声明都写清楚,便于后续的使用。

#ifndefIMAGPROCESS_H

#defineIMAGPROCESS_H

 #include

#include"ui_imagprocess.h"

#include //getOpenFileName的类声明

#include

#include//常规的opencv声明

classimagprocess : public QMainWindow

{

      Q_OBJECT

public:

     imagprocess(QWidget *parent = 0);

      ~imagprocess();

private slots:

      voidon_open_clicked();

     voidon_process_clicked();//声明两个槽函数,分别对应openprocess

 private:

     Ui::imagprocessClass ui;

    cv::Mat image; // the image variable

};

#endif// IMAGPROCESS_H

总的来说,没有需要特别说明的。这些都是比较基本的,当然了在不知情的情况下。总是会出现很多的问题,这些都是在不断地阅读中明白的。没有什么文献可以阅读,书籍去约定俗称。遇到了,记下来,然后就可以了。

41imagprocess.cpp的填写。这个是关键,所以出现了很多问题。也算是写了很长时间。所以说,这里将会把自己遇到的众多问题跟大家分享一下。

#include"imagprocess.h"

using namespace cv;

imagprocess::imagprocess(QWidget*parent)

      : QMainWindow(parent)

{

     ui.setupUi(this);

      //connect(ui.open,SIGNAL(clicked()),this,SLOT(on_open_clicked()));

//connect(ui.process,SIGNAL(clicked()),this,SLOT(on_process_clicked()));

}

imagprocess::~imagprocess()

{

}


void imagprocess::on_open_clicked()

{

    QString fileName =QFileDialog::getOpenFileName(this, tr("Open Image"),  

    ".", tr("Image Files (*.png *.jpg *.jpeg*.bmp)")); 

  std::string str = fileName.toStdString();

   image=imread(str);

//image = cv::imread(fileName.toLatin1().data());

  namedWindow("Original Image");

  imshow("Original Image",image); 

}

 void imagprocess::on_process_clicked()

{

     flip(image, image, 1);    

     namedWindow("Output Image");   

    imshow("Output Image", image);

}

这是函数最核心的部分。将会详细去说:

(1)//connect(ui.open,SIGNAL(clicked()),this,SLOT(on_open_clicked()));

/connect(ui.process,SIGNAL(clicked()),this,SLOT(on_process_clicked()));

这个是槽函数的连接函数,如果在Qt设计师里没有添加槽函数的话,是需要用语句来写出来的。当然,程序运行了之后,我发现打开图像要进行两次,所以就想着把它注释掉,结果不影响运行。所以,这里我就比较疑惑。

当我还没写完的时候,问题就解决了:由于我在声明函数的过程中,使用了on_ 这样就有内置的函数,来完成链接。所以问题就变得更加简单了!

(2)void imagprocess::on_open_clicked()

{

  QString fileName =QFileDialog::getOpenFileName(this, tr("Open Image"),  

   ".",tr("Image Files (*.png*.jpg *.jpeg *.bmp)")); 

 std::string str = fileName.toStdString();

  image=imread(str);

  //image =cv::imread(fileName.toLatin1().data());

 namedWindow("Original Image");

 imshow("Original Image",image); 

}

函数on_open_clicked()的主体,当点击打开图像之后,就会执行这里的内容。当然,为了简单,并没有对异常情况进行判断。这个之后会慢慢来弥补。

QStringfileName = QFileDialog::getOpenFileName(this, tr("Open Image"),  

 ".", tr("Image Files (*.png*.jpg *.jpeg *.bmp)")); 

获取图像的路径,比如E\cat.jpg等。这个没什么好说的,很明了,就是自己去写的时候,需要多加注意。每个参数的意思也很明确。

std::stringstr = fileName.toStdString();

image=imread(str);

//image= cv::imread(fileName.toLatin1().data());

这三行内容放在一起说。前两行所要表达的内容和第三行是一样的。上一行中,fileNameQstring类型的,也就说想要利用cv::imread来显示不可能的。为了用imread来显示,先来看看imread的结构:

Matimaread(const string &filename,intflags=1)这里的filename要求是string来显示。所以就要转换了,第一行就是将Qstring转换成string.

第三行就直接可以了。

namedWindow("OriginalImage");

imshow("OriginalImage",image);

参考opencv的内容,本人已经烂熟于心,所以不多说。

(3)void imagprocess::on_process_clicked()

{

   flip(image, image, 1);   

  namedWindow("Output Image");   

   imshow("Output Image", image);

}

点击process,将会执行的函数内容。flip就是一个图像的翻转,没什么难度

   void flip(InputArray src, OutputArray dst, int flipCode); 

参数fipCode:整数,水平发转;0垂直反转;负数,水平垂直均反转。就是这样了。

Main函数不做处理就是了。

5、实验结果

void flip(InputArray src, OutputArray dst, int flip

qt学习笔记(3)Qt、opencv、vs2010本地读取图像、反转图像并显示_第4张图片


没什么问题哦!当然了,没有充分利用到qt,只是用了两个按钮。不过,这也让我们体验一下图像显示的小成就。

 

稍微复杂点的显示


 3.2 imagprocess.h


#ifndef IMAGPROCESS_H

#define IMAGPROCESS_H 

#include

#include "ui_imagprocess.h"

#include

#include//label的声明

#include//后面用的cvtColor的声明

#include

#include

class imagprocess : public QMainWindow

{

      Q_OBJECT

public:

     imagprocess(QWidget*parent = 0);

      ~imagprocess();

 private slots:

      void on_open_clicked();

    void on_process_clicked();

private:

     Ui::imagprocessClassui;

     cv::Mat image; // the image variable

};


 #endif // IMAGPROCESS_H

其他的内容跟简单的版本没有差别。

4.2 imagprocess.cpp

#include "imagprocess.h"

using namespace cv;

imagprocess::imagprocess(QWidget *parent)

      :QMainWindow(parent)

{

      ui.setupUi(this);

      //connect(ui.open,SIGNAL(clicked()),this,SLOT(on_open_clicked()));

   //connect(ui.process,SIGNAL(clicked()),this,SLOT(on_process_clicked()));

}

imagprocess::~imagprocess()

{

}

voidimagprocess::on_open_clicked()

{

QString fileName =QFileDialog::getOpenFileName(this, tr("Open Image"),  

 ".", tr("Image Files (*.png*.jpg *.jpeg *.bmp)")); 

 //std::string str = fileName.toStdString();

 //image=imread(str);

 image =cv::imread(fileName.toLatin1().data());

 cvtColor(image,image,CV_RGB2RGBA); 

  QImage img = QImage((const unsignedchar*)(image.data), image.cols, image.rows, QImage::Format_RGB32); 

  QLabel *label = new QLabel(this); 

  label->move(100, 20);//图像在窗口中所处的位置; 

   label->setPixmap(QPixmap::fromImage(img)); 

  label->resize(label->pixmap()->size());     

   label->show();

}

voidimagprocess::on_process_clicked()

{

    cv::flip(image, image, 1);   

    cv::cvtColor(image, image,CV_RGB2RGBA); 

       QImage img = QImage((const unsignedchar*)(image.data), image.cols, image.rows, QImage::Format_RGB32); 

       QLabel *label = new QLabel(this); 

       label->move(100, 20); 

       label->setPixmap(QPixmap::fromImage(img)); 

       label->resize(label->pixmap()->size());     

       label->show();

}


程序解释:

voidimagprocess::on_open_clicked()里面的内容:

(1)cvtColor(image,image,CV_RGB2RGBA); 

cvtColorOpencv里的颜色空间转换函数,可以实现RGB颜色向HSVHSI等颜色空间的转换,也可以转换成灰度图像。

void cvCvtColor( const CvArr*src, CvArr* dst, int code );

第一个参数是输入图像

第二个参数是输出图像

第三个参数是彩色空间转换的模式,能实现不同类型的颜色空间转换。比如CV_BGR2GRAY表示转换为灰度图,CV_BGR2HSV将图片从RGB空间转换为HSV空间。当code选用CV_BGR2HSV时,对于8位图,需要将RGB值归一化到0-1之间。这样得到HSV图中的H范围才是0-360SV的范围是0-1。图像在QT显示前,必须转化成QImage格式,图像在QT显示前,必须转化成QImage格式,RGBA格式转化成RGB。到底是什么格式转换成什么呢?这个有点疑惑,为什么成了RGBA转换成RGB了呢。这个也算是个遗留的问题吧。

2QImage img = QImage((const unsigned char*)(image.data),image.cols, image.rows, QImage::Format_RGB32); 

这句是将cv:image转换成QImage

3QLabel *label = new QLabel(this); 

QT平台下创建一个标签的语句。

4 label->move(100, 20); /

点的位置是(10020),图像的左上角坐标

5label->setPixmap(QPixmap::fromImage(img)); 

就是将Qimage显示,QPixmap的具体信息,还没有搞明白。

6label->resize(label->pixmap()->size());   

更改尺寸  

7label->show();

最后显示。从(3)-7)是QT图象显示的部分,还不算很明白。不过先记住!

on_process_clicked()函数就不多介绍了。

显示一个效果吧。分别是原始图像和反转图像。很显然,颜色有变化。那就是cvtColor的效果吧。不过,还是希望显示一个正常的颜色了。具体要怎么弄呢?以后再做研究。

qt学习笔记(3)Qt、opencv、vs2010本地读取图像、反转图像并显示_第5张图片

qt学习笔记(3)Qt、opencv、vs2010本地读取图像、反转图像并显示_第6张图片


注:写程序的过程中遇到的问题。

1class “QString”没有成员“toAscii”

这是在寻找别人程序的过程中看到的。然后就出现了这样的问题。然后将toAscii换成toLatin1OK了。这是由于版本升级导致的。2.4版本以后就不用toAscii了。

2Debud Error!R6010-abort() has been called

qt学习笔记(3)Qt、opencv、vs2010本地读取图像、反转图像并显示_第7张图片


这个问题太常见了。主要问题是:下标等越界,指针位置不恰当。而这里呢,是由于我犯了一个错误。就是在读取图片的过程中,路径是E\C++程序\cat.jpg里面包含了汉字。然后就出现了这个问题。个人认为,这样导致了fileName无法正确被使用,所以读取图片自己让对不对了。


因此,不管是什么语言编程,除了注释,方便自己去理解,一定要用英文的。这样才不会因为这些细小的问题,浪费了自己的时间。


 


 


 


 










你可能感兴趣的:(Qt)