要把cvNamedWindow(char*,int flag)建立的視窗 顯示QT效能,如: 顯示座標、像素值、放大、pan 和save 等,
方法一:在編譯OpenCV庫時選中 WITH_QT。
方法二:在OpenCV常規庫建立後(也就是沒有選WITH_QT 項編譯的庫), 可以在C:\OpenCV231\opencv\modules\highgui\src原檔案目錄中,
copy 這3個檔案:window_QT.cpp、window_QT.h、window_QT.qrc 和一個目錄files_Qt\ 到自己的project\ 目錄下,並且:
1)注釋掉window_QT.h中line44,如“//#include "precomp.hpp"” ,
並添加 include 如: #include "cxcore.h"
#include "cv.h"
#include "highgui.h"”
2)注釋掉 window_QT.cpp中line43,如: //#if defined(HAVE_QT)” 和最後一行,“//#endif”
3)開啟window_QT.qrc的屬性,並且在:
Custom Build Step---->Command Line中:
"$(QTDIR)\bin\rcc.exe" -name window_QT -o ../GeneratedFiles/qrc_window_QT.cpp ../window_QT.qrc
Custom Build Step---->Discription:RCC window_QT.qrc
Custom Build Step---->Outputs:../GeneratedFiles/qrc_window_QT.cpp
Custom Build Step---->Additional Dependencies:"$(QTDIR)\bin\rcc.exe";"../window_QT.qrc"
4)在把編譯的“qrc_window_QT.cpp”檔案加入 項目中。
5)再次編譯,OK!
因為 上面3個檔案中重新用QT實現了highgui中的相關函數如cvNamedWindow(char*,int flag),在工程中包含 這上個檔案,程式中call的函數就直接到這3個檔案中找,而屏蔽掉了OpenCv庫中的相關函數了。
ps:1. 也許還要再Linker---->input 中加入QtTestd4.lib
2. 如果cvNamedWindow(char*,int flag)創立的視窗在子線程中(不在GUI線程中),則不能用 WITH_QT的OpenCV庫(i.e.方法一 、二都不行)。 這時,一個solution 就是 在子線程中用普通庫裡的 cvNamedWindow(char*,int flag),而在gui線程中用 帶有 WITH_QT庫 之中的cvNamedWindow_1(char*,int flag)(由cvNamedWindow()改名 ),即實現 在程式中用 兩種類型window。
方法三:實現 在程式中同時用 兩種類型window。也就是在方法二的基礎上把window_QT.cpp、window_QT.h兩個檔案中與 普通CV庫名字相同的函數 改名 (如加尾碼_1),以免發生call衝突!
CV_IMPL int cvWaitKey_1( int arg );
CV_IMPL int cvNamedWindow_1( const char* name, int flags );
CV_IMPL void cvDestroyWindow_1( const char* name );
CV_IMPL void cvDestroyAllWindows_1(void);
CV_IMPL void cvMoveWindow_1( const char* name, int x, int y );
CV_IMPL void cvResizeWindow_1(const char* name, int width, int height );
CV_IMPL int cvCreateTrackbar_1( const char* name_bar, const char* window_name, int* value, int count, CvTrackbarCallback on_change);
CV_IMPL int cvGetTrackbarPos_1( const char* name_bar, const char* window_name );
CV_IMPL void cvSetTrackbarPos_1( const char* name_bar, const char* window_name, int pos );
CV_IMPL void cvSetMouseCallback_1( const char* window_name, CvMouseCallback on_mouse,void* param );
CV_IMPL void cvShowImage_1( const char* name, const CvArr* arr );
一共modify了11個函數,這11個函數可以和 common CV庫 的類似函數共用了。並且還應在window_QT.h中開始部分對函數進行聲明!
Gui線程中用這11個函數沒有問題, 但要在子線程中用,就要 注意,首先必須在gui 線程中 create 新的Qwidge子類的執行個體( cvNamedWindow_1( )等11個函數在Qwidge子類的 implement(cpp檔案)中),然後再用QWidget::moveToThread( &thread_sub) 把QWidget子類的執行個體對象 移入 子線程中去,這樣就保證了在GUI主線程中create,在子線程run了。
不能是QOBject 的繼承類,只能是QWidget的繼承類!!!
如:
在mainwindow.h中定義了兩個類
//*********************************************
class DispThreadObject: public QWidget//QObject// 這裡只能是QWidget的子類,QObject不行!!!否則也會出現上面的錯誤
{
Q_OBJECT
public:
DispThreadObject();
~DispThreadObject();
void SetUseDisparity(int useDisparity);
Sequence seq1;
Sequence seq2;
CvStereoBMState *BMState;
cv::StereoSGBM sgbm;
CImageProcessingThread* thread_A;
CImageProcessingThread* thread_B;
bool mm_break;
public slots:
void slotDispTreadObject();
private:
int m_useDisparity;
};
//%%%%%%%%%%%%%
GUI主類
class MyMainWindow: public QMainWindow
{
Q_OBJECT
public:。。。。。
QThread dispThread;
DispThreadObject dispObject;
};
在mainwindow.cpp中
//*********************************************
void MyMainWindow::slotDisparityOnline_Thread()
{
。。。。。。
connect(&dispThread,SIGNAL(started()),&dispObject,SLOT(slotDispTreadObject()));
dispObject.moveToThread(&dispThread);
dispThread.start();
。。。。。。
};
//%%%%%%%%%%%%%%%%%%%%%
void DispThreadObject::slotDispTreadObject()
{
int numSaved=0;
std::string filename;
int width=782;
int height=582;
IplImage* imageL = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 1);
IplImage* imageR = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 1);
IplImage* disparity = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 1);
cvNamedWindow_1("display disparity_SGBM",1);
while(numSaved< m_useDisparity){
if (mm_break){
break;
}
if(!(thread_A->imageQueue.empty()) && !(thread_B->imageQueue.empty())){
seq1.name= (thread_A->imageQueue.front()).name;
seq1.frame=(thread_A->imageQueue.front()).frame;
//*********
seq2.name= (thread_B->imageQueue.front()).name;
seq2.frame=(thread_B->imageQueue.front()).frame;
//production and consumption model to queue
thread_A->usedBytes.acquire();
thread_A->imageQueue.pop();//popping an used element
thread_A->freeBytes.release();
thread_B->usedBytes.acquire();
thread_B->imageQueue.pop();
thread_B->freeBytes.release();
//decide left or right image.
if (seq1.name.compare(0,1,"L")) {
//gray image
cvCvtColor(seq1.frame,imageL,CV_BGR2GRAY);
cvCvtColor(seq2.frame,imageR,CV_BGR2GRAY);
} else if (seq2.name.compare(0,1,"L")) {
cvCvtColor(seq2.frame,imageL,CV_BGR2GRAY);
cvCvtColor(seq1.frame,imageR,CV_BGR2GRAY);
}
//combine file name
char ch = seq1.name.at(seq1.name.size()-5);
filename="disp";
filename.append(1,ch);
filename.append(".png");
//int runTime = DisparityAlgorithm::stereoSGBM(imageL,imageR,disparity,sgbm);//
int runTime = DisparityAlgorithm::stereoBM(imageL,imageR,disparity,BMState);
cvShowImage_1("display disparity_SGBM",disparity);
cvWaitKey_1(1);
//cvSaveImage(filename.c_str(),disparity);
//release space
cvReleaseImage(&seq1.frame);
cvReleaseImage(&seq2.frame);
filename.clear();
++numSaved;
if (0/*stop push_button*/){
break;
}
}
}
cvReleaseImage(&imageL);
cvReleaseImage(&imageR);
cvDestroyWindow_1("display disparity_SGBM");
}//