QT - View Webcam on a Qlabel using another Thread?

Asked

Viewed 82 times

1

Hello, I’m doing a C++ project using QT GUI. 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 includes in the window are slow, overloaded apparently. Below is the capture code of the device images.

  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 link variable is in charge of changing the value when I click another button (Close Camera) to exit the loop.

My question is, is there any way to display camera images on Qlabel using another thread? Or if there is any way to display the images without overloading the window in question? Thanks for your help.

1 answer

1


The graphical interface seems locked because you are consuming all the resources of your thread (the main one) when making a loop virtually "infinite".

You can try moving the update code to another thread, but it’s simpler to use a timer to make periodic captures of the webcam image:

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

  2. In the call of the method connected to the slot timeout() (which will run at each set interval period), read the webcam image and update the QLabel the same way you’re doing.

Code example:

[...]

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

  • Thanks for the reply, I followed your advice above but now I came across the following error message: 'SIGNAL was not declared in this Scope'. And the second message is 'macro Signal passed 3 Arguments but takes just 1' . I even installed the Qtimer libraries, although I didn’t need to, but the error persists. I would know what this problem could be?

  • Probably something wrong with your method statement onTimeout (he was declared a slot, in a class inherited from QObject and that uses the macro Q_OBJECT - as indicated Qt documentation for the inter-object communication mechanism?). Anyway, since it’s another problem you should open another question. :)

  • Ah, and if that answer helped you, please consider marking it as accepted.

  • 1

    I got it! actually it was all right with the macro and the class, the error was in the connect() statement, I think q lost some parentheses of the function, and my compiler did not accuse rs, Well, Thanks for the answer, solved my problem friend, Hug!

  • Reply accepted, thank you again.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.