`

“愚蠢的四天”---QT与OpenCV的结合

 
阅读更多

       长沙这阴暗的天气已经持续好几天了,我也在这见不到太阳的天空下混混沌沌地度过了艰难的四天。虽然我成功搞定了大学最后一个体侧,以后终于能坐在操场旁静静地看着人家跑步,但是,我却丝毫没有半点如释重负的感觉,取而代之的是一种“黑云压城城欲摧”的压迫感,我度过了“愚蠢”的四天,为啥呢?为啥呢?作为程序员来讲,你懂得。一定是太久没见到太阳了····

       这次想将openCV结合QT来将自己之前所做的一些些东西(或者说是建立在理解基础上的抄袭)结合到QT上,做一个类似于图像处理的软件,这样我相信更加有成就感,于是我就开始了······“愚蠢”的四天:

 

       第一篇      openCV、QT与VS的环境配置

       要敲代码没有问题,首先要搞定环境问题。主要有以下两种环境搭配形式:

       (1)VS作为编程软件,openCV、QT作为库导入VS进行编程;

       (2)QT Greator作为编程软件,openCV作为库导入其中进行编程。

 坑爹的从这里就开始了!我一开始安装的就是VS2015,是最新版本的,当时也是觉得最新的应该功能更齐全吧(现在想抽自己)。于是,我尝试使用方法(1),将openCV、QT导入VS2015中,openCV早就已经配置好了,现在就是配置QT了。

 

一、VS2015配置QT(失败)

 VS配置QT的一般步骤是(VS已经安装完成):

                    1>  官网上下载正确的QT,并且傻瓜式安装(唯一要注意的是最好安装路径不要有中文、空格、“program files”、“document”等字眼)(官网:www.qt.io/download/

                    2>  配置QT的环境变量。将环境变量Path添加该路径(请示各自情况而定):F:\QT\5.5\msvc2012\bin;(否则可能会出现某些文件找不到|虽然装了插件,但是VS不按套路响应)

                    3>  官网上下载正确的QT-add-VS插件,并且傻瓜式安装(与上述注意相同最好!)

                    4>  正确完成上述两个步骤后,打开VS,可以发现工具栏多出了 QT5(这里安装的是QT5)选项:

我们点击QT5选项,选择最后一个“Qt Options”,配置QT路径

 

这里选择你安装的qt路径,VS将自动检测,若不相符合(比如说你下载的qt是vs-mingw的,用在vs2015那就是不行的)配置将不成功。

配置完成之后,环境设置就算成功了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

听上去是不是很简单,对,是很简单。然而我使用的是VS2015,当我做到第三步的时候,qt-add-vs一直提醒我“···不能检测到vs200x···”,真的不知道是我的插件下错了还是为何。。。挣扎了好久,最后还是觉得····失败了

或许是我其中某些环节忽略了,但是,惨痛的结果还是告诉我一个道理:

                       新的,可能是最完善的,但不一定是最合适、最方便的

                       第一个吃螃蟹的人,往往也会被螃蟹伤得体无完肤。。。。

                       吃蟹有风险,下河需谨慎啊!

 

 

二、 QT creator 配置openCV编程(失败)

看到网上很多人都在说,为什么不用QT自带的QTCreator?这玩意编程起来也是很方便的,并且对于初学者来说,QT Creator是非常好的选择。好吧,既然如此,那我就试试吧!

其实QT配置openCV是非常容易的事情,我们可以看到QT Creator界面如下:

 这里有个test.pro的属性表,类似于VS配置openCV时也添加了一个属性表,但是QT Creator里这个属性表是本身就存在的,并且有内容,如下:


 为了配置openCV,我们只需添加如下语句即可:

 


 实际上就是将openCV的运行目录和库文件包括进来,本质上是跟VS配置openCV道理是一样的。这样简单配置之后,openCV就可以在QT Creator运行了!代码写的飞起啊,这个QT Creator的智能识别我感觉也是非常的舒服顺手,瞬间觉得自己就无敌了!

 

然而······

 

编译时没有问题的,我在QT Creator中写了一个C++控制台的程序,就简单的几行openCV的代码:

                                    IplImage* img = cvLoadImage("1.png");

                                    cvNamedWindow("img");

                                    cvShowImage("img", img);

编译完美通过,没有问题,当结果出来的时候,我泪崩了,出现了一个窗口,没有图片!

没有图片····

没有图片····

我没有放弃,换了几个图片试了试,还是没有图片。

机智的我推测是不是img没有加载进来,于是调用了一下img->width,于是···程序崩溃了!(强制中断)

此时的我已经无力吐槽,代码从头到脚就三行,哪能有错?于是我上网查询解决方案,在进行了大量的搜索之后,得出了一个可能得结论:

        “版本较低的openCV在QT Creator中是可以完美运行的,较高的版本需要自己编译openCV才行”

我……&*¥&……*&……&&&*……&&*(&*(*(……&&……¥……##%……R^&&*&*

我的openCV版本是2-4-8,算是比较新的,所以可能造成了不能识别(这里可能说的不太恰当,不是不能识别,从智能代码补全可以看出库已经导入进来了,但是遇到了什么问题目前不得而知)的问题。

好吧,于是我开始自己编译openCV:

其实编译过程并不复杂,如下:

(1).首先,得下载一个Cmake软件,编译openCV。打开Cmake软件,如下图所示:

 这里的第一栏“where is the source code”就是你openCV的安装路径,第二栏“where to build the banaries”就是编译之后的文件所在地,这个任意创建即可;

这里选择框中的一大堆东西,我们只需要再勾选“WITH OPENGL”和“WITH QT”即可,其他不要动!

选择好之后,我们点击Configure。

在出现 “Configure Done”后,我们点击Generate生成build的文件,出现“Generate Done”后,这一步我们就算完成了!很好,这一步看上去难度并不是很大(前面说的正确下载版本以及路径配置时前提哦!不然血的教训告诉大家是会错的)

接下来,我们进入“cmd”界面,将路径转到刚刚Cmake build完之后的目录下,我这里是D:\opencvmake243,输入mingw-make,于是系统开始编译该目录下的文件。。。。。。。。。。。。

0%

1%

4%

····

24%

我擦,卡住了。一看出现错误了!!!!!!

core/operations.hpp:4024: error: got 2 template parameters for `void cv::AlgorithmInfo::addParam(cv::Algorithm&, const char*, cv:: Ptr<_Tp2>&, bool, cv::  Ptr<_Tp2> (cv::Algorithm::*)(), void (cv::Algorithm::*)(const cv:: Ptr<_Tp2>&), const std::string&)'

查了解决方法,即进入operations.hpp,将4021那行的函数给删掉即可。(还有很多问题参考http://www.ebaina.com/bbs/thread-5328-1-1.html,这也让我意识到,问题还有可能出现)

然而····

它总是不按套路出牌,各个网站上提出的问题,它都没有出现,反而出现了如下问题:

 首先我想说的是,找这个错误在哪,我的眼睛都要瞎了。。。然后,其实错误具体是什么并不是关键,可以看到,犯错误的文件已经不是openCV了,而是QT,这让我很无奈了。最终搞了很久也没有搞定这个问题。使用QT Creator的办法也就此宣告失败。。。

 

三、VS2012+QT+openCV(成功)

最终我选择了妥协,下载了vs2012,老老实实的按照一中所述的方法进行配置,终于成功了!这里我就不详细介绍了一个是一中叙述很详细,二是,我累了,心累了。。。。

 

 

其实还好,这样一看下来,会发现什么问题其实都只解决了一部分,说白了就是什么问题都没有解决,只是选择了一种妥协的办法来让我的学习进行下去。可是,乐观的我想想,这未尝不是好事呢,虽然很多的小问题都没有解决,但是妥协了之后也许可以解决最终的问题,牺牲小问题、解决大问题的这种做法,why not?以后的学习生活一定会碰到很多不顺利的地方,也许这里卡住了,换个方法就豁然开朗了呢!

恩,真会自我安慰。。。。

 

                                             第二篇     快速入门QT

 

一、基本原理理解-------信号与槽机制

 

要想尽快入门QT,那么掌握信号与槽机制是非常有必要的,这是QT区别于其他编程语言的独特之处。

类似于Java里的“事件”,信号与槽机制实际上就是一个触发与响应的机制,下面简单谈下我的理解以及基本的应用:

             信号,实际上就是一个触发器,提供信号的对象有很多,用得最多、最简单的一种就是按钮了,我们往往按下按钮,想要触发某种信号时,这时按下的这个动作就是一个信号!事实上几乎所有的控件都有他的信号,这个信号可以是自己定义的,也有QT中已经写好的,比如说,QT中自带的信号如下:

第一个是click(),实际上就是按下按钮后的信号。这些自带的信号不用自己再作定义,若想自行定义信号,则在头文件里,类的成员中加上如下:

                           public signals:

                                                   void mySignal();

然后再在.cpp文件中定义这个信号成员函数,注意,这里信号的类型只能是void。

 

槽实际上就是一个响应,在信号触发成功后,接下来的任务就是槽响应了!实际上如信号,QT中也定义了自己的槽,如:

 如果要自己定义槽,则在头文件中添加槽成员函数:

                                   public slots:

                                                 void mySlots();

再在.cpp文件中定义这个槽函数即可。

 

很关键的一点就是,虽然定义了信号和槽,那么他们如何连接呢?比如说我有一个按钮btn和标签label,想让按钮点击后标签消失,如何将这两个关联起来呢?QT提供了一个连接函数:

           

bool QObject::connect ( const QObject * sender, const char * signal, 
		 const QObject * receiver, const char * member ) [static]

解读出来实际上是     连接(发送对象,信号函数,接受对象,槽函数)

那么我们要达到目的,就可以在构造函数中添加一下联系:

                connect (btn, click(), label, destroy());

以上就是整个信号与槽机制的内容。

 

 

二、简单应用---与openCV结合显示图片

 

接下来,我们要结合openCV做一个小小的项目:点击按钮,显示图片!点击这个事件我们知道要用到信号与槽机制,那么还需要就是了解QT显示图像的机制。QT使用Qimage显示图像,而openCV使用IplImage显示图像,那么我们要进行转换:

QImage test2012::ImageCV2Qimg(IplImage* img)
{
 assert(img!=NULL);
 int h = img->height;
 int w = img->width;
 int channel = img->nChannels;
 QImage qimg = QImage(w, h, QImage::Format_RGB32);

 for(int i=0;i<h;i++) 
    { 
        for(int j=0;j<w;j++) 
        { 
            int r,g,b; 
            if(channel == 3) 
            { 
                b=(int)CV_IMAGE_ELEM(img,uchar,i,j*3+0); 
                g=(int)CV_IMAGE_ELEM(img,uchar,i,j*3+1); 
                r=(int)CV_IMAGE_ELEM(img,uchar,i,j*3+2); 
            } 
            else if(channel == 1) 
            { 
                b=(int)CV_IMAGE_ELEM(img,uchar,i,j); 
                g=b; 
                r=b; 
            } 
            qimg.setPixel(j,i,qRgb(r,g,b)); 
        } 
    } 
 return qimg;
}

Qimage的存储顺序是RGB,而IplImage的存储顺序是BGR,所以我们要按顺序恢复。

 

使用QT设计大师添加信号与槽机制:

打开.ui文件,QT设计大师将自动弹出,我们可以方便的在里面配置信号与槽机制,首先在放置想要的控件,这里是放置一个按钮;接着点击工具栏上的编辑信号\槽,在按钮上拖动下来,于是会自动弹出信号与槽机制的选择框,可以选择QT自带的,也可以手动添加自己写的函数: 

 

这里的showMyImage是我自己定义的槽函数:

void test2012::ShowMyImage()
{
 img = cvLoadImage("11.png");
 //IplImage* temp = cvCreateImage(cvGetSize(img), 8, 4);
 //cvCvtColor(img, temp, CV_BGR2BGRA);
 QImage qimg = ImageCV2Qimg(img);
 //QLabel *label = new QLabel(this); 
    this->label->setPixmap(QPixmap::fromImage(qimg));   
    this->label->resize(label->pixmap()->size()); 
    this->label->show();
}

这里Qimage是使用一个标签label显示图像,显示方法如上,还有Qpaint等其他的显示方法,后续介绍。程序到这里就编写完成,点击按钮,得到效果:
                        

 

于是,“愚蠢”的四天,我就干了点这事。当然,还稍许研究了下排序,稍后会写上。
 

         

 

 

 

      

  • 大小: 5.8 KB
  • 大小: 16.7 KB
  • 大小: 24.1 KB
  • 大小: 13.1 KB
  • 大小: 12.9 KB
  • 大小: 42 KB
  • 大小: 81.6 KB
  • 大小: 16.9 KB
  • 大小: 17.4 KB
  • 大小: 57.7 KB
  • 大小: 85.6 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics