Ubuntu下为OpenCV配置wxWidgets/OpenGL以及三者混合编程


OpenCV的GUI部分做的太简单了 复杂的功能难以实现 整合其他库时接口兼容性等问题多多 真费事 写个手记以备用

转载请注明http://blog.csdn.net/boksic 如有疑问欢迎留言

安装和配置工程


安装wxwidgets(http://wiki.wxwidgets.org/Installing_and_configuring_under_Ubuntu)

sudo apt-get install libwxgtk2.8-dev libwxgtk2.8-dbg

安装opengl

sudo apt-get install freeglut3-dev libglew1.5-dev

为链接器添加链接库选项

-lGLU -lglut

整合wxWidgets

编译时出现错误

/usr/include/wx/platform.h:196:22: fatal error: wx/setup.h: そのようなファイルやディレクトリはありません

编译选项的问题

给 compiler加上  `wx-config --cxxflags`

给 linker加上`wx-config --libs --gl-libs`

代码整合

首先 在运行wxWidgets的主循环函数时如何同时运行opencv或opengl的实时性函数(如摄像头捕获)

参考http://wiki.wxwidgets.org/Making_a_render_loop的文章

当中最好的方法是采用idle events 

首先要定义好显示opencv或opengl的面板派生类,本例中用的是BasicDrawPane和BasicGLPane(会在后面讲到)

	BasicDrawPane* drawPane;
	BasicGLPane *glPane;
其中drawPane是用来绘制OpenCV数据,glPane是用来绘制OpenGL数据。


机制是

在主frame的初始化函数中添加面板的显示函数

在主程序函数的onIdle中添加绘图函数

如果还要添加其他的实时显示 按照这个模式修改如下地方即可

class MyApp: public wxApp {
//省略
	BasicDrawPane* drawPane;
	BasicGLPane *glPane;
//省略
};

bool MyApp::OnInit() {

//省略
	drawPane = new BasicDrawPane(frame);
	sizer->Add(drawPane, 1, wxEXPAND);
	int args[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 };
	glPane = new BasicGLPane((wxFrame*) frame, args);
	sizer->Add(glPane, 1, wxEXPAND);
//省略
}

void MyApp::onIdle(wxIdleEvent& evt) {
	if (render_loop_on) {
		glPane->paintNow();
		drawPane->paintNow();
//省略
	}
}

完整的代码是

class MyFrame;

class MyApp: public wxApp {
	bool render_loop_on;
	bool OnInit();
	void onIdle(wxIdleEvent& evt);
	MyFrame* frame;
	BasicDrawPane* drawPane;
	BasicGLPane *glPane;
public:
	void activateRenderLoop(bool on);

};

IMPLEMENT_APP(MyApp)

class MyFrame: public wxFrame {

public:
	wxString CurrentDocPath;

	MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);

	void onClose(wxCloseEvent& evt) {
		wxGetApp().activateRenderLoop(false);
		evt.Skip(); // don't stop event, we still want window to close
	}
	void OnQuit(wxCommandEvent& event);

DECLARE_EVENT_TABLE()
};

enum {
	ID_Quit = 1
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Quit, MyFrame::OnQuit) 
EVT_CLOSE(MyFrame::onClose)
END_EVENT_TABLE()

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) {
	Close(true);
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) :
	wxFrame(NULL, -1, title, pos, size) {
	wxMenu *menuFile = new wxMenu;

	menuFile->Append(ID_Quit, _("E&xit") );
	wxMenuBar *menuBar = new wxMenuBar;
	menuBar->Append(menuFile, _("&File") );

	SetMenuBar(menuBar);

	CreateStatusBar();
	SetStatusText(_("http://blog.csdn.net/boksic"));
}

bool MyApp::OnInit() {

	render_loop_on = false;

	wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
	frame = new MyFrame(_("HMD Interface"), wxPoint(-1, -1), wxSize(1280, 530));

	drawPane = new BasicDrawPane(frame);
	sizer->Add(drawPane, 1, wxEXPAND);
	int args[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 };
	glPane = new BasicGLPane((wxFrame*) frame, args);
	sizer->Add(glPane, 1, wxEXPAND);
	frame->SetSizer(sizer);
	frame->SetAutoLayout(true);
	frame->Show();

	activateRenderLoop(true);

	cap = VideoCapture("input.avi");
	return true;
}

void MyApp::activateRenderLoop(bool on) {
	if (on && !render_loop_on) {
		Connect(wxID_ANY, wxEVT_IDLE, wxIdleEventHandler(MyApp::onIdle) );
		render_loop_on = true;
	} else if (!on && render_loop_on) {
		Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyApp::onIdle) );
		render_loop_on = false;
	}
}
void MyApp::onIdle(wxIdleEvent& evt) {
	if (render_loop_on) {
		glPane->paintNow();
		drawPane->paintNow();
		evt.RequestMore();
	}
}

而面板的模式可以参照如下opencv的显示

class BasicDrawPane: public wxPanel {

public:
    BasicDrawPane(wxFrame* parent);

    void paintEvent(wxPaintEvent& evt);
    void paintNow();
    void render(wxDC& dc);

DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(BasicDrawPane, wxPanel)
EVT_PAINT(BasicDrawPane::paintEvent) END_EVENT_TABLE()

BasicDrawPane::BasicDrawPane(wxFrame* parent) :
	wxPanel(parent) {
}

void BasicDrawPane::paintEvent(wxPaintEvent& evt) {
	wxPaintDC dc(this);
	render(dc);
}

void BasicDrawPane::paintNow() {
	wxClientDC dc(this);
	render(dc);
}

void BasicDrawPane::render(wxDC& dc) {

	if (cap.read(ori))//从摄像头读取一帧图像到mat数据ori中
		process();//自己的opencv处理函数

	cvtColor(frame, temp, CV_RGB2BGR);
	wxImage wxImage0(temp.cols, temp.rows, temp.data, true);
	wxBitmap wxBitmap0 = wxBitmap(wxImage0);
	dc.DrawBitmap(wxBitmap0, 0, 0);




}

当中一个关键点是是如何将opencv的mat数据显示出来 其实很简单的几句代码就可以了

frame和temp都是opencv的mat类数据

要将frame图像显示出来 先进行rgb到bgr转换 再wximage转换、wxbitmap转换即可

	cvtColor(frame, temp, CV_RGB2BGR);
	wxImage wxImage0(temp.cols, temp.rows, temp.data, true);
	wxBitmap wxBitmap0 = wxBitmap(wxImage0);
	dc.DrawBitmap(wxBitmap0, 0, 0);


显示opengl的类用的是wxGLCanvas的派生,区别不算大

class BasicGLPane : public wxGLCanvas
{
    wxGLContext*	m_context;
	CModel3DS * monkey;
public:
	BasicGLPane(wxFrame* parent, int* args);
	virtual ~BasicGLPane();

	void resized(wxSizeEvent& evt);

    	void paintEvent(wxPaintEvent& evt);
	void paintNow();
	void render(wxDC& dc);
	DECLARE_EVENT_TABLE()
};


BEGIN_EVENT_TABLE(BasicGLPane, wxGLCanvas)
EVT_PAINT(BasicGLPane::paintEvent) END_EVENT_TABLE()

GLMmodel* pmodel1 = NULL;

void BasicGLPane::paintEvent(wxPaintEvent& evt) {
    wxPaintDC dc(this);
    render(dc);
}

void BasicGLPane::paintNow() {
    wxClientDC dc(this);
    render(dc);
}




BasicGLPane::BasicGLPane(wxFrame* parent, int* args) :
    wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize,
            wxFULL_REPAINT_ON_RESIZE)
{





    m_context = new wxGLContext(this);

    // To avoid flashing on MSW
    SetBackgroundStyle(wxBG_STYLE_CUSTOM);

    int argc = 1;
    char* argv[1] = { wxString((wxTheApp->argv)[0]).char_str() };
    glutInit(&argc, argv);

//这里是opengl的初始化代码段 可以添加自己代码

}
BasicGLPane::~BasicGLPane() {    
	delete m_context;
}
void BasicGLPane::resized(wxSizeEvent& evt) {    
	Refresh();
}
void BasicGLPane::render(wxDC& dc) {   
	if (!IsShown())        
	return;   
	wxGLCanvas::SetCurrent(*m_context);    
	wxPaintDC(this);    
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//这里是opengl的绘图代码段 可以添加自己代码   
 	glFlush();   
 	SwapBuffers();
} 



















你可能感兴趣的:(Ubuntu下为OpenCV配置wxWidgets/OpenGL以及三者混合编程)