在Linux Ubuntu平台上使用OpenCV 2.2显示图像Qt
嘿家伙, 我在使用OpenCV 2.2的Ubuntu 10.10上使用Qt作为我的C++ IDE平台。 我就写的代码,并显示块,其中的问题是:在Linux Ubuntu平台上使用OpenCV 2.2显示图像Qt
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
int main(int argc, char *argv[])
{
VideoCapture cap = VideoCapture(0);
Mat frame;
do
{
cap >> frame;
imshow("frame",frame);
} while (waitKey(10) != 27);
return 0;
}
我得到3警告印出似乎是这样的:
VIDIOC_QUERYMENU: Invalid argument
,一切似乎要被罚款(相机作品)。
我不得不添加了Qt的使用,并加入3行代码,它看起来像这样:
#include <QApplication>
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
VideoCapture cap = VideoCapture(0);
Mat frame;
do
{
cap >> frame;
imshow("frame",frame);
} while (waitKey(10) != 27);
return app.exec();
}
我仍然得到3条警告线,但现在,“帧”窗口是灰色的,并没有显示任何内容。
这是我第一次使用Qt,所以我真的不知道它是如何工作的。我只能猜测QApplication正在控制窗口管理,导致imshow
命令无法打开新窗口。
我会感谢您的帮助, THNX!
你的问题是与Qt处理自己的事件循环,因此OpenCV的事件循环饿死,永远不会运行。
让他们一起工作的方式非常简单:将OpenCV显示为QPixmap(通过将图像转换为QImage然后使用QLabel来显示它)。然后将此QLabel添加到您的QWidget。您的QWidget可以嵌入或成为QApplication的主要部件。
要使用你的简历的缓冲垫::图像作为你的QImage,看到这个答案how to convert an opencv cv::Mat to qimage
要显示此的QImage,看到 Display QImage with QtGui
你的假设是不正确的。 OpenCV将有自己的连接到X服务器,不受Qt窗口管理的影响(但是,waitKey()输入处理和app.exec()不会平行工作)。
我也测试了类似的代码,以发现任何未知的副作用。 OpenCV 2.2和Qt 4.6.2的所有窗口在我的Debian机器上都能正常工作。
你身边的一个简单测试可能是在你的while循环之后创建app对象。但是,它可能只是您的堆栈布局中的随机更改,导致您的警告成为严重问题?你还应该检查valgrind。
我最近遇到过类似的问题(使用OpenCV和Qt作为最终的GUI显示网络摄像头信息)。我发现播放视频(基本上是一组图像)的最佳方式是使用GLWidget。在这个GLWidget中,您可以创建一个矩形并为其添加纹理,其中纹理是要显示的图像。另一个问题是OpenCV和OpenGL的图像格式不同,但您可以通过更改通道的顺序轻松更改格式。
在你的代码中,你正在创建一个拥有自己的iddle进程的QApplication,所以你永远不会到达你的while循环。您还没有创建任何Qt显示窗口,我建议您检查Qt附带的示例以检查应用程序的基本结构,并从QMainWindow或QDialog开始。
的步骤是:
- 创建你的主窗口(QDialog是我用什么)。
- 创建一个GLWidget并将其添加到您的Dialog/MainWindow的布局中。
- 从OpenCV接收图像并将其转换为OpenGL正确显示的格式。
- 使用OpenGL,create a rectangle and attach the image as a texture。
不能混淆的事件循环的OpenCV的控制和qt的app.exec
要么使用cvNamedWindow的Qt风格,要么从openCV简单抓取图像并将它们显示在QLabel中。或者更好地继承QWidget并编写自己的QImage画家
void OpencvWidget::paintEvent(QPaintEvent*)
{
//m_win is the window size
QPainter p(this);
p.drawImage(m_win,m_image,m_image.rect());
}
恕我直言,使用OpenGL对于简单的imshow操作来说是不必要的复杂。 – 2011-03-02 17:11:52
当然,这取决于您认为必要的因素。他编写的代码是在while循环的每次迭代中接收一个新图像。根据我的经验,只有使用OpenGL,我才能避免在视频中闪烁(这正是我认为他正在尝试显示的内容)。 – sergi 2011-03-02 17:57:37