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. QPixmap::scaled: Pixmap is a null pixmap (displaying Pixmap on the label)
Forum Updated to NodeBB v4.3 + New Features

QPixmap::scaled: Pixmap is a null pixmap (displaying Pixmap on the label)

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 4 Posters 2.7k 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.
  • Y Offline
    Y Offline
    Yamado
    wrote on last edited by
    #1

    Hello.
    I've been trying to write a program that when you click on a button it captures the current frame from the webcam (something like this, but more GUI based: https://www.youtube.com/watch?v=oHFTM1XPicI), but lastly, I've come to some problems.
    Whenever I run my program, activate a webcam, and then try to capture frame I get the following errors in the Application Output:

    QPixmap::scaled: Pixmap is a null pixmap
    OpenCV: terminate handler is called! The last OpenCV error is:
    OpenCV(4.5.2) Error: Assertion failed (!_src.empty()) in cv::cvtColor, file C:\build\master_winpack-build-win64-vc15\opencv\modules\imgproc\src\color.cpp, line 182
    18:43:33: The program has unexpectedly finished.
    

    And to be clear, I do not get any errors in Qt.
    Rest of the code:
    myvideocapture.h

    
    #ifndef MYVIDEOCAPTURE_H
    #define MYVIDEOCAPTURE_H
    
    #include <QPixmap>
    #include <QImage>
    #include <QThread>
    #include <opencv2/opencv.hpp>
    
    #define ID_CAMERA 0
    
    class MyVideoCapture : public QThread
    {
        Q_OBJECT
    public:
        MyVideoCapture(QObject *parent = nullptr);
        QPixmap klatka();
        /*QPixmap zdjecie() const
        {
            return frame3;
        }*/
    
        QPixmap pixmap() const
        {
            return mPixmap;
        }
    signals:
        void newPixmapCaptured(); // imagen nueva ha sido capturada
        //void nowaklatka();
    protected:
        void run() override;
    private:
        QPixmap mPixmap; // imagen de Qt
        cv::Mat mFrame; // imagen de OpenCV
        cv::VideoCapture mVideoCap; // capturador de video
        cv::Mat frame2;
        QPixmap frame3;
        //QPixmap frame4;
    
    
        QImage cvMatToQImage(const cv::Mat &inMat);
        QPixmap cvMatToQPixmap(const cv::Mat &inMat);
    };
    
    #endif // MYVIDEOCAPTURE_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "myvideocapture.h"
    #include "myvideocapture.cpp"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        mOpenCV_videoCapture = new MyVideoCapture(this);
        /*connect(mOpenCV_videoCapture, &MyVideoCapture::nowaklatka, this, [&]()
        {
            ui->label_2->setPixmap(mOpenCV_videoCapture->zdjecie().scaled(500, 500));
        });*/
        connect(mOpenCV_videoCapture, &MyVideoCapture::newPixmapCaptured, this, [&]()
        {
            ui->label->setPixmap(mOpenCV_videoCapture->pixmap().scaled(500, 500));
        });
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
        mOpenCV_videoCapture->terminate();
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        mOpenCV_videoCapture->start(QThread::HighestPriority);
    }
    
    void MainWindow::on_pushButton_2_clicked()
    {
        MyVideoCapture f;
        QPixmap frame4 = f.klatka();
        ui->label_2->setPixmap(frame4.scaled(500, 500));
    }
    
    /*void MyVideoCapture::klatka()
    {
        frame2 = mFrame.clone();
        frame3 = cvMatToQPixmap(frame2);
    
    }*/
    

    myvideocapture.cpp

    #include "myvideocapture.h"
    #include "mainwindow.h"
    //#include "ui_mainwindow.h"
    #include <QDebug>
    
    MyVideoCapture::MyVideoCapture(QObject *parent)
        : QThread { parent }
        , mVideoCap { ID_CAMERA }
    {
    }
    
    
    void MyVideoCapture::run()
    {
        if (mVideoCap.isOpened())
        {
            while (true)
            {
                mVideoCap >> mFrame;
                applyColorMap(mFrame, mFrame, cv::COLORMAP_HOT);
                if (!mFrame.empty())
                {
                    //cv::rectangle(mFrame, cv::Point(10, 10), cv::Point(401, 401), cv::Scalar(0, 0, 255), 1);
    
                    mPixmap = cvMatToQPixmap(mFrame);
                    emit newPixmapCaptured();
                }
            }
        }
    }
    
    
    QPixmap MyVideoCapture::klatka()
    {
        //extern QPixmap frame3;
        //QPixmap frame4;
    
        frame2 = mFrame.clone();
        frame3 = cvMatToQPixmap(frame2);
        return frame3;
    }
    
    
    
    QImage MyVideoCapture::cvMatToQImage(const cv::Mat &inMat)
    {
        switch (inMat.type())
        {
            // 8-bit, 4 channel
            case CV_8UC4:
            {
                QImage image(inMat.data, inMat.cols, inMat.rows, static_cast<int>(inMat.step), QImage::Format_ARGB32);
                return image;
            }
            // 8-bit, 3 channel
            case CV_8UC3:
            {
                QImage image(inMat.data, inMat.cols, inMat.rows, static_cast<int>(inMat.step), QImage::Format_RGB888);
                return image.rgbSwapped();
            }
            // 8-bit, 1 channel
            case CV_8UC1:
            {
        #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
                QImage image(inMat.data, inMat.cols, inMat.rows, static_cast<int>(inMat.step), QImage::Format_Grayscale8);
        #else
                static QVector<QRgb>  sColorTable;
    
                // only create our color table the first time
                if (sColorTable.isEmpty())
                {
                    sColorTable.resize(256 );
    
                    for (int i = 0; i < 256; ++i )
                    {
                        sColorTable[i] = qRgb(i, i, i );
                    }
                }
    
                QImage image(inMat.data,
                             inMat.cols, inMat.rows,
                             static_cast<int>(inMat.step),
                             QImage::Format_Indexed8 );
    
                image.setColorTable(sColorTable );
        #endif
                return image;
            }
            default:
            {
                qWarning()<< "ASM::cvMatToQImage()- cv::Mat image type not handled in switch:" << inMat.type();
                break;
            }
        }
        return QImage();
    }
    
    
    
    
    QPixmap MyVideoCapture::cvMatToQPixmap(const cv::Mat &inMat)
    {
        return QPixmap::fromImage(cvMatToQImage(inMat));
    }
    

    According to the debugger, I guess it crashes right after the void MainWindow::on_pushButton_2_clicked() function is done, in the mainwindow.cpp however, I don't know how I could implement it in the other way so it would work properly.

    Zrzut ekranu 2021-05-16 190101.png

    Please help...

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by mrjj
      #2

      Hi
      MyVideoCapture is a thread so your usage seems a bit suspect as it
      will have a very short life.

      void MainWindow::on_pushButton_2_clicked()
      {
      MyVideoCapture f;
      QPixmap frame4 = f.klatka();
      ui->label_2->setPixmap(frame4.scaled(500, 500));
      } << "f" dies here so might not have time to capture anything.

      However, you already have
      mOpenCV_videoCapture
      which seems to be a MyVideoCapture
      so it seems a bit odd to make a new one.

      Also you did hook up to the signal
      connect(mOpenCV_videoCapture, &MyVideoCapture::newPixmapCaptured, this, &
      {
      ui->label->setPixmap(mOpenCV_videoCapture->pixmap().scaled(500, 500));
      });

      Does this function ever run?

      It will only emit that signal if it captures a frame so if it's not emitted then something is
      up with the actual capture.

      Y 1 Reply Last reply
      0
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #3

        I would say it's the common problem when converting cv::Mat to a QImage - noone is reading the documentation and then wonder why the program is crashing. A forum search would have helped here too...

        "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. The image does not delete the buffer at destruction. You can provide a function pointer cleanupFunction along with an extra pointer cleanupInfo that will be called when the last copy is destroyed."

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        1 Reply Last reply
        3
        • mrjjM mrjj

          Hi
          MyVideoCapture is a thread so your usage seems a bit suspect as it
          will have a very short life.

          void MainWindow::on_pushButton_2_clicked()
          {
          MyVideoCapture f;
          QPixmap frame4 = f.klatka();
          ui->label_2->setPixmap(frame4.scaled(500, 500));
          } << "f" dies here so might not have time to capture anything.

          However, you already have
          mOpenCV_videoCapture
          which seems to be a MyVideoCapture
          so it seems a bit odd to make a new one.

          Also you did hook up to the signal
          connect(mOpenCV_videoCapture, &MyVideoCapture::newPixmapCaptured, this, &
          {
          ui->label->setPixmap(mOpenCV_videoCapture->pixmap().scaled(500, 500));
          });

          Does this function ever run?

          It will only emit that signal if it captures a frame so if it's not emitted then something is
          up with the actual capture.

          Y Offline
          Y Offline
          Yamado
          wrote on last edited by
          #4

          @mrjj said in QPixmap::scaled: Pixmap is a null pixmap (displaying Pixmap on the label):

          Hi
          MyVideoCapture is a thread so your usage seems a bit suspect as it
          will have a very short life.

          void MainWindow::on_pushButton_2_clicked()
          {
          MyVideoCapture f;
          QPixmap frame4 = f.klatka();
          ui->label_2->setPixmap(frame4.scaled(500, 500));
          } << "f" dies here so might not have time to capture anything.

          However, you already have
          mOpenCV_videoCapture
          which seems to be a MyVideoCapture
          so it seems a bit odd to make a new one.

          Oh my god... I've changed

          void MainWindow::on_pushButton_2_clicked()
          {
              MyVideoCapture f;
              QPixmap frame4 = f.klatka();
              ui->label_2->setPixmap(frame4.scaled(500, 500));
          }
          

          to

          void MainWindow::on_pushButton_2_clicked()
          {
              QPixmap frame4 = mOpenCV_videoCapture->klatka();
              ui->label_2->setPixmap(frame4.scaled(500, 500));
          }
          

          and now it works as intended. Thank you so much!

          Also you did hook up to the signal
          connect(mOpenCV_videoCapture, &MyVideoCapture::newPixmapCaptured, this, &
          {
          ui->label->setPixmap(mOpenCV_videoCapture->pixmap().scaled(500, 500));
          });

          Does this function ever run?

          It will only emit that signal if it captures a frame so if it's not emitted then something is
          up with the actual capture.

          Well yes, it displays frames from my webcam after I press first button. I might mislead you, as I forgot to add mainwindow.h file. Here it is:

          
          #ifndef MAINWINDOW_H
          #define MAINWINDOW_H
          
          #include <QMainWindow>
          
          namespace Ui
          {
          class MainWindow;
          }
          
          class MyVideoCapture;
          
          class MainWindow : public QMainWindow
          {
              Q_OBJECT
          public:
              explicit MainWindow(QWidget *parent = nullptr);
              ~MainWindow();
              //QPixmap frame4;
          
          private slots:
              void on_pushButton_clicked();
          
              void on_pushButton_2_clicked();
          
          private:
              Ui::MainWindow *ui;
              MyVideoCapture *mOpenCV_videoCapture;
              //QPixmap frame4;
          };
          
          #endif // MAINWINDOW_H
          
          1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @Yamado said in QPixmap::scaled: Pixmap is a null pixmap (displaying Pixmap on the label):

            and now it works as intended. Thank you so much!

            But will still crash now and then - read my post and my link

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            1
            • VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by
              #6

              You are also running a huge race condition as mPixmap is read and written from 2 different threads without mutexing

              "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
              2

              • Login

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