使用Qt創建第一個OpenCV的Gui應用


 

寫在前面

    學習OpenCV有一些小日子了,發現群里還有很多初學OpenCV的人像我當初一樣跌跌撞撞到處找資料,所以在這里把學習筆記分享給大家,希望有志學習OpenCV進行計算機視覺活動的小伙伴們能少走一些彎路。

    經過多方面查閱資料,了解到Qt開發平台對OpenCV的支持很好,但是在網上這方面的資料很少,能查到的大部分的圖形交互設計都是基於OpenCV2.0之前的數據結構IplImage,而OpenCV現在官方已經更新到2.4.9版本了。偶然發現一本好書最近得到了一本好書《 OpenCV 2 Computer Vision Application Programming Cookbook》,下載的鏈接為http://ishare.iask.sina.com.cn/f/20485520.html?retcode=0, 2011年5月出版,全書都是基於OpenCV2.2版本的實現,采用了新的數據結構,該書現在已經有中文版《OpenCV2計算機視覺編程手冊》2013年7月科學出版社出版。我這里強烈建議利用C++開發的朋友們不要再使用老版本的數據結構了,實在影響開發效率。至於大家最熟悉的參考書《learning OpenCV》和《OpenCV教程——基礎篇》這兩本廣為流傳的書,我的看法是已經遠遠不能滿足OpenCV新版本的學習了。老版本的OpenCV頭文件的包含格式一般是:

#include "cv.h"
#include "highgui.h"

     而2.2以后的版本頭文件包含一般為:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

    為了保持對之前版本的兼容,這些頭文件仍然能夠使用,但是建議使用新的包含方式。

打開並顯示圖片

       在Qt中,信號與槽是最重要的機制,這里我們可以創建一個按鈕、或者菜單、工具條,來作為發射信號的載體,用一個槽函數來接收打開這個動作。

QPushButton  OpenImageButton = new QPushButton( tr("Find Image") );
OpenImageButton->setDefault( false );
OpenImageButton->setEnabled( true );
       槽函數:打開文件可以利用Qt類QFileDialog來實現。
void qttest1::on_OpenImage_clicked()
{
   QString fileName = QFileDialog::getOpenFileName( this, tr( "Open Image" ), ".", tr("Image Files(*.png*.jpg*.jpeg*.bmp)"));
   image = cv::imread( fileName.toLocal8Bit().data());
   cv::imshow("Source Image", image);
}

     上面的函數已經實現了打開並顯示圖片。我們再添加一個按鈕,並定義一個函數來對圖片進行操作。

void qttest1::on_Process_clicked()
{
   cv::flip(image, image, 1);
   cv::namedWindow("Output Image");
   cv::imshow("Output Image", image);
}

      對於初學者,這些工作都做完之后,當然不要忘記連接信號與槽。

connect(OpenImageButton,SIGNAL(clicked()),SLOT(on_OpenImage_clicked()));
connect(ProcessButton,SIGNAL(clicked()),SLOT(on_Process_clicked()));

    這些工作做完以后,就可以打開並顯示圖片啦!

1

    3

        當然,有些同學可能會出現下面這樣的情況,記得在你的析構函數里釋放對象,

       cvDestroyAllWindows();

       按理說,OpenCV2是自動釋放對象的,樓主這里還沒有搞清楚,也請搞清楚的同學留言,非常感謝。

2

    小小改進一下吧

      單獨彈出一個窗口並顯示總是給人突兀的感覺,下面實現Qt的窗體中顯示圖片,顯示的方法有很多,不同的顯示方法存在着效率等各方面的問題,這里使用QImage轉QPixmap,然后用QLabel::setPixmap()來完成顯示,還有比較常用的方法是在paintEvent()中直接畫,具體的差異沒有去探究。

      我們寫一個小函數來實現:

void qttest1::displayMat(cv::Mat image)
{
   cv::Mat rgb;
   QImage img;
   if(image.channels()==3)
   {
       //cvt Mat BGR 2 QImage RGB
       cv::cvtColor(image,rgb,CV_BGR2RGB);
       img =QImage((const unsigned char*)(rgb.data),
                   rgb.cols,rgb.rows,
                   rgb.cols*rgb.channels(),
                   QImage::Format_RGB888);
   }
   else
   {
       img =QImage((const unsigned char*)(image.data),
                   image.cols,image.rows,
                   image.cols*image.channels(),
                   QImage::Format_RGB888);
   }

   imagelabel->setPixmap(QPixmap::fromImage(img));
   imagelabel->resize(imagelabel->pixmap()->size());
}

       最后的效果是這樣,是不是簡潔明了了很多?

4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM