OpenCV 轻量级而且高效,由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
QT 框架中快速应用OpenCV 是本文要结束的内容,和MFC比较起来,QT的信号槽机制比MFC的信号机制慢,但是因为能很好的实现跨平台,所以我在这里总结一下可能对一些人有点用。OpenCV.China论坛上有一个帖子叫做《在MFC框架中快速应用OpenCV》看了后就想结合QT写一下。
0搭建环境:OpenCV + QT 4.6
我的实验是基于VS2008来做的,QT官方虽然提供了VS2008-add-in的插件,我没有用。直接下载器编译好的库文件进行配置,OpenCV的在VS2008下面的配置方法Google一下到处都是,这里不再补充。首先需要做的是在VS2008里面你需要使QT下和OpenCV的程序能分别跑起来。对于QT在VS的配置其实挺简单,有头文件和相应的链接库,保证调用的时候路径正确,一般就没有问题了。常用命令行make程序的人应该会很清楚那些IDE只不过是层画皮。
1.显示图像
QWidget是QObject下的***个子类,使用它显示图像会减少不必要的开销。首先定制一个自己需要的QWidget:
- classmyWidget:publicQWidget
- {
- Q_OBJECT
- public:
- myWidget(constIplImage*img,QWidget*parent=0);
- ~myWidget();
- protected:
- voidpaintEvent(QPaintEvent*e);
- private:
- IplImage*iplImg;
- QImage*qImg;
- };
需要绘制一个图像,我重载paintEvent(QpaintEvent *e),我在这里面使用QPainter进行绘制。
- voidmyWidget::paintEvent(QPaintEvent*e)
- {
- QPainterpainter(this);
- painter.drawImage(QPoint(5,5),*qImg);
- }
rawImage(QPoint(5,5),qImg);的作用是将qImg绘制在左上顶点位于QPoint(5,5)处。
这里面有可能两个问题,***个问题是要显示的图片太小,创建的Widget太大,***显示比较丑陋。这时可以在此函数里面获得qImg的宽高,然后resize一下就好了。另外一个问题是:绘制的时候使用的是QImage,不是IplImage类型。关于这个问题论坛上有人专门写了IplImage <-> QImage的转换代码,我在这里不重复那个做法,一是有人已经做了,另外处于效率考虑,这里提供另一种方法。
通常同学们都是用cvLoadImage来读图片,保存在IplImage里面,在这里这个图片我们保存在img里面,然后通过img传进QWidget,然后我new一个QImage
- qImg=newQImage(QSize(img->width,img->height),QImage::Format_RGB888);
我这里假设iplImg是RGB格式,且每个通道大小为8。然后创建一个IplImage 的文件头
- iplImg=cvCreateImageHeader(cvSize(img.width(),img.height()),8,3);
此iplImage和QImage的不同之处在于QImage没有直接提供创建文件头的方法,可以通过如下方式创建只有文件头数据的QImage
- qImg=newQImage(QSize(0,0),QImage::Format_RGB888);
另外两者的图像矩阵像素排列有点不同,比如IplImage中的BGR到了QImage中应该是RGB,当然单通道的灰度图是一样的,值得庆幸的是两者的像素矩阵都是形状相同的多维数组。这样我们可以通过指针共享这部分数据,一种方法如下:
- iplImg->imageData=(char*)qImg.bits();
将iplImg的图像矩阵指到qImg那里,以后我们只需要对IplImage运用OpenCV里面的函数进行处理,其实就直接在处理qImg里面的数据了。但是现在的图像数据还在img里面,首先得把数据搞到手,然后放到iplImg和qImg的共享区中去,另外将颜色排列以QImage中的RGB顺序为标准。
- if(img->origin==IPL_ORIGIN_TL)
- {
- cvCopy(img,iplImg,0);
- }
- else
- {
- cvFlip(img,iplImg,0);
- }
- cvCvtColor(iplImg,iplImg,CV_BGR2RGB);
实际上只要做到这里图片就能显示了。如下图所示
给出myWidget.cpp完整代码
- #include"myWidget.h"
- #include<QtGui\QPainter>
- #include<QtCore\QPoint>
- myWidget::myWidget(constIplImage*img,QWidget*parent/*=0*/):QWidget(parent)
- {
- qImg=newQImage(QSize(img->width,img->height),
- QImage::Format_RGB888);
- iplImg=cvCreateImageHeader(cvSize(img->width,img->height),
- 8,3);
- iplImg->imageData=(char*)qImg->bits();
- if(img->origin==IPL_ORIGIN_TL)
- {
- cvCopy(img,iplImg,0);
- }
- else
- {
- cvFlip(img,iplImg,0);
- }
- cvCvtColor(iplImg,iplImg,CV_BGR2RGB);
- this->resize(img->width,img->height);
- }
- myWidget::~myWidget()
- {
- cvReleaseImage(&iplImg);
- deleteqImg;
- }
- voidmyWidget::paintEvent(QPaintEvent*e)
- {
- QPainterpainter(this);
- painter.drawImage(QPoint(0,0),*qImg);
- }
调用的代码很简单:
- intmain(intargc,char*argv[])
- {
- QApplicationapp(argc,argv);
- IplImage*img=cvLoadImage("460.jpg",1);
- if(img)
- {
- myWidget*mw=newmyWidget(img);
- mw->show();
- }
- intre=app.exec();
- cvReleaseImage(&img);
- returnre;
- }
小结:关于详解 QT 框架中快速应用OpenCV 上篇内容介绍完了,希望本文读你有所帮助,想要深入了解请看:
详解 QT 框架中快速应用OpenCV 基于视频播放 下篇。