Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QT application with OpenCV and multithreading dies, no errors given
Forum Update on Monday, May 27th 2025

QT application with OpenCV and multithreading dies, no errors given

Scheduled Pinned Locked Moved Unsolved General and Desktop
1 Posts 1 Posters 628 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bsmith
    wrote on 4 Sept 2019, 20:00 last edited by bsmith 9 Apr 2019, 20:05
    #1

    Hello! I am working on building a simple QT interface that I later plan to add extra functionality, but for now I am simply trying to display 8 QImages in QLabels from cv::Mat images. The Mats are inside of a TBB concurrent_queue and are pushed from a cv::VideoCapture tbb::thread. This alone works outside of QT perfectly, but trying to integrate this with QT has been a struggle.

    Here are my header files:

    //camerastreamer.hpp
    #pragma once
    #include <iostream>
    #include <string>
    #include <thread>
    #include <vector>
    #include <concurrent_queue.h>
    #include "opencv2/videoio.hpp"
    
    
    using namespace std;
    using namespace cv;
    using namespace tbb;
    
    
    class CameraStreamer{
        public:
        //this holds camera stream urls
        vector<string> camera_source;
        //this holds OpenCV VideoCapture pointers
        vector<VideoCapture*> camera_capture;
        //this holds queue(s) which hold images from each camera
        vector<concurrent_queue<Mat>*> frame_queue;
        //this holds thread(s) which run the camera capture process
        vector<thread*> camera_thread;
        //Constructor for IP Camera capture
        CameraStreamer(vector<string> source);
        //Destructor for releasing resource(s)
        ~CameraStreamer();
    
        private:
        int camera_count;
        //initialize and start the camera capturing process(es)
        void startMultiCapture();
        //release all camera capture resource(s)
        void stopMultiCapture();
        //main camera capturing process which will be done by the thread(s)
        void captureFrame(int index);
    };
    
    //mainwindow.h
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QThread>
    #include <QVector>
    #include <QtWidgets/QSlider>
    #include <QtWidgets/QToolButton>
    #include <QtWidgets/QToolButton>
    #include <QtWidgets/QCheckBox>
    #include <QtWidgets/QTextBrowser>
    
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
        QThread *thread;
        
        void setup();
       
    signals:
        void sendSetup();
        void sendToggleStream();
    
    private slots:
        void receiveFrame1(QImage img);
        void receiveFrame2(QImage img);
        void receiveFrame3(QImage img);
        void receiveFrame4(QImage img);
        void receiveFrame5(QImage img);
        void receiveFrame6(QImage img);
        void receiveFrame7(QImage img);
        void receiveFrame8(QImage img);
        void receiveToggleStream();
    };
    
    #endif // MAINWINDOW_H
    
    //ocvworker.h
    #ifndef OCVWORKER_H
    #define OCVWORKER_H
    
    #include <QObject>
    #include <QImage>
    #include <QtWidgets/QLabel>
    #include <QVector>
    #include <QtWidgets/QLabel>
    
    #include "opencv2/highgui.hpp"
    #include "opencv2/opencv.hpp"
    
    #include "camerastreamer.hpp"
    
    const string ip = "192.168.122.1";
    
    class OCVworker : public QObject
    {
        Q_OBJECT
    
    private:
        vector<string> capture_source = {
                "http://"+ip+":8081/?action=stream",
                "http://"+ip+":8082/?action=stream",
                "http://"+ip+":8083/?action=stream",
                "http://"+ip+":8084/?action=stream",
                "http://"+ip+":8080/?action=stream",
                "http://"+ip+":8085/?action=stream",
                "http://"+ip+":8086/?action=stream"
            };
        CameraStreamer cam(capture_source);
        Mat frame,R,G,B,dst;
        vector<Mat> frames, col;
        Mat chans[3];
        Mat merged, edges1,refedges, throwaway1,throwaway2;
        double lutvals[7][2][3] = {{{63.,0.,125.},{252.,251.,253.}},{{8.,48.,107.},{247.,251.,255.}},{{0.,68.,27.},{247.,252.,245.}},{{103.,0.,12.},{152.,245.,228.}},{{102.,37.,102.},{255.,255.,255.}},{{-190.,-253.,255.},{922.,245.,63.5}},{{-191.,-94.,10.},{1016.,670.,665.}}};
        bool toggleStream, alignEnable;
    
    public:
        explicit OCVworker(QObject *parent = nullptr);
        ~OCVworker();
    
    signals:
        void sendFrame1(QImage img);
        void sendFrame2(QImage img);
        void sendFrame3(QImage img);
        void sendFrame4(QImage img);
        void sendFrame5(QImage img);
        void sendFrame6(QImage img);
        void sendFrame7(QImage img);
        void sendFrame8(QImage img);
    
    public slots:
        void receiveGrabFrame();
        void receiveToggleStream();
        void receiveEnableAlign();
    };
    
    #endif // OCVWORKER_H
    

    and my cpp files:

    //camerastreamer.cpp
    #include "camerastreamer.hpp"
    
    CameraStreamer::CameraStreamer(vector<string> stream_source)
    {
        camera_source = stream_source;
        camera_count = camera_source.size();
        startMultiCapture();
    }
    
    CameraStreamer::~CameraStreamer()
    {
        //stopMultiCapture();
    }
    
    void CameraStreamer::captureFrame(int index)
    {
        VideoCapture *capture = camera_capture[index];
        while (true)
        {
            Mat frame,frames[3];
            //Grab frame from camera capture
            (*capture) >> frame;
            cv::split(frame,frames);
            frame=frames[0];
            //Put frame to the queue
            frame_queue[index]->push(frame);
            //relase frame resource
            frame.release();
        }
    }
    
    void CameraStreamer::startMultiCapture()
    {
        VideoCapture *capture;
        thread *t;
        concurrent_queue<Mat> *q;
        for (int i = 0; i < camera_count; i++)
        {   //Make VideoCapture instance
            string url = camera_source[i];
            capture = new VideoCapture(url);
            cout << "Camera Setup: " << url << endl;
            //Put VideoCapture to the vector
            camera_capture.push_back(capture);
            //Make thread instance
            t = new thread(&CameraStreamer::captureFrame, this, i);
            //Put thread to the vector
            camera_thread.push_back(t);
            //Make a queue instance
            q = new concurrent_queue<Mat>;
            //Put queue to the vector
            frame_queue.push_back(q);
        }
    }
    
    void CameraStreamer::stopMultiCapture()
    {
        VideoCapture *cap;
        for (int i = 0; i < camera_count; i++) {
            cap = camera_capture[i];
            if (cap->isOpened())
            {   //Relase VideoCapture resource
                cap->release();
                cout << "Capture " << i << " released" << endl;
            }
        }
    }
    
    //mainwindow.cpp
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "ocvworker.h"
    #include <QTimer>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->frame1->setScaledContents(true);
        ui->frame2->setScaledContents(true);
        ui->frame3->setScaledContents(true);
        ui->frame4->setScaledContents(true);
        ui->frame5->setScaledContents(true);
        ui->frame6->setScaledContents(true);
        ui->frame7->setScaledContents(true);
        ui->frame8->setScaledContents(true);
        setup();
    }
    
    MainWindow::~MainWindow()
    {
        thread->quit();
        while(!thread->isFinished());
        delete thread;
        delete ui;
    }
    
    void MainWindow::setup()
    {
        thread = new QThread();
        OCVworker *worker = new OCVworker();
    
        QTimer *workerTrigger = new QTimer();
        workerTrigger->setInterval(1);
    
        connect(workerTrigger, SIGNAL(timeout()), worker, SLOT(receiveGrabFrame()));
        connect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(thread, SIGNAL(finished()), workerTrigger, SLOT(deleteLater()));
        connect(this, SIGNAL(sendToggleStream()), worker, SLOT(receiveToggleStream()));
        connect(ui->playButton, SIGNAL(clicked(bool)), this, SLOT(receiveToggleStream()));
        connect(ui->checkBox, SIGNAL(toggled(bool)), worker, SLOT(receiveEnableAlign()));
        connect(worker, SIGNAL(sendFrame1(QImage)), this, SLOT(receiveFrame1(QImage)));
        connect(worker, SIGNAL(sendFrame2(QImage)), this, SLOT(receiveFrame2(QImage)));
        connect(worker, SIGNAL(sendFrame3(QImage)), this, SLOT(receiveFrame3(QImage)));
        connect(worker, SIGNAL(sendFrame4(QImage)), this, SLOT(receiveFrame4(QImage)));
        connect(worker, SIGNAL(sendFrame5(QImage)), this, SLOT(receiveFrame5(QImage)));
        connect(worker, SIGNAL(sendFrame6(QImage)), this, SLOT(receiveFrame6(QImage)));
        connect(worker, SIGNAL(sendFrame7(QImage)), this, SLOT(receiveFrame7(QImage)));
        connect(worker, SIGNAL(sendFrame8(QImage)), this, SLOT(receiveFrame8(QImage)));
        connect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(thread, SIGNAL(finished()), workerTrigger, SLOT(deleteLater()));
        cout << "Got Here" <<endl;
    
    
        workerTrigger->start();
        worker->moveToThread(thread);
        workerTrigger->moveToThread(thread);
    
        thread->start();
    }
    
    void MainWindow::receiveFrame1(QImage img)
    {
        ui->frame1->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::receiveFrame2(QImage img)
    {
        ui->frame2->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::receiveFrame3(QImage img)
    {
        ui->frame3->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::receiveFrame4(QImage img)
    {
        ui->frame4->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::receiveFrame5(QImage img)
    {
        ui->frame5->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::receiveFrame6(QImage img)
    {
        ui->frame6->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::receiveFrame7(QImage img)
    {
        ui->frame7->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::receiveFrame8(QImage img)
    {
        ui->frame8->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::receiveToggleStream()
    {
        if(!ui->playButton->text().compare(">")) ui->playButton->setText("||");
        else ui->playButton->setText(">");
        emit sendToggleStream();
    }
    
    //ocvworker.cpp
    #include "ocvworker.h"
    
    OCVworker::OCVworker(QObject *parent) :
        QObject(parent),
        toggleStream(false),
        alignEnable(false),
    {
    
    }
    
    OCVworker::~OCVworker()
    {
        /*cam->~CameraStreamer();
        delete cam;*/
    }
    
    void OCVworker::receiveGrabFrame()
    {
        for (int i= 0; i < int(capture_source.size()); i++)
        {
            if (cam.frame_queue[i]->try_pop(frame))
            {
                frame.convertTo(R, CV_8UC1, lutvals[i][1][0]/255., lutvals[i][0][0]);
                frame.convertTo(G, CV_8UC1, lutvals[i][1][1]/255., lutvals[i][0][1]);
                frame.convertTo(B, CV_8UC1, lutvals[i][1][2]/255., lutvals[i][0][2]);
                col.push_back(B);
                col.push_back(G);
                col.push_back(R);
                merge(col,dst);
                QImage qimg((const unsigned char *) dst.data, dst.cols, dst.rows, QImage::Format_Indexed8);
                switch (i) {
                case 0: {
                    emit sendFrame1(qimg);
                    break;}
                case 1: {
                    emit sendFrame2(qimg);
                    break;}
                case 2: {
                    emit sendFrame3(qimg);
                    break;}
                case 3: {
                    emit sendFrame4(qimg);
                    break;}
                case 4: {
                    applyColorMap(frame,dst,COLORMAP_PINK);
                    QImage qimg2((const unsigned char *) frame.data, frame.cols, frame.rows, QImage::Format_Indexed8);
                    emit sendFrame5(qimg2);
                    break;}
                case 5: {
                    applyColorMap(frame,dst,COLORMAP_MAGMA);
                    QImage qimg3((const unsigned char *) frame.data, frame.cols, frame.rows, QImage::Format_Indexed8);
                    emit sendFrame6(qimg3);
                    break;}
                case 6: {
                    applyColorMap(frame,dst,COLORMAP_INFERNO);
                    QImage qimg4((const unsigned char *) frame.data, frame.cols, frame.rows, QImage::Format_Indexed8);
                    emit sendFrame7(qimg4);
                    break;}
                default:
                    break;
                }
                frame.copyTo(frames[i]);
                if(frame.empty()){
                    cout << "Frame "+to_string(i)+" Emtpy";
                    return;
                }
                cout << "Got to Frame"+to_string(i);
            }
        }
        for (int i=3; i<6; i++)
        {
            frames[i].copyTo(chans[i-3]);blur(frames[i],throwaway1,Size(3,3));
            Canny(throwaway1,edges1,50,200,3);
            blur(frames[3],throwaway1,Size(3,3));
            Canny(throwaway1,refedges,50,200,3);
            edges1.convertTo(throwaway1,CV_32FC1);
            refedges.convertTo(throwaway2,CV_32FC1);
            Point2d offset = phaseCorrelate(throwaway1,throwaway2);
            Mat warpmat = (Mat_<double>(2,3) << 1, 0, offset.x,0,1,offset.y);
            warpAffine(chans[i-3],chans[i-3],warpmat,frames[3].size());
        }
        merge(chans,3,merged);
        QImage qmerge((const unsigned char *) merged.data, merged.cols, merged.rows, QImage::Format_Indexed8);
        emit sendFrame8(qmerge);
    }
    
    void OCVworker::receiveToggleStream()
    {
        toggleStream = !toggleStream;
    }
    void OCVworker::receiveEnableAlign()
    {
        alignEnable = !alignEnable;
    }
    
    //main.cpp
    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    
    //.pro file
    #-------------------------------------------------
    #
    # Project created by QtCreator 2019-07-15T13:48:32
    #
    #-------------------------------------------------
    
    QT       += core gui
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = TTCGUI
    TEMPLATE = app
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which has been marked as deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    QMAKE_CXX = g++
    QMAKE_LINK = g++
    
    CONFIG += c++11
    
    SOURCES += \
            camerastreamer.cpp \
            main.cpp \
            mainwindow.cpp \
            ocvworker.cpp
    
    HEADERS += \
            camerastreamer.hpp \
            mainwindow.h \
            ocvworker.h
    
    FORMS += \
            mainwindow.ui
    
    INCLUDEPATH += /usr/local/Cellar/opencv/4.1.0_2/include/opencv4/opencv \
    /usr/local/Cellar/opencv/4.1.0_2/include/opencv4 \
    /usr/local/Cellar/tbb/2019_U6/include/tbb
    
    LIBS += `/opt/local/bin/pkg-config opencv4 --cflags --libs`
    LIBS += -I/usr/local/Cellar/tbb/2019_U6/include/tbb
    LIBS += -L/usr/local/Cellar/tbb/2019_U6/lib
    LIBS+= -ltbb
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    

    My compile commands are:

    /Applications/Xcode.app/Contents/Developer/usr/bin/g++ -std=c++11 camerastreamer.cpp `pkg-config --cflags --libs` -I/usr/local/Cellar/tbb/2019_U6/include/tbb -ltbb -c
    /Applications/Xcode.app/Contents/Developer/usr/bin/g++ -std=c++11 ocvworker.cpp `pkg-config opencv4 --cflags --libs` -I/usr/local/Cellar/tbb/2019_U6/include/tbb -ltbb -I~/Qt/5.13.0/clang_64/lib/QtWidgets.framework/Versions/5/Headers -I~/Qt/5.13.0/clang_64/lib/QtCore.framework/Versions/5/Headers -I~/Qt/5.13.0/Src/qtbase/include -I~/Qt/5.13.0/clang_64/lib/QtGui.framework/Versions/5/Headers -c
    qmake proj.pro -spec macx-g++ CONFIG+=debug CONFIG+=x86_64 CONFIG+=qml_debug
    make -j36 in build-proj-Desktop_Qt_5_13_0_clang_64bit-Debug
    

    The application build dies at runtime with no output. Debugging stops on line 36 of mainwindow.cpp, where a new OCVworker pointer is constructed (OCVworker *worker = new OCVWorker()).

    Any wisdom on what might be causing this application to crash would be very appreciated, as I've been trying to figure this issue out for a couple of weeks now. Thank you!

    1 Reply Last reply
    0

    1/1

    4 Sept 2019, 20:00

    • Login

    • Login or register to search.
    1 out of 1
    • First post
      1/1
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved