open webcamera with OpenCV and show it with QLabel - white window

Cristina1986 picture Cristina1986 · Feb 6, 2013 · Viewed 19.5k times · Source

I work on Win7 x64 with OpenCV and Qt Libraries and VS 2010.

I would like to open my camera with OpenCV and then to show captured frames with Qt, for example using QLabel, after converting from Mat to QImage.

I want to do this because to use the functions imshow("camera", image) and waitKey() slows down streaming camera.

This is my code:

int main () {
 QApplication a(argc, argv);
 QLabel myLabel;
 VideoCapture cap(0);
 //namedWindow(c"camera", 1);

 for (;;) {

    cap >> image;
        //conversion from Mat to QImage
    Mat dest;
    cvtColor(image, dest,CV_BGR2RGB);
    QImage image1= QImage((uchar*) dest.data, dest.cols, dest.rows, dest.step, QImage::Format_RGB888);

        //show Qimage using QLabel
    myLabel.setPixmap(QPixmap::fromImage(image1));
    myLabel.show();
    //imshow("camera",image);
    //if (waitKey(30)>= 0)  break;
 }
return a.exec();
}   

Webcam is opened correctly and works, But I see a white window and not the captured frames, as you can see in this image enter image description here

If I uncomment: namedWindow (..), imshow(..), if(waitKey(..), it works (i see two windows with the same images), but I show captured frames with OpenCV and this is what I want to avoid.

My question is: I'm wrong in something?? I do not know, the conversion from Mat to Qimage is wrong ??.. Or, cannot I display captured frames only with Qt?

Thank you!

Answer

Nemanja Boric picture Nemanja Boric · Feb 6, 2013

I don't have much experience, but I can see what can go wrong here:

 for (;;) {

    cap >> image;
        //conversion from Mat to QImage
    Mat dest;
    cvtColor(image, dest,CV_BGR2RGB);
    QImage image1= QImage((uchar*) dest.data, dest.cols, dest.rows, dest.step, QImage::Format_RGB888);

        //show Qimage using QLabel
    myLabel.setPixmap(QPixmap::fromImage(image1));
    myLabel.show();
    //imshow("camera",image);
    //if (waitKey(30)>= 0)  break;
 }

You are doing this in dead loop - it will cause your QLabel to update itself infinitely, so you may not see anything. Also, if uncommenting waitKey is helping you, that pretty much mean that you are converting data to QImage well, but something other is broken.

Note that a.exec() will never execute, as you will be stuck in the loop, but I guess this was enough for hitting the concept.

In order not to stuck event loop, you need to create QTimer and every x milliseconds to update your widget:

 class VideoWindow: public QWidget
 {
    Q_OBJECT
    public:
        VideoWindow(QWidget* parent = 0): QWidget(parent), cap(0)
        {
            timer = new QTimer(this);
            connect(timer, SIGNAL(timeout()), this, SLOT(updatePicture()));
            timer->start(20);
        }


    public slots:
        void updatePicture()
        {
            cap >> image;
            //conversion from Mat to QImage
            Mat dest;
            cvtColor(image, dest,CV_BGR2RGB);
            QImage image1 = QImage((uchar*) dest.data, dest.cols, dest.rows, dest.step, QImage::Format_RGB888);

            //show Qimage using QLabel
            setPixmap(QPixmap::fromImage(image1));
        }

    private:
        QTimer * timer;
        VideoCapture cap;
};

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    VideoWindow w;
    w.show();

    app.exec();
    return 0;   
}