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

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:
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?
How to convert an OpenCV image into something (bitmap?) that the preferred GUI can display (and perhaps save)?
(Optional) How to convert an image that was loaded using the preferred interface into a form that OpenCV can use?

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;
}

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)

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?
Answer: I don't see why it should not be doable or it is a poorly designed library (which I don't think OpenCV is).
For your other questions (and the "How" of question 1), I did a quick search on QtCentre and found an interesting thread about OpenCV integration with Qt. There is some source code examples that you can look at.
If you don't find what your are looking for in that thread you can start a new one.
Or google for OpenCV integration in Qt or search on Google Code, there is some projects using both Qt and OpenCV (OpenCV Stereo Vision is one).
Good luck.

Well I don't know much about OpenCV, but I work with wxWidgets alot.
I highly recommend wxWidgets simply because of its intuitive structure and code layout.
Also, QT is only available under the LGPL on Windows, so licensing may be an issue. wxWidgets can be used in commercial projects without restrictions.
As for converting images back and forth, wxWidgets has a large number of classes/functions for working with images.

I have made a little progress. The GUI part of OpenCV does seem to stay out of the way. I have even used it in a WxWidgets application to show an image, and nothing bad seemed to happen. That was on a Windows XP box using VC++ 2008. The only interaction that OpenCV/highGUI appears to have with the windowing system is to make direct Windows API calls and to monitor the event queue for keyboard events, which it passes on.
I'm working on how to convert from OpenCV images to WxWidgets images and back. A big help you guys are. :-)

Related

Qt use of Class and CLassPrivate

When examining classes written by Qt, I discover many contain a class called "Class", and another called "ClassPrivate". For example QFile contains QFile and QFilePrivate, QIODevice contains QIODevice and QIODevicePrivate.
What is the purpose of this design?
This is a common design pattern called private implementation, or pimpl for short. Qt actually calls it d/q pointer, but it is the same thing.
The Q_D and Q_Q macros are part of a design pattern called the d-pointer (also called the opaque pointer) where the implementation details of a library may be hidden from its users and changes to the implementation can be made to a library without breaking binary compatibility.
The main reason for this in binary compatibility. Qt, unlike many other projects like boost, has had the guarantee of API (source) and ABI (binary) compatibility for the same major version.
So, the API and ABI would not break e.g. inside the Qt 5.x series. They would have to change the major version to break any of this.
Now, the private implementation really helps with this as the implementation details are no longer in the publicly available header file.
They can add further private members (method or variable) in the private implementation while the public interface would still online contain a private implementation pointer.
This makes the public interface completely opaque allowing flexibility in changing the implementation details without having to worry about the public interface.
Here is an example they give:
class Widget
{
// ...
private:
Rect m_geometry;
String m_stylesheet; // NEW in WidgetLib 1.1
};
class Label : public Widget
{
public:
// ...
String text() const
{
return m_text;
}
private:
String m_text;
};
This would break the client code using Widget causing a crash. However, if you hide the implementation details of the Widget class behind a private pointer, you can do anything with it since it is hidden. So, in the above example, you can add "m_stylesheet" without any risks and the client code using Label will not crash.
In case you wonder why binary compatibility is such a big deal: Qt has been a popular framework used by many applications, some really big. It would be a major pain in the neck to upgrade the Qt dependency for them if it did not offer binary compatibility.
When designing libraries like Qt, it is desirable that applications that dynamically link to Qt continue to run without recompiling even after the Qt library is upgraded/replaced with another version. For example, if your application CuteApp was based on Qt 4.5, you should be able to upgrade the Qt libraries (on Windows shipped with the application, on Linux often comes from package manager automatically!) from version 4.5 to Qt 4.6 and your CuteApp that was built with Qt 4.5 should still be able to run.
Basically, when you upgrade Qt in this way for your application, you can just drop in the new version without even having to recompile your application. And the features of your application will just keep working as before. This is great because you do not need to send a new version of your application to the customers. They can just upgrade Qt on their side and benefit from performance improvements in Qt or bug fixes indeed, etc.
And as a matter of convention, these private implementation are written in Qt inside files with the _p.h suffix.
You can also refer to this page for further binary compatibility examples.
In Qt 4.8, we see this structure please look at this doc
But in Qt6 we don't have QFilePrivate or ClassPrivate classes. look at this
If you see in Qt 4.8 Structure of classes has one QObjectData and one QObject
for more detail, you can compare this source which was for Qt 4.8 and now the new version of QObject class.
QFile inherits QObject and QFilePrivate inherits QObjectData
What is the purpose of this design?
I guess they want to provide very strong encapsulationYou cannot access the d pointer as a user of the API, which is the whole point of encapsulation.
d_ptr is a pointer in QObject class in Qt 4.8
Look at D-Pointer document.
The trick is to keep the size of all public classes of a library
constant by only storing a single pointer. This pointer points to a
private/internal data structure that contains all the data. The size
of this internal structure can shrink or grow without having any
side-effect on the application because the pointer is accessed only in
the library code and from the application's point of view the size of
the object never changes - it's always the size of the pointer. This
pointer is called the d-pointer.
The spirit of this pattern is outlined in the code below (all code in
this article doesn't have destructors, of course you should add them
in real code).

Get Window ID from xcb using a class or name

I want to use Qt's QWindow::fromWinID function to draw widgets onto an external window (hopefully this will work).
Unfortunately, I need to draw on a window which has a certain name/class (I can show it using xwininfo and xprop). The only code I can find to do this is inside the source of xwininfo and xprop, but it seems like a bunch of unnecessary code to do a simple thing: find the window with a certain property equal to some string, and return its window ID for Qt to use. Unfortunately, I'm very badly versed in XCB, and wouldn't know how to start.
How can I do this without 200 lines of code?
The only code I can find to do this is inside the source of xwininfo and xprop
Which really is a great resource, alongside with xdotool.
find the window with a certain property equal to some string
Yeah, but there's no X11 built-in that does this, which is why those tools go that way. Then there's things to consider like reparenting and non-reparenting window managers, i.e., whether or not you need to descend into the client window and so on.
I'm afraid there's no much easier way. Low-level X programming, whether with Xlib or XCB, just brings some verbosity.
One thing you could consider is using the library extracted from (and used by) xdotool, called libxdo. It would offer this functionality for you in xdo_search_windows. The library uses (and therefore pulls in) Xlib rather than XCB, though.
Here's a sample program you can compile with gcc -lxdo test.c:
#include <xdo.h>
int main() {
xdo_t *xdo = xdo_new(NULL);
xdo_enter_text_window(xdo, CURRENTWINDOW, "A", 0);
return 0;
}

Saving recording to MP3 container in Qt

I am programming on the Windows 7 platform using Qt 4.8.4, Qt Mobility 1.2 and C++. I am attempting to record audio from the front jack and save it to a file in mp3 format. I have the program working with the LAME encoder, but the file is being saved as WAV.
It appears that I have no control over the container type, which is defaulting to PCM/WAV.
Here are the QAudioEncoderSettings I am using:
QAudioEncoderSettings settings;
settings.setCodec("audio/mpeg");
settings.setSampleRate(boxValue(ui->sampleRateBox).toInt());
settings.setBitRate(boxValue(ui->bitrateBox).toInt());
settings.setQuality(QtMultimediaKit::EncodingQuality(ui->qualitySlider->value()));
settings.setEncodingMode(ui->constantQualityRadioButton->isChecked() ?
QtMultimediaKit::ConstantQualityEncoding :
QtMultimediaKit::ConstantBitRateEncoding);
QString container = "audio/x-mp3";
capture->setEncodingSettings(settings, QVideoEncoderSettings(), container);
A post recording conversion is not an option, as the files may become quite large, and the probability that the process would be ended before the conversion was complete is quite high.
Thank you for any help provided.
You can try Qt Media Encoding Library for that - http://qt-project.org/forums/viewthread/29117/

QT5 QSound does not play all wave files

I am in the midst of migrating our app based on QT4.X to QT5. Phonon support has been removed in QT5, so I have changed my code that plays a wave file to use QSound.
Change is pretty straightforward. I just had to use QSound, which is now located in Multimedia library. Here is the code:
QSound::play("small_wave_file.wav");
For most of my wave files, this works just fine; however, for my wave file(with 44100Hz sample rate) it does not work.
Official QT bug can be found here.
UPDATE: This bug has been fixed in qt 5.1
It turns out that some wave files confuse QSound. Still not sure exactly what causes the issue. When I loaded my wave file in Audacity, and then exported it back to a different wave file without any changes(same sample rate...). QSound played the file just fine.
In MacOSX when I click "Get Info" on the problematic wave file, general wave info record from the wave file was not available; so perhaps QSound was unable to get sample rate information from; and because it did not know which sample rate to expect from the wave file?
The interesting part is that iTunes played the original file just fine, and it had the correct sample rate somehow. Also Phonon used to play the original file as well just fine.
Anyhow, hopefully this helps with some people that had issues with QSound::play() method.
UPDATE: Since QSound::play() was very buggy on the mac, I opted to use the native NSSound to play my wave files from QT application on the mac. Here is the code:
void play_sound( const char* file)
{
NSSound *sound = [[NSSound alloc] initWithContentsOfFile:[NSString stringWithUTF8String:file] byReference:NO];
[sound play];
[sound release];
}
Also note that Qt has several different sound playback APIs. For small file playback with lower latency I found this to be much faster:
http://doc.qt.io/qt-5/qsoundeffect.html#details
Also:
http://doc.qt.io/qt-5/qmediaplayer.html

Cross-platform custom cursors for Qt, cursor in resource file

I feel like I'm missing something since I can't see any way to easily do a cross-platform cursor in Qt. That is, I'd like to use a standard cursor editor, or just a common cursor file type, and stick it in the resource file.
I see a couple platform specific manners providing handles (meaning I couldn't load from a resource) or a generic way taking a pixmap. In the pixmap method I would then have to find someway to store the hotspot along with the pixmap.
I don't want animated cursors, just a plain color image (32x32).
What is the easiest way to handling this?
I'm currently working on an application where I'd like to have some nice custom cursors. The way I'm doing that is:
Add an image to a Qt resource file (*.qrc) - I am working with PNG with transparency exported from an SVG (always have your original art sources in SVG for things like this in case you need scaling)
<RCC>
<qresource prefix="/">
<file alias="default">cursors/cursor_default.png</file>
</qresource>
</RCC>
This will allow you to ship your cursors along with your application since Qt resource files are converted to C++ sources, which are then added to your binary
In your source code do:
QPixmap cursor_pixmap = QPixmap(":cursor_default");
QCursor cursor_default = QCursor(cursor_pixmap, 0, 0);
setCursor(cursor_default);
There are two important things to notice here both related to the constructor of the QCursor - the pixmap you add to it and the hotspot coordinates (here both set to 0 which is the top left corner of the pixmap that represents the shape of your cursor). There are actually 2 constructors for QCursor which are imho useful here:
- `QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX = -1, int hotY = -1)` - this allows you to use a mask to manipulate the pixels of your cursor
- `QCursor::QCursor(const QPixmap &pixmap, int hotX = -1, int hotY = -1)` - if you are working with a PNG or other supported image format which allows transparency you can omit the mask as it is in my case.
The hotspot is a very essential part of a cursor - it tells your application which part of your cursor is the "trigger" that is the spot which does something compared to the rest which is just fancy visuals and nothing functional.
While looking for resources on Qt customization of cursors I found this article (the image above is from it), which I can totally recommend every one, interested in this topic, to read.
In terms of storing the hotspot I don't think that something like this is necessary. After all your resource files are compiled and added to the binary hence when you assign a hotspot to a cursor inside your code it will be there. I doubt that any OS actually has a format (let alone multi-platform one) that stores both the cursor and its hotspot due to the fact that depending on the application you may want to change the hotspot (for example due to scaling the bitmap itself in order to have multiple sizes) which would be a lot more difficult if you have it bound to the cursor's bitmap. If you really want to go the distance with this (I would advise against it) you can create your own custom file format which contains both. Since the Qt resource files are - to my knowledge - meant for managing images you would have to implement the whole IO mechanics in order to support your custom format.
Hope this helps. The solution above is as cross-platform as you can get with the Qt framework. Note however that the custom QCursor will only be available inside your application and wherever you have set it in. Cursor that is above the window frame for example is considered OS-specific due to the fact that the window frame itself is an OS-specific feature and if you want to alter its behaviour you will have to go a lot deeper (and also outside Qt's safe zone) meaning check how cursors are handled on an OS-level.

Resources