要把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");
}//