歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

詳解 QT 框架中快速應用OpenCV

QT 框架中快速應用OpenCV 是本文要結束的內容,和MFC比較起來,QT的信號槽機制比MFC的信號機制慢,但是因為能很好的實現跨平台,所以我在這裡總結一下可能對一些人有點用。

0搭建環境:OpenCV + QT 4.6

我的實驗是基於VS2008來做的,QT官方雖然提供了VS2008-add-in的插件,我沒有用。直接下載器編譯好的庫文件進行配置,OpenCV的在VS2008下面的配置方法Google一下到處都是,這裡不再補充。首先需要做的是在VS2008裡面你需要使QT下和OpenCV的程序能分別跑起來。對於QT在VS的配置其實挺簡單,有頭文件和相應的鏈接庫,保證調用的時候路徑正確,一般就沒有問題了。常用命令行make程序的人應該會很清楚那些IDE只不過是層畫皮。

1.顯示圖像

QWidget是QObject下的第一個子類,使用它顯示圖像會減少不必要的開銷。首先定制一個自己需要的QWidget:

  1. class myWidget : public QWidget
  2. {
  3. Q_OBJECT
  4. public:
  5. myWidget(const IplImage *img,QWidget *parent = 0);
  6. ~myWidget();
  7. protected:
  8. void paintEvent(QPaintEvent *e);
  9. private:
  10. IplImage* iplImg;
  11. QImage *qImg;
  12. };

需要繪制一個圖像,我重載paintEvent(QpaintEvent *e),我在這裡面使用QPainter進行繪制。

  1. void myWidget::paintEvent(QPaintEvent *e)
  2. {
  3. QPainter painter(this);
  4. painter.drawImage(QPoint(5,5),*qImg);
  5. }

rawImage(QPoint(5,5),qImg);的作用是將qImg繪制在左上頂點位於QPoint(5,5)處。

這裡面有可能兩個問題,第一個問題是要顯示的圖片太小,創建的Widget太大,最後顯示比較丑陋。這時可以在此函數裡面獲得qImg的寬高,然後resize一下就好了。另外一個問題是:繪制的時候使用的是QImage,不是IplImage類型。關於這個問題論壇上有人專門寫了IplImage <-> QImage的轉換代碼,我在這裡不重復那個做法,一是有人已經做了,另外處於效率考慮,這裡提供另一種方法。

通常同學們都是用cvLoadImage來讀圖片,保存在IplImage裡面,在這裡這個圖片我們保存在img裡面,然後通過img傳進QWidget,然後我new一個QImage

  1. qImg = new QImage(QSize(img->width,img->height),QImage::Format_RGB888);

我這裡假設iplImg是RGB格式,且每個通道大小為8。然後創建一個IplImage 的文件頭

  1. iplImg = cvCreateImageHeader(cvSize(img.width(),img.height()),8,3);

此iplImage和QImage的不同之處在於QImage沒有直接提供創建文件頭的方法,可以通過如下方式創建只有文件頭數據的QImage

  1. qImg = new QImage(QSize(0,0),QImage::Format_RGB888);

另外兩者的圖像矩陣像素排列有點不同,比如IplImage中的BGR到了QImage中應該是RGB,當然單通道的灰度圖是一樣的,值得慶幸的是兩者的像素矩陣都是形狀相同的多維數組。這樣我們可以通過指針共享這部分數據,一種方法如下:

  1. iplImg->imageData = (char*)qImg.bits();

將iplImg的圖像矩陣指到qImg那裡,以後我們只需要對IplImage運用opencv裡面的函數進行處理,其實就直接在處理qImg裡面的數據了。但是現在的圖像數據還在img裡面,首先得把數據搞到手,然後放到iplImg和qImg的共享區中去,另外將顏色排列以QImage中的RGB順序為標准。

  1. if (img->origin == IPL_ORIGIN_TL)
  2. {
  3. cvCopy(img,iplImg,0);
  4. }
  5. else
  6. {
  7. cvFlip(img,iplImg,0);
  8. }
  9. cvCvtColor(iplImg,iplImg,CV_BGR2RGB);

實際上只要做到這裡圖片就能顯示了。如下圖所示

給出myWidget.cpp完整代碼

  1. #include "myWidget.h"
  2. #include <QtGui\QPainter>
  3. #include <QtCore\QPoint>
  4. myWidget::myWidget(const IplImage *img,QWidget *parent /* = 0 */) : QWidget(parent)
  5. {
  6. qImg = new QImage(QSize(img->width,img->height),
  7. QImage::Format_RGB888);
  8. iplImg = cvCreateImageHeader(cvSize(img->width,img->height),
  9. 8,3);
  10. iplImg->imageData = (char*)qImg->bits();
  11. if (img->origin == IPL_ORIGIN_TL)
  12. {
  13. cvCopy(img,iplImg,0);
  14. }
  15. else
  16. {
  17. cvFlip(img,iplImg,0);
  18. }
  19. cvCvtColor(iplImg,iplImg,CV_BGR2RGB);
  20. this->resize(img->width,img->height);
  21. }
  22. myWidget::~myWidget()
  23. {
  24. cvReleaseImage(&iplImg);
  25. delete qImg;
  26. }
  27. void myWidget::paintEvent(QPaintEvent *e)
  28. {
  29. QPainter painter(this);
  30. painter.drawImage(QPoint(0,0),*qImg);
  31. }

調用的代碼很簡單:

  1. int main(int argc,char* argv[])
  2. {
  3. QApplication app(argc,argv);
  4. IplImage *img = cvLoadImage("460.jpg",1);
  5. if (img)
  6. {
  7. myWidget *mw = new myWidget(img);
  8. mw->show();
  9. }
  10. int re = app.exec();
  11. cvReleaseImage(&img);
  12. return re;
  13. }

小結:關於詳解 QT 框架中快速應用OpenCV 上篇內容介紹完了 見 http://www.linuxidc.com/Linux/2013-04/83226.htm ,希望本文讀你有所幫助,想要深入了解請看:

詳解 QT 框架中快速應用OpenCV 基於視頻播放 下篇 http://www.linuxidc.com/Linux/2013-04/83226p2.htm。

Copyright © Linux教程網 All Rights Reserved