PDA

View Full Version : Multithreaded opencv video processing Qt/C++



wassim24
26th December 2014, 14:36
Hope your are doing good ! I'm strugguling from yesterday on how to implement a multithreaded video processing program with opencv.

I understand how threads actually work, how to use a simple mutex etc...But when it comes to implementation, i'm completely lost.

My goal is to create an interface with Qt and display two labels, one showing original video feed and the other showing the processed one, each one handeled by a thread.

For now i'm just trying to get on thread to display images, but i really struggle with it.

Here is what i've done so far :

CaptureThread a class inheriting from QThread : It is supposed to handle the start of cam capture etc...



#include <QThread>

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/videoio.hpp"

#include <QTimer>

class CaptureThread : public QThread
{
Q_OBJECT

public:
explicit CaptureThread(QObject *parent);


protected:
void run();

signals:
void frameCaptured(cv::Mat);

public slots:
void captureFrame();

private:
QTimer* tmrTimer;
cv::VideoCapture capWebam;
cv::Mat capturedFrame;

};

#endif // CAPTURETHREAD_H



And this is its implementation :



#include "capturethread.h"
#include <QDebug>

CaptureThread::CaptureThread(QObject* parent):QThread(parent)
{
capWebam.open(0);
}

void CaptureThread::run()
{
tmrTimer = new QTimer(this);
QObject::connect(tmrTimer, SIGNAL(timeout()), this, SLOT(captureFrame()));

tmrTimer->start(10);
exec();
}

void CaptureThread::captureFrame()
{
if(capWebam.isOpened()){
capWebam.read(capturedFrame);

emit frameCaptured(capturedFrame);
}

}


MainWindow use to display the camera feed etc...



#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/videoio.hpp"
#include <capturethread.h>

#include <QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

public slots:
void pricessFrameAndUpdateGUI(cv::Mat matOriginal);

private slots:
void on_button_clicked();

private:
Ui::MainWindow *ui;
QImage toGrayscale(QImage image);

cv::VideoCapture capWebcam;
cv::Mat matOriginal;
cv::Mat matProcessed;

QImage qimgOriginal;
QImage qimgProcessed;

QTimer* tmrTimer;

CaptureThread* cpThread;
};

#endif // MAINWINDOW_H


its implementaion



#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCore>
#include <cv.h>
#include <QColor>
#include <opencv/highgui.h>

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
ui->setupUi(this);

cpThread = new CaptureThread(this);
QObject::connect(cpThread, SIGNAL(frameCaptured(cv::Mat)),this, SLOT(pricessFrameAndUpdateGUI(cv::Mat)));
cpThread->start();

}

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

void MainWindow::pricessFrameAndUpdateGUI(cv::Mat matOriginal)
{


cv::Canny(matOriginal, matProcessed, 100, 300);

cv::cvtColor(matOriginal, matOriginal, CV_BGR2RGB);
QImage qimgOriginal((uchar*)matOriginal.data, matOriginal.cols, matOriginal.rows, matOriginal.step, QImage::Format_RGB888);
QImage qimgProcessed((uchar*)matProcessed.data, matProcessed.cols, matProcessed.rows, matProcessed.step,QImage::Format_Indexed8);

ui->original->setPixmap(QPixmap::fromImage(qimgOriginal));
ui->modified->setPixmap(QPixmap::fromImage(qimgProcessed));

}


After compiling and executing the program i get this error :




Starting /media/wassim/BLAZER/Workspace/CPP/build-firstCV-Desktop_Qt_5_3_GCC_64bit-Debug/firstCV...

VIDEOIO ERROR: V4L/V4L2: VIDIOC_S_CROP

QObject: Cannot create children for a parent that is in a different thread.

(Parent is CaptureThread(0xc02be0), parent's thread is QThread(0xae82c0), current thread is CaptureThread(0xc02be0)

The program has unexpectedly finished.

/media/wassim/BLAZER/Workspace/CPP/build-firstCV-Desktop_Qt_5_3_GCC_64bit-Debug/firstCV crashed


Thanks you guys for your help !

ChrisW67
27th December 2014, 01:56
The CaptureThread object is created in the main program thread. The run() function is executed in a different thread and tries to create a new QTimer parented to the CaptureThread causing the error you see. You might want to use the worker object arrangement you see first in the QThread docs (http://doc.qt.io/qt-5/qthread.html#details). It is more fully explained here (mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/).

wassim24
27th December 2014, 08:43
Thank for your answer !
I will try that and keep you in touch !

wassim24
28th December 2014, 08:31
Thank your it worked very well !

slman alii
13th January 2017, 14:21
where did you initialize your timer please