QT - Display WebCam on a QLabel using another Thread?

1

Hello, I'm doing a project in C ++ using GUI QT. In the project in question I need to display images of a camera in the window, but in doing so, the performance of the window is very compromised, all other buttons and features that it includes in the window are slow, overwhelmed it seems. Here is the image capture code for the device.

  void mainwindow::on_ButtonShowCamera_clicked(){

ligaCam = true;

if(!this->cap.isOpened()){ // se ja estiver aberto, nao abre denovo //
    this->cap.open(0);
}

QImage img;

while(ligaCam == true){
    Mat frame;
    this->cap.read(frame);

    img = MatToQImage(frame); // converte tipo Mat para QImage //
    ui->labelScreen->setPixmap(QPixmap::fromImage(img));
    ui->labelScreen->setScaledContents(true);

    qApp->processEvents(); 
   //imshow("help", frame);

    if (waitKey(30) >= 0)
        break;
}

}

The variable ligaCam takes care of changing the value when I click on another button (Close Camera) to exit the loop.

My question is if there is any way to display camera images in QLabel using another thread? Or if there was some way to display the images without overloading the window in question? Thanks in advance for your help.

    
asked by anonymous 03.08.2016 / 17:44

1 answer

1

The graphical interface seems to be locked because you are consuming the entire resource of your thread (the main one) by making a virtually "infinite" loop.

You can try to move the update code to another thread, but it is simpler to use a timer to make periodic captures of the Webcam image:

  • In the window class where you display the camera image (for example, it may be in another class depending on your organization), instantiate a QTimer . Set it to a desired refresh interval (for example, every 100 milliseconds), and start. Do not forget to connect to the slot timeout() .

  • In the call of the method connected to slot timeout() (which will run every configured interval period), read the Webcam image and update QLabel in the same way you are doing. >

  • Code sample:

    [...]
    
    <Classe>::<Classe>() { // Construtor (por exemplo)
        QTimer *pTimer = new QTimer(this);
        QObject::connect(pTimer, SIGNAL(timeout()), this, SLOT(onTimeout()));
        pTimer->start(100);
    }
    
    [...]
    
    <Classe>::onTimeout() {
        Mat frame;
        this->cap.read(frame);
    
        img = MatToQImage(frame); // converte tipo Mat para QImage //
        ui->labelScreen->setPixmap(QPixmap::fromImage(img));
        ui->labelScreen->setScaledContents(true);
    }
    

    A more complete example using this approach can be found in this my test project .

        
    03.08.2016 / 18:25