Showing an image using OpenCV 2.2 on a Linux Ubuntu platform with Qt

10,396

Solution 1

Your problem is with Qt handling its own event loop and thus the event loop of OpenCV is starved and never get run.

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.

To use the buffer of your cv::Mat image as your QImage, see this answer how to convert an opencv cv::Mat to qimage

To display this QImage, see Display QImage with QtGui

Solution 2

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).

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.

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.

Solution 3

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.

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.

The steps are:

  1. Create your main Window (QDialog is what I used).
  2. Create a GLWidget and add it to the layout of your Dialog/MainWindow.
  3. Receive the image from OpenCV and transform it to a format that OpenGL displays it correctly.
  4. Using OpenGL, create a rectangle and attach the image as a texture.

Solution 4

You can't mix openCV's control of the event loop and qt's 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

void OpencvWidget::paintEvent(QPaintEvent*)
{
    //m_win is the window size
    QPainter p(this);                           
    p.drawImage(m_win,m_image,m_image.rect());

}
Share:
10,396
Royi Freifeld
Author by

Royi Freifeld

Updated on June 04, 2022

Comments

  • Royi Freifeld
    Royi Freifeld almost 2 years

    I'm using Qt as 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:

    #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:

    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:

    #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.

    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.

  • Dat Chu
    Dat Chu about 13 years
    IMHO, using OpenGL is unnecessarily complex for a simple imshow operation.
  • sergi
    sergi about 13 years
    It depends on what you consider necessary, of course. The code that he wrote is receiving a new image every iteration of the while loop. In my experience, only using OpenGL I have been able to avoid flickering in a video (that's what I am supposed he is trying to display).