0

I am trying to display a video in QLabet in QT Creator. I am reading video using openCV. Here is my code:

mainwindow.cpp

#include "includes.h"
#include "vidreadthread.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    VidReadThread *thread1 = new VidReadThread("Video read thread");
    thread1->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

vidreadthread.cpp

#include "vidreadthread.h"
#include "includes.h"

using namespace cv;
extern MainWindow *mainPtr;

VidReadThread::VidReadThread(QString s) : name(s)
{
}

void VidReadThread::run()
{
    QThread::msleep(100);
    VideoCapture cap;
    cap.open("helicopter_with_stickers.mp4");
    while(1)
    {
        Mat image1;
       // Capture frame-by-frame
        cap >> image1;

       // If the frame is empty, break immediately
       if (image1.empty())
         break;

       QImage image2 = QImage((uchar*) image1.data, image1.cols, image1.rows, image1.step, QImage::Format_RGB888);
       mainPtr->ui->label1->setPixmap(QPixmap::fromImage(image2));
    }
}

I am able to display the video but I can't set frame rate. Whole 60sec of video gets over in 4-5 frames. With only OpenCV I have command on frame rate with cvWaitkey(), but here msleep() doesn't seem to be working for a similar application. Please suggest a way to do so without frame skipping. I made a vidreadthread so that GUI doesn't get hanged while video is being read.

If there is any other way by which I can display OpenCV window inside my QT UI, then please recommend that as well.

A.k.
  • 192
  • 1
  • 22
  • If you choose Qml(Qt Quick) , I can suggest 2 different ways and also examples with directly related with opencv. I know how to do with Qt Quick App. but I dont know with Qt Widget app. – Yunus Temurlenk Jan 15 '20 at 11:23
  • 1
    Your `msleep()` is outside the loop, so it will not affect the frame rate for sure. Moreover, you are accessing the `QLabel` pointer from another thread without ensuring that no one else is accessing it (through critical section for example) so you are subject to race conditions here too. – Fareanor Jan 15 '20 at 11:31
  • @Fareanor Just cos of being curious. I am also using a loop in a different thread to take frames from the camera. I am reaching the frames in the thread loop using a global static qimage. Because you said "no one else is accesing.." or I misunderstood? I think he can also access it – Yunus Temurlenk Jan 15 '20 at 11:42
  • 1
    @YunusTemurlenk In fact, if several threads/processes access to the same location in memory at the same time, the behaviour is undefined (anything can happen). This is why you need something like mutexes, semaphores, ... in order to atomically lock the access to the shared variable while a worker is reading/writing it. You can start by taking a look at [this](https://stackoverflow.com/questions/34510/what-is-a-race-condition) – Fareanor Jan 15 '20 at 11:51
  • @Fareanor I ll check it thanks. – Yunus Temurlenk Jan 15 '20 at 11:59
  • 1
    my experiences shows that updating widgets from another thread is not good solution! SO make a signal in thread and SLOT in main thread, whenever Mat is ready pass it to the main thread – Saeed Masoomi Jan 15 '20 at 13:59
  • @Fareanor Adding while inside the loop did the trick. Also, how are you suggesting to ensure that no one is accessing QLabel pointer when it is already being accessed? – A.k. Jan 16 '20 at 04:22

1 Answers1

0

try moveto thread may works better

.cpp

for (int i = 0; i<Camera::getCameraCount();)
        ui->comboBox->addItem(QString::number(i++)); //name camera
    camera = new Camera();
    camera->moveToThread(&thread); 

connect(this, SIGNAL(cameraOperate(int)), camera, SLOT(Operate(int))); 
connect(camera, SIGNAL(updateImage(QImage)), this, SLOT(updateImage(QImage))); 


void app0::updateImage(QImage image)
{
    ui->videoviewer->setPixmap(QPixmap::fromImage(image));
}

camera thread:

void Camera::Operate(int _index)
{
    if (open(_index)) { qDebug() << "Camera open success!";}
    else { qDebug() << "Camera open failed!"; return; }
    if (capture.get(28) == -1) { cout << "get 28 -1" << "\n";emit }
    while (1)
    {
        qApp->processEvents();
        Mat matin = read(); //read mat
        matnow = matin;
        QImage image = Mat2QImage(matin);
        emit updateImage(image);
    }
}

link:https://blog.csdn.net/Sun_tian/article/details/104236327