在Win32 VC++上,将OpenCV与其他GUI(如Qt或WxWidgets)结合使用

17

我想使用OpenCV的图像处理函数,但不使用OpenCV GUI。我正在使用OpenCV 2.0版本,并将使用Qt4或WxWidgets进行GUI功能开发。我使用VC++ 2008 Express(VC++ 9.0)进行编译。

我猜这可以分为两个或三个问题:

  1. 是否需要禁用OpenCV的高级GUI,以免它干扰首选的GUI库,如果是,应该如何操作?

  2. 如何将OpenCV图像转换为首选GUI可以显示(并且可以保存)的格式(例如位图)?

  3. (可选)如何将使用首选接口加载的图像转换为OpenCV可以使用的格式?

5个回答

5
好的。我已经得到了关于WxWidgets的答案。其中一个关键是不要与openCV City Hall争RGB序列的问题。OpenCv非常喜欢“BGR”。WxWidgets仅使用“RGB”。尽管opencv数据结构有一个字节序列字段,但很少被使用。即使是在显示图像的高级GUI函数(在MS Windows上),如果字节序列设置为“RGB”,也会出现明显的蓝色柑橘效果。我固执地在我的本地安装中修复了这个错误,但其他操作也失败了。所以,我只能叹气并将opencv侧的字节顺序设置为“BGR”,并根据需要进行字节交换。
以下C++代码要求将其转换为wxImages的openCV图像为RGB,序列为“BGR”,8位深度和3个交错通道,并且width_step = width*3。这些例程不检查兼容性。使用需谨慎。一个适合生产环境的版本将提供ROI和其他花哨功能。
#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;
}

这似乎适用于RGB图像。如果我有一个灰度IplImage呢? - Sunny

5

我知道我来参与这个讨论已经很晚了,但我刚好看到了。无论如何,我已经使用OpenCV和wxWidgets一起工作了几年,所以我想做出贡献:

是否有必要禁用OpenCV的higui以使其不干扰首选GUI库?如果是,应该怎么做?

通常情况下不需要。但是,对于特定版本的OpenCV和Windows,您可能会遇到一些问题。但大多数情况下,集成非常顺畅。我经常在我的前端中使用wx 启用图像捕获的高级界面部分。我在几个版本的Windows、Ubuntu和OS X上都这样做过。

如何将OpenCV图像转换为首选GUI可以显示(并可能保存)的内容(位图?)?

除了在wxImage之间来回复制外,还可以将IplImage的数据直接填充到OpenGL纹理中,并在wxGLCanvas上绘制它。这种策略的一个重要优点是,您可以使用标准的OpenGL方法在纹理上绘制。

(可选)如何将使用首选接口加载的图像转换为OpenCV可以使用的形式?

最好不要 :) 我使用wxFileDialog等让用户指定路径,但所有后端都是直接OpenCV。

(自我推销)

我编写的代码可以完成这些工作,是一个名为MADTraC的项目的一部分,该项目是用于实时计算机视觉应用程序的GUI /应用程序框架。

(结束自我推销)


1
需要采取措施禁用OpenCV的higui以避免与首选GUI库产生干扰吗?如果需要,应该怎么做?
答案:我认为这是可行的,或者它是一个设计不良的库(我不认为OpenCV是这样的)。
对于您的其他问题(第一问题的"How"),我在QtCentre上进行了快速搜索,并找到一个有关OpenCV integration with Qt的有趣线程。其中有一些源代码示例供您参考。
如果在该线程中没有找到您要查找的内容,则可以开始一个新线程。
或者在Google上搜索OpenCV integration in Qt,或者在Google Code上搜索,有一些同时使用Qt和OpenCV(例如OpenCV Stereo Vision)的项目。
祝好运。

0

我对OpenCV不是很了解,但我经常使用wxWidgets。

我强烈推荐wxWidgets,因为它具有直观的结构和代码布局。

此外,QT在Windows下仅可在LGPL下使用,因此许可可能成为问题。而wxWidgets可以在商业项目中无限制地使用。

至于图像的转换,wxWidgets有大量用于处理图像的类/函数。


3
我看到 QT(无论在 Windows 还是 Linux 上)使用 LGPL 许可证的唯一问题是:如果 Jive 改变了 QT 库并不想分享他的更改,那就不行了。除此之外,没有必要担心任何许可证问题。 - Symbiosoft

0

我已经有了一些进展。OpenCV的GUI部分似乎不会妨碍程序运行。我甚至在一个使用WxWidgets的应用程序中使用它来显示图像,没有发生任何问题。这是在Windows XP上使用VC++ 2008进行的。OpenCV/highGUI与窗口系统唯一的交互是直接调用Windows API并监视键盘事件队列,然后将其传递。

我正在研究如何从OpenCV图像转换为WxWidgets图像以及如何反向转换。你们真是太棒了。:-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接