在带有 Qt 的 Linux Ubuntu 平台上使用 OpenCV 2.2 显示图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5170571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Showing an image using OpenCV 2.2 on a Linux Ubuntu platform with Qt
提问by Royi Freifeld
Hey guys, I'm using Qtas my C++ IDE platform over Ubuntu 10.10 with OpenCV 2.2. I'll just write pieces of code and show where the problem is:
大家好,我在 Ubuntu 10.10 和 OpenCV 2.2 上使用Qt作为我的 C++ IDE 平台。我将只编写代码段并显示问题所在:
#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;
}
I get 3 warning printouts that seems something like this:
我得到 3 个警告打印输出,看起来像这样:
VIDIOC_QUERYMENU: Invalid argument
And everything seems to be fine (the camera works).
一切似乎都很好(相机工作正常)。
I had to add usage of the Qt and added 3 lines of code, and it looks like this:
我不得不添加 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();
}
I still get the 3 warning lines but now, the "frame" window is grey, and nothing is shown.
我仍然收到 3 条警告线,但现在,“框架”窗口是灰色的,什么也没有显示。
This is my first time using Qt, so I don't really know how it works. I can only guess that QApplication is getting control over the window management, that causes the imshow
command to not be able to open a new window.
这是我第一次使用Qt,所以我真的不知道它是如何工作的。我只能猜测 QApplication 正在控制窗口管理,导致imshow
命令无法打开新窗口。
I would appreciate your help, THNX!
感谢您的帮助,THNX!
采纳答案by Dat Chu
Your problem is with Qt handling its own event loop and thus the event loop of OpenCV is starved and never get run.
你的问题是 Qt 处理它自己的事件循环,因此 OpenCV 的事件循环是饥饿的,永远不会运行。
The way to get them to work together is quite simple: Display your OpenCV as a QPixmap (by convert your image to QImage then use QLabel to display it). Then add this QLabel to your QWidget. Your QWidget can either be embedded or become the main widget of your QApplication.
让它们一起工作的方法非常简单:将您的 OpenCV 显示为 QPixmap(通过将您的图像转换为 QImage,然后使用 QLabel 来显示它)。然后将此 QLabel 添加到您的 QWidget。您的 QWidget 可以被嵌入或成为您的 QApplication 的主要小部件。
To use the buffer of your cv::Mat image as your QImage, see this answer how to convert an opencv cv::Mat to qimage
要将 cv::Mat 图像的缓冲区用作 QImage,请参阅此答案如何将 opencv cv::Mat 转换为 qimage
To display this QImage, see Display QImage with QtGui
要显示此 QImage,请参阅 使用 QtGui 显示 QImage
回答by ypnos
Your assumption is not correct. OpenCV will have its own connection to the X server and not be affected by Qt's window management (however, waitKey() input handling and app.exec() will not trivially work in parallel).
你的假设是不正确的。OpenCV 将有自己的 X 服务器连接,并且不受 Qt 窗口管理的影响(但是,waitKey() 输入处理和 app.exec() 不会并行工作)。
I also tested similar code to spot any unforseen side effects. All windows are drawing fine on my Debian machine with OpenCV 2.2 and Qt 4.6.2.
我还测试了类似的代码以发现任何不可预见的副作用。在我的带有 OpenCV 2.2 和 Qt 4.6.2 的 Debian 机器上,所有窗口都可以正常绘制。
A trivial test on your side could be to create the app object just after your while loop. However, it may be just the random change in your stack layout that caused your warnings to become a serious issue? You should also check with valgrind.
对你来说一个简单的测试可能是在你的 while 循环之后创建 app 对象。但是,可能只是堆栈布局的随机变化导致您的警告成为严重问题?您还应该检查 valgrind。
回答by sergi
I have faced a similar problem recently (displaying webcam information using OpenCV and Qt as the final GUI). The best way that I find out to play the video (which is basically a set of images) is to use a GLWidget. In this GLWidget you can create a rectangle and attach a texture to it, where the texture is the image that you want to show. Another problem is that the format of the image is different for OpenCV and OpenGL, but you can easily change the format by changing the order of the channels.
我最近遇到了类似的问题(使用 OpenCV 和 Qt 作为最终 GUI 显示网络摄像头信息)。我发现播放视频(基本上是一组图像)的最佳方法是使用 GLWidget。在这个 GLWidget 中,您可以创建一个矩形并为其附加纹理,其中纹理是您要显示的图像。另一个问题是 OpenCV 和 OpenGL 的图像格式不同,但是您可以通过更改通道的顺序轻松更改格式。
In your code, you are creating an QApplication that has its own iddle process, so you never reach your while loop. You also haven't created any Qt display window, I recommend you to check the examples that come with Qt to check the basic structure of the application and start with a QMainWindow or a QDialog.
在您的代码中,您正在创建一个 QApplication ,它具有自己的中间进程,因此您永远不会到达您的 while 循环。您还没有创建任何 Qt 显示窗口,我建议您查看 Qt 附带的示例以检查应用程序的基本结构,并从 QMainWindow 或 QDialog 开始。
The steps are:
步骤是:
- Create your main Window (QDialogis what I used).
- Create a GLWidgetand add it to the layout of your Dialog/MainWindow.
- Receive the image from OpenCV and transform it to a format that OpenGL displays it correctly.
- Using OpenGL, create a rectangle and attach the image as a texture.
- 创建您的主窗口(我使用的是QDialog)。
- 创建一个GLWidget并将其添加到 Dialog/MainWindow 的布局中。
- 从 OpenCV 接收图像并将其转换为 OpenGL 正确显示的格式。
- 使用 OpenGL,创建一个矩形并将图像附加为纹理。
回答by Martin Beckett
You can't mix openCV's control of the event loop and qt's app.exec
你不能混合 openCV 的事件循环控制和 qt 的 app.exec
Either use the Qt flavour of the cvNamedWindow, or simple grab images from openCV and display them in a QLabel. Or better inherit from QWidget and write your own QImage painter
要么使用 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());
}