Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV with other GUI (like Qt or WxWidgets) on Win32 VC++

I want to use OpenCV's image processing functions, but not the OpenCV GUI. I'm using OpenCV 2.0. I will use either Qt4 or WxWidgets for GUI functions. I compile with VC++ 2008 Express (VC++ 9.0).

I guess it breaks down to two or three questions:

  1. Is it necessary to do something to disable OpenCV's higui so it does not interfere with the preferred GUI library, and if so, how?

  2. How to convert an OpenCV image into something (bitmap?) that the preferred GUI can display (and perhaps save)?

  3. (Optional) How to convert an image that was loaded using the preferred interface into a form that OpenCV can use?

like image 929
Jive Dadson Avatar asked Feb 05 '10 22:02

Jive Dadson


2 Answers

Okay. I've got the answer to my own question for WxWidgets. One key is not to fight openCV City Hall about RGB sequence. OpenCv really likes "BGR". WxWidgets uses "RGB" only. The opencv data structure has a field for byte sequence, but it is seldom honored. Even the highGui function (on MS Windows) that displays an image will put up spectacularly blue tangerines if the byte sequence is set to "RGB". I stubbornly fixed that bug in my local installation, but other operations failed also. So, I just sigh and set the byte order on the opencv side to "BGR" and do the byte swapping as necessary.

The C++ code below requires that the openCV images that it converts to wxImages are RGB, sequence "BGR", 8 bit depth and 3 interleaved channels, and have width_step = width*3. The routines don't check compatibility. Use at your own peril. A ready-for-primetime version would provide for regions of interest (ROI) and other fanciness.

#include "wx/wx.h"
#include "cv.h"
#include "highgui.h" // Optional


void copy_and_swap_rb(char *s, char *d, int size) {
    // Copy image data source s to destination d, swapping R and B channels.
    // Assumes 8 bit depth, 3 interleaved channels, and width_step = width*3
    const int step = 3;
    char *end = s + size;
    while (s<end) {
        d[0] = s[2];
        d[1] = s[1];
        d[2] = s[0];
        d += step; s += step;   
    }
}

void wx2cv(wxImage &wx, IplImage *ipl) {
    // Copy image data from wxWidgets image to Ipl (opencv) image
    // Assumes ipl image has seq "GBR", depth 8, and 3 channels, and 
    // has the same size as the wxImage, and width_step = width*3.
    copy_and_swap_rb((char*)wx.GetData(), ipl->imageData, ipl->imageSize);
}

void cv2wx(IplImage *ipl, wxImage &wx ) {
    // Copy image data from Ipl (opencv) image to wxImage
    // Assumes ipl image has seq "GBR", depth 8, and 3 channels, and 
    // has the same size as the wxImage, and width_step = width*3.
    copy_and_swap_rb( ipl->imageData, (char*)wx.GetData(),   
                      wx.GetWidth()*wx.GetHeight()*3);
}

IplImage *cv_from_wx(wxImage &wx) {
    // Return a new IplImage copied from a wxImage. 
    // Must be freed by user with cvReleaseImage().
    IplImage *ret = cvCreateImage(cvSize(wx.GetWidth(), wx.GetHeight()), 
                                  IPL_DEPTH_8U, 3);
    wx2cv(wx, ret);
    return ret;
}

wxImage wx_from_cv( IplImage *cx) {
    // Return new wxImage copied from a compatible IplImage.
    // Assumes ipl image has seq "GBR", depth 8, and 3 channels
    // Fear not. The copy on return is cheap; does not deep-copy the data.
    wxImage wx(cx->width, cx->height, (unsigned char*) malloc(cx->imageSize), false);
    cv2wx(cx, wx);
    return wx;
}
like image 175
9 revs Avatar answered Oct 07 '22 17:10

9 revs


I know I'm super late to this discussion, but I just happened across it. Anyways, I've been using OpenCV and wxWidgets together quite happily for a few years now, so I thought I'd pitch in:

Is it necessary to do something to disable OpenCV's higui so it does not interfere with the preferred GUI library, and if so, how?

Not generally. There are a couple hiccups that you can run into for specific versions of OpenCV and Windows. For the most part, though, the integration is very smooth. I routinely use wx for my front end and the parts of highgui that enable image capture. I've done this on several versions of Windows, Ubuntu, and OS X.

How to convert an OpenCV image into something (bitmap?) that the preferred GUI can display (and perhaps save)?

An alternative to copying back and forth between a wxImage is stuffing the IplImage's data directly into an OpenGL texture and painting it on a wxGLCanvas. One big advantage for this strategy is that you can then draw on top of the texture using standard OpenGL methods.

(Optional) How to convert an image that was loaded using the preferred interface into a form that OpenCV can use?

Don't :) I use wxFileDialog etc to let the user specify paths, but all of the backend is directly OpenCV.

(begin self plug)

Code I've written to do a lot of this is part of a project called MADTraC, which is a GUI/application framework for real-time computer vision applications.

(end self plug)

like image 44
dantswain Avatar answered Oct 07 '22 19:10

dantswain