How to get wxOpenCv demo
What is wxOpenCv ?
WxOpenCv is a simple demo application to show you how to integrate wxWidgets with OpenCv library. The application take the video stream from a camera and displays it a window. Also, it adds a green rectangle to every frame and shows you how many frames per second you receive. Aditionaly,
I did a small hack to provide access to the system/driver control parameters of the camera. Note, that this might not be the best optimization of the speed or resources as this is not a scope of this project. The image bellow represents a snapshot of the application running.
Download the source zip file from here and unzip the file. Inside you will have the source code, the msvc++ 6.0 project files and also the executable (release version) compiled already for the widows. Then you can open the project in have a look at the code.
Project files explained
There are six cpp files aith as many header in the project and their functionality is briefly described bellow.
How does it work
The way I implemented this is fairly simple. I use a thread (worker) to pull frames from the camera object and feeds this into the camera view. The main challenge I encounter initially was how to convert from the IPL image format used by opencv to something wxwidtgets can work with which is bitmap. I will start first with some details on this conversion, see bellow:
- camview.cpp - class CCamView , method DrawCam, is where the conversion takes place. Bellow is a snapshot.
// get raw data from ipl image
cvGetRawData( pDstImg, &rawData, &step, &roiSize );
// convert data from raw image to wxImg
wxImage pWxImg = wxImage( nCamWidth, nCamHeight, rawData, TRUE );
// convert to bitmap to be used by the window to draw
m_pBitmap = wxBitmap( pWxImg.Scale(m_nWidth, m_nHeight) );
Where pDstImg is a copy of the ipl image received from the camera +/- extra drawing, and m_pBitmap is the bitmap used by the CcamView
class to draw onto the window.
- camera.cpp class CCamera, method GetNextFrame, is where I receive the first frame from the camera covert it to RGB and feed it into the camera view. See the code sample bellow (actually simplified).
// grab frame from camera
pFrame = cvQueryFrame( m_pCapture );
// convert from BGR to RGB
cvConvertImage( pFrame, m_pVideoImg, CV_CVTIMG_FLIP | CV_CVTIMG_SWAP_RB );
// draw frame on the camera view
m_pCameraView->DrawCam( m_pVideoImg );
The GetNextFrame method is called by the Run method of the camera object which also does some checking on either the camera was paused or parameters or changed. The camera Run method is called from within the worker thread main loop.
- worker.cpp class CwxopencvWorker, method Entry, is where I periodically call for a new frame the camera object +/- a given delay by default set at 5ms.
The camera control panel hack
I found a way to access the camera control panel using the a VFW dummy structure. It was a bit of a pain since vfw is more like a black box. You will find this implemented in file frame.cpp, class CGUIFrame, methods OnVideoFormat and OnVideoSource as per the following snapshot:
// create a dummy structure to use for conversion for dlg call
typedef struct CvCaptureCAM_VFW
// convert capture reference to the VFW dummy structure
CvCapture* ptest = pView->m_pCamera->m_pCapture;
CvCaptureCAM_VFW* p = (CvCaptureCAM_VFW*) ptest;
// call the camera video source config panel using the capture windows reference from the dummy structure
capDlgVideoSource( p->capWnd );
Portability on other platforms (Linux, MacOS, etc)
Given that both libraries are portable, there should be possible to be able to compile this code, at least on Linux. You will find that in the camera.cpp file I differentiate the code by platform using the WIN32_LARRY define. I did manage to get this working on Linux as well, some three years ago or so, but ever since then I neglected the portability issue, however I left the code in place. I remember at the time that I had some problems to get the Logitech webcam driver to work under Linux which should be ok by now. If you do manage to get this ported over and tested let me know.
Well, once again this is just one way to demonstrate how its possible to integrate these to libraries. If you find any bugs or better ways to implement or optimize this demo please let me know at: email@example.com.