詳解 QT 框架中快速應用OpenCV 基于圖片 上篇
QT 框架中快速應用OpenCV 是本文要結(jié)束的內(nèi)容,和MFC比較起來,QT的信號槽機制比MFC的信號機制慢,但是因為能很好的實現(xiàn)跨平臺,所以我在這里總結(jié)一下可能對一些人有點用。OpenCV.China論壇上有一個帖子叫做《在MFC框架中快速應用OpenCV》看了后就想結(jié)合QT寫一下。
0搭建環(huán)境:OpenCV + QT 4.6
我的實驗是基于VS2008來做的,QT官方雖然提供了VS2008-add-in的插件,我沒有用。直接下載器編譯好的庫文件進行配置,OpenCV的在VS2008下面的配置方法Google一下到處都是,這里不再補充。首先需要做的是在VS2008里面你需要使QT下和OpenCV的程序能分別跑起來。對于QT在VS的配置其實挺簡單,有頭文件和相應的鏈接庫,保證調(diào)用的時候路徑正確,一般就沒有問題了。常用命令行make程序的人應該會很清楚那些IDE只不過是層畫皮。
1.顯示圖像
QWidget是QObject下的***個子類,使用它顯示圖像會減少不必要的開銷。首先定制一個自己需要的QWidget:
- class myWidget : public QWidget
- {
- Q_OBJECT
- public:
- myWidget(const IplImage *img,QWidget *parent = 0);
- ~myWidget();
- protected:
- void paintEvent(QPaintEvent *e);
- private:
- IplImage* iplImg;
- QImage *qImg;
- };
需要繪制一個圖像,我重載paintEvent(QpaintEvent *e),我在這里面使用QPainter進行繪制。
- void myWidget::paintEvent(QPaintEvent *e)
- {
- QPainter painter(this);
- painter.drawImage(QPoint(5,5),*qImg);
- }
rawImage(QPoint(5,5),qImg);的作用是將qImg繪制在左上頂點位于QPoint(5,5)處。
這里面有可能兩個問題,***個問題是要顯示的圖片太小,創(chuàng)建的Widget太大,***顯示比較丑陋。這時可以在此函數(shù)里面獲得qImg的寬高,然后resize一下就好了。另外一個問題是:繪制的時候使用的是QImage,不是IplImage類型。關于這個問題論壇上有人專門寫了IplImage <-> QImage的轉(zhuǎn)換代碼,我在這里不重復那個做法,一是有人已經(jīng)做了,另外處于效率考慮,這里提供另一種方法。
通常同學們都是用cvLoadImage來讀圖片,保存在IplImage里面,在這里這個圖片我們保存在img里面,然后通過img傳進QWidget,然后我new一個QImage
- qImg = new QImage(QSize(img->width,img->height),QImage::Format_RGB888);
我這里假設iplImg是RGB格式,且每個通道大小為8。然后創(chuàng)建一個IplImage 的文件頭
- iplImg = cvCreateImageHeader(cvSize(img.width(),img.height()),8,3);
此iplImage和QImage的不同之處在于QImage沒有直接提供創(chuàng)建文件頭的方法,可以通過如下方式創(chuàng)建只有文件頭數(shù)據(jù)的QImage
- qImg = new QImage(QSize(0,0),QImage::Format_RGB888);
另外兩者的圖像矩陣像素排列有點不同,比如IplImage中的BGR到了QImage中應該是RGB,當然單通道的灰度圖是一樣的,值得慶幸的是兩者的像素矩陣都是形狀相同的多維數(shù)組。這樣我們可以通過指針共享這部分數(shù)據(jù),一種方法如下:
- iplImg->imageData = (char*)qImg.bits();
將iplImg的圖像矩陣指到qImg那里,以后我們只需要對IplImage運用opencv里面的函數(shù)進行處理,其實就直接在處理qImg里面的數(shù)據(jù)了。但是現(xiàn)在的圖像數(shù)據(jù)還在img里面,首先得把數(shù)據(jù)搞到手,然后放到iplImg和qImg的共享區(qū)中去,另外將顏色排列以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(const IplImage *img,QWidget *parent /* = 0 */) : QWidget(parent)
- {
- qImg = new QImage(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);
- delete qImg;
- }
- void myWidget::paintEvent(QPaintEvent *e)
- {
- QPainter painter(this);
- painter.drawImage(QPoint(0,0),*qImg);
- }
調(diào)用的代碼很簡單:
- int main(int argc,char* argv[])
- {
- QApplication app(argc,argv);
- IplImage *img = cvLoadImage("460.jpg",1);
- if (img)
- {
- myWidget *mw = new myWidget(img);
- mw->show();
- }
- int re = app.exec();
- cvReleaseImage(&img);
- return re;
- }
小結(jié):關于詳解 QT 框架中快速應用OpenCV 上篇內(nèi)容介紹完了,希望本文讀你有所幫助,想要深入了解請看: