Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. QtonPi
  4. Custom Qlabel show Videocamera on different thread
Forum Updated to NodeBB v4.3 + New Features

Custom Qlabel show Videocamera on different thread

Scheduled Pinned Locked Moved Solved QtonPi
9 Posts 3 Posters 3.8k Views 1 Watching
  • 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.
  • D Offline
    D Offline
    davidino
    wrote on last edited by
    #1

    Goodmorning,
    I'm using a raspberry pi3 board with a custom image built with Yocto, where I've included opencv libraries. Qt version is 5.7.1.
    I succeded to show the camera video output on a QLabel, but now I wanted to make the opencv operations on a different thread, to not overload the GUI thread.
    Hence, I've created a custom QLabel widget called videocamera, where the opencv task is done by a Worker class.

    Unfortunately, when I get the error Segmentation fault. Have you got any ideas?
    Thank you.

    videocamera.h

    #ifndef VIDEOCAMERA_H
    #define VIDEOCAMERA_H
    
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/videoio.hpp>
    #include <QWidget>
    #include <QTimer>
    #include <QLabel>
    #include <QThread>
    #include <QSignalMapper>
    
    using namespace cv;
    
    class Worker : public QObject
    {
        Q_OBJECT
    
        QImage m_image;
        VideoCapture cap;
    
        public slots:
        void doWork()
        {
            if(cap.open(0))
            {
                Mat image;
                cap >> image;
                //conversion from Mat to QImage
                Mat dest;
                cvtColor(image, dest,CV_BGR2RGB);
                m_image = QImage((uchar*) dest.data, dest.cols, dest.rows, dest.step, QImage::Format_RGB888);
                emit resultReady(m_image);
            }
        }
    
        void deleteLater()
        {
    
        }
    
    signals:
        void resultReady(const QImage &result);
    };
    
    class VideoCamera : public QLabel
    {
        Q_OBJECT
    public:
        explicit VideoCamera(QWidget *parent = nullptr);
        ~VideoCamera();
    
    public slots:
        void updatePicture(const QImage&);
    
    private:
        Worker* worker;
        QThread workerThread;
        QTimer* timer;
    };
    
    #endif // VIDEOCAMERA_H
    
    
    

    videocamera.cpp

    
    #include "videocamera.h"
    
    using namespace cv;
    
    VideoCamera::VideoCamera(QWidget *parent):
        QLabel(parent)
    {
        worker=new Worker();
        worker->moveToThread(&workerThread);
        timer = new QTimer(this);
    
        connect(timer, SIGNAL(timeout()), worker, SLOT(doWork()));
        connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(worker, SIGNAL(resultReady(const QImage&)), this, SLOT(updatePicture(const QImage&)));
    
        workerThread.start();
        timer->start(10);
    }
    
    void VideoCamera::updatePicture(const QImage &image)
    {
        //show Qimage using QLabel
        this->setPixmap(QPixmap::fromImage(image));
    }
    
    VideoCamera::~VideoCamera()
    {
        workerThread.quit();
        workerThread.wait();
    }
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Your original data has likely become invalid by the time you try to create the QPixmap object. You should make a copy before sending it.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      J.HilkJ 1 Reply Last reply
      1
      • D Offline
        D Offline
        davidino
        wrote on last edited by
        #3

        Hello SGaist,
        thank you for your answer!! You are right. I solved passing directly the Pixmap, instead of QImage. Is it what you meant?

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by SGaist
          #4

          No it's not, can you show the new version of your code ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • SGaistS SGaist

            Hi,

            Your original data has likely become invalid by the time you try to create the QPixmap object. You should make a copy before sending it.

            J.HilkJ Online
            J.HilkJ Online
            J.Hilk
            Moderators
            wrote on last edited by J.Hilk
            #5

            Hi, @SGaist ,

            arn't the const ,& references of void resultReady(const QImage &result); ignored by a Qt::QueuedConnection and a copy is send anyway? The default connection type between threads is QueuedConnection after all.

            @davidino I had a case where QImage was not properly registerstered in the metatyp system, that caused problems for qued connections. Do you get any warnings in your consol output during run time?

            Or better yet, use the new Qt5 Syntax and see if it compiles:

            //5th argument Qt::QueuedConnection just to be sure
            connect(worker, Worker::resultReady, this, VideoCamera::updatePicture, Qt::QueuedConnection);
            

            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            D 1 Reply Last reply
            1
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Here it's the QImage construction that is important. It uses the third constructor which doesn't copy the data hence you have to handle the lifetime of the underlying data. In this case there's a need to force a deep copy.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • D Offline
                D Offline
                davidino
                wrote on last edited by
                #7

                Hello Gaist,
                thank you very much. Now I got it!
                Below the working Worker class.

                
                class Worker : public QObject
                {
                    Q_OBJECT
                
                    Mat dest;
                    QImage m_image;
                    VideoCapture cap;
                    QObject* parent;
                
                    public slots:
                    void doColor()
                    {
                        if(cap.isOpened())
                        {
                            Mat image;
                            cap >> image;
                            //conversion from Mat to QImage
                            cvtColor(image, dest,CV_BGR2RGB);
                            m_image = QImage((uchar*) dest.data, dest.cols, dest.rows, dest.step, QImage::Format_RGB888);
                            emit resultReady(m_image);
                        }
                        else
                            cap = VideoCapture(0);
                    }
                
                1 Reply Last reply
                0
                • J.HilkJ J.Hilk

                  Hi, @SGaist ,

                  arn't the const ,& references of void resultReady(const QImage &result); ignored by a Qt::QueuedConnection and a copy is send anyway? The default connection type between threads is QueuedConnection after all.

                  @davidino I had a case where QImage was not properly registerstered in the metatyp system, that caused problems for qued connections. Do you get any warnings in your consol output during run time?

                  Or better yet, use the new Qt5 Syntax and see if it compiles:

                  //5th argument Qt::QueuedConnection just to be sure
                  connect(worker, Worker::resultReady, this, VideoCamera::updatePicture, Qt::QueuedConnection);
                  
                  D Offline
                  D Offline
                  davidino
                  wrote on last edited by
                  #8

                  Hello @J-Hilk,
                  thank you for your email.
                  The only console outputs that I have are the following, but they don't bother the program.

                  evdevkeyboard: Could not read from input device (No such device)
                  evdevkeyboard: Failed to query led states

                  I'll pass to Qt5 connect Syntax for sure, thank you.

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    There's another solution worth investigating. Since your images are likely not going to change size, you could make m_image directly the right size and then wrap the data from it in the dest Mat (see this constructor). Doing so you you can remove the m_image = etc. line.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0

                    • Login

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