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. Signal/Slot Multithreaded With GUI Displaying OpenCV Mat
Forum Updated to NodeBB v4.3 + New Features

Signal/Slot Multithreaded With GUI Displaying OpenCV Mat

Scheduled Pinned Locked Moved Solved General and Desktop
17 Posts 6 Posters 5.6k Views 2 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.
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by
    #7

    You can try onImageChanged(0, tFrame.clone(), false);

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    1 Reply Last reply
    1
    • P Offline
      P Offline
      pistorinoj
      wrote on last edited by
      #8

      Thanks.

      I tried something similar but no luck. Instead of passing an OpenCV Mat through the signal, I processed the Mat into a QImage and passed that as the parameter of the signal. I assume that that would make a local copy of the QImage on the GUI thread. But, again, the app crashes unless you delay the worker thread.

      J.HilkJ 1 Reply Last reply
      0
      • P pistorinoj

        Thanks.

        I tried something similar but no luck. Instead of passing an OpenCV Mat through the signal, I processed the Mat into a QImage and passed that as the parameter of the signal. I assume that that would make a local copy of the QImage on the GUI thread. But, again, the app crashes unless you delay the worker thread.

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #9

        @pistorinoj do you, by any Chance, pass your connect Statement, Qt::DirectConnection as 5th paarmeter?


        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.

        1 Reply Last reply
        0
        • P Offline
          P Offline
          pistorinoj
          wrote on last edited by
          #10

          No. The Connect statement uses QueuedConnection.

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

            Depending on how you build your QImage it will have the same issue of needing the underlying data's existence to be guaranteed.

            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
            • P Offline
              P Offline
              pistorinoj
              wrote on last edited by
              #12

              I built it using the same code above. All I did was move everything before the pixmap call onto the worker thread and pass the img.

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

                Sorry, I understood that you changed your code to emit a QImage rather than a cv::Mat.

                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
                • P Offline
                  P Offline
                  pistorinoj
                  wrote on last edited by
                  #14

                  Right. That is what I did.
                  My signal code now looks like what I say below. But I have to put in the msleep statements in the app crashes.

                  bool Channel::ImageDisp(int tChannelNumber, Mat tmat, bool MainWinCond)
                  {
                     if (tmat.type() == CV_8UC1)
                     {
                  	// Set the color table (used to translate colour indexes to qRgb values)
                          QVector<QRgb> colorTable;
                  	for (int i = 0; i<256; i++)
                  		colorTable.push_back(qRgb(i, i, i));
                  	// Copy input Mat
                  	const uchar *qImageBuffer = (const uchar*)tmat.data;
                  	// Create QImage with same dimensions as input Mat
                  	QImage img(qImageBuffer, tmat.cols, tmat.rows, tmat.step, QImage::Format_Indexed8);
                  	img.setColorTable(colorTable);
                  	emit ImageChanged(tChannelNumber, img , false, MainWinCond);
                  	QThread::msleep(15);
                      }
                      else if (tmat.type() == CV_8UC3)
                      {
                  	// 8-bits unsigned, NO. OF CHANNELS=3
                  	// Copy input Mat
                  	const uchar *qImageBuffer = (const uchar*)tmat.data;
                  	// Create QImage with same dimensions as input Mat
                  	QImage img(qImageBuffer, tmat.cols, tmat.rows, tmat.step, QImage::Format_RGB888);
                  	emit ImageChanged(tChannelNumber, img , true, MainWinCond);
                  	QThread::msleep(15);
                      }
                      else
                  	return (false);
                  
                      return(true);
                  }
                  
                  jsulmJ 1 Reply Last reply
                  0
                  • P pistorinoj

                    Right. That is what I did.
                    My signal code now looks like what I say below. But I have to put in the msleep statements in the app crashes.

                    bool Channel::ImageDisp(int tChannelNumber, Mat tmat, bool MainWinCond)
                    {
                       if (tmat.type() == CV_8UC1)
                       {
                    	// Set the color table (used to translate colour indexes to qRgb values)
                            QVector<QRgb> colorTable;
                    	for (int i = 0; i<256; i++)
                    		colorTable.push_back(qRgb(i, i, i));
                    	// Copy input Mat
                    	const uchar *qImageBuffer = (const uchar*)tmat.data;
                    	// Create QImage with same dimensions as input Mat
                    	QImage img(qImageBuffer, tmat.cols, tmat.rows, tmat.step, QImage::Format_Indexed8);
                    	img.setColorTable(colorTable);
                    	emit ImageChanged(tChannelNumber, img , false, MainWinCond);
                    	QThread::msleep(15);
                        }
                        else if (tmat.type() == CV_8UC3)
                        {
                    	// 8-bits unsigned, NO. OF CHANNELS=3
                    	// Copy input Mat
                    	const uchar *qImageBuffer = (const uchar*)tmat.data;
                    	// Create QImage with same dimensions as input Mat
                    	QImage img(qImageBuffer, tmat.cols, tmat.rows, tmat.step, QImage::Format_RGB888);
                    	emit ImageChanged(tChannelNumber, img , true, MainWinCond);
                    	QThread::msleep(15);
                        }
                        else
                    	return (false);
                    
                        return(true);
                    }
                    
                    jsulmJ Online
                    jsulmJ Online
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #15

                    @pistorinoj Please read http://doc.qt.io/qt-5/qimage.html#QImage-3
                    "The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer."
                    Your buffer is tmat.data. tmat is a local variable and is destroyed when ImageDisp finishes. That's why QThread::msleep(15) helps. But this isn't a solution but a dirty work around.
                    You need to make sure the buffer is alive as long as you use the QImage. Maybe changing "Mat tmat" to "Mat &tmat" will already be anough.

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

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

                      Then it's exactly the problem I described, you have to trigger a copy of your QImage so it will deep copy the data from your underlying buffer.

                      Or create a QImage of the right size and format and then do a memcpy of your buffer into the QImage internal buffer. Whatever you prefer.

                      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
                      3
                      • P Offline
                        P Offline
                        pistorinoj
                        wrote on last edited by
                        #17

                        Thanks all.

                        I did not realize that even QImage was making a shallow copy.
                        I changed this so that the first thing the slot does is make a deep copy of the QImage and that seems to have addressed the issue.

                        Sorry for being so slow.

                        Thanks again.

                        1 Reply Last reply
                        1

                        • Login

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