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. A continuous capture of a window sceen as QPixmap? for OpenCV
Forum Updated to NodeBB v4.3 + New Features

A continuous capture of a window sceen as QPixmap? for OpenCV

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 562 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.
  • J Offline
    J Offline
    jaouad100
    wrote on last edited by
    #1

    I'm trying to get a live view of a specific window using Qt6.6. So far I have succeed to do that for the whole screen. However, when I implemented the code for a specific window I get stuck at capturing the window screen as QPixmap. The object is QWindowCapture but it doesn't have a method for capturing or something similar. Once I get that, I'll convert it into OpenCV format for further processing which is what I have done with screen capturing. That's my goal why I need capturing.

    Here is the code if you want to try it:

    #include <QApplication>
    #include <QScreen>
    #include <QPixmap>
    #include <QImage>
    #include <opencv2/opencv.hpp>
    #include <QAbstractListModel>
    #include <QCapturableWindow>
    #include <QWindowCapture>
    
    QT_USE_NAMESPACE
    
    class WindowListModel : public QAbstractListModel
    {
        Q_OBJECT
    
    public:
        explicit WindowListModel(QObject *parent = nullptr);
    
        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    
        QCapturableWindow window(const QModelIndex &index) const;
    
    public Q_SLOTS:
        void populate();
    
    private:
        QList<QCapturableWindow> windowList;
    };
    
    class Screenshot {
    public:
        void displayLiveView();
    
    private:
        QPixmap grabScreen();
    };
    
    QPixmap Screenshot::grabScreen() {
        QScreen *screen = QGuiApplication::primaryScreen();
        if (!screen)
            return QPixmap();
    
        return screen->grabWindow(0);
    }
    
    void Screenshot::displayLiveView() {
        while (true) {
            QPixmap pixmap = grabScreen();
            if (pixmap.isNull()) {
                qDebug() << "Failed to capture the screen.";
                continue;
            }
            QImage image = pixmap.toImage();
            cv::Mat mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
            cv::imshow("Live View", mat);
            
            // Break if 'ESC' is pressed
            if (cv::waitKey(30) == 27) {
                break;
            }
        }
    }
    
    void captureAndShowWindow(const QString& windowName) {
        // Obtain a list of available windows
        WindowListModel windowListModel;
        windowListModel.populate();
    
        QCapturableWindow targetWindow; // Window we are looking for
    
        bool windowFound = false;
        for (int i = 0; i < windowListModel.rowCount(); i++) {
            QModelIndex index = windowListModel.index(i);
            if (index.isValid()) {
                QString currentWindowDesc = windowListModel.data(index, Qt::DisplayRole).toString();
                if (currentWindowDesc.contains(windowName)) {
                    targetWindow = windowListModel.window(index);
                    windowFound = true;
                    break;
                }
            }
        }
    
        if (!windowFound) {
            qDebug() << "Window not found!";
            return;
        }
    
        // Capture the specific window
        QWindowCapture windowCapture;
        windowCapture.setWindow(targetWindow);
        //STUCK
    }
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
    
        // Print available windows
        WindowListModel model;
        for (int i = 0; i < model.rowCount(); i++) {
            QModelIndex index = model.index(i);
            if (index.isValid()) {
                QString windowDesc = model.data(index, Qt::DisplayRole).toString();
                std::cout << i + 1 << ". " << windowDesc.toStdString() << std::endl;
            }
        }
    
        Screenshot screenshot;
        screenshot.displayLiveView();
        captureAndShowWindow("Settings");
    
        return 0;
    }
    

    The CMakeLists:

    cmake_minimum_required(VERSION 3.10)
    
    project(ScreenshotApp)
    
    # Set up the required version of Qt 
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTORCC ON)
    set(CMAKE_AUTOUIC ON)
    
    include_directories(include)
    
    list(APPEND CMAKE_PREFIX_PATH "/home/user/Qt/6.6.0/gcc_64/lib/cmake")
    
    find_package(Qt6 COMPONENTS Widgets Multimedia REQUIRED)
    find_package(OpenCV 4.7.0 REQUIRED)
    
    set_property(SOURCE main.cpp PROPERTY SKIP_AUTOMOC ON)
    
    add_executable(main main.cpp ${SOURCES})
    target_link_libraries(main Qt6::Widgets ${OpenCV_LIBS} Qt6::Multimedia)
    

    I'm open for other solutions or using different version of Qt.

    SGaistS 1 Reply Last reply
    0
    • J Offline
      J Offline
      jaouad100
      wrote on last edited by
      #7

      The trick is to get targetWindowId and feed that to QScreen grabWindow. This will give you QPixmap format which is easily converted into OpenCV cv::Mat.

      For that I picked a class which is called private in Qt source code because it is not part of their API.

      class QCapturableWindowPrivate : public QSharedData {
      public:
          using Id = size_t;
      
          QString description;
          Id id = 0;
      
          static const QCapturableWindowPrivate *handle(const QCapturableWindow &window)
          {
              return window.d.get();
          }
      
          QCapturableWindow create() { return QCapturableWindow(this); }
      };
      
      class Screenshot {
      public:
          Screenshot(const QString& windowName);
          void displayLiveView();
      
      private:
          QPixmap grabWindow();
          WId targetWindowId = 0;
          QWindowCapture windowCapture;
      };
      
      Screenshot::Screenshot(const QString& windowName) {
          WindowListModel windowListModel;
          windowListModel.populate();
      
          QCapturableWindow targetWindow; // Window we are looking for
      
          bool windowFound = false;
          for (int i = 0; i < windowListModel.rowCount(); i++) {
              QModelIndex index = windowListModel.index(i);
              if (index.isValid()) {
                  QString currentWindowDesc = windowListModel.data(index, Qt::DisplayRole).toString();
                  if (currentWindowDesc.contains(windowName)) {
                      targetWindow = windowListModel.window(index);
                      windowFound = true;
                      break;
                  }
              }
          }
      
          if (!windowFound) {
              qDebug() << "Window not found!";
              return;
          }
      
          windowCapture.setWindow(targetWindow);
      
          auto handle = QCapturableWindowPrivate::handle(targetWindow);
          targetWindowId = handle ? handle->id : 0;
      }
      
      QPixmap Screenshot::grabWindow() {
          if (targetWindowId == 0) return QPixmap();
      
          QScreen *screen = QGuiApplication::primaryScreen();
          if (!screen) return QPixmap();
      
          return screen->grabWindow(targetWindowId);
      }
      
      void Screenshot::displayLiveView() {
          while (true) {
              QPixmap pixmap = grabWindow();
              if (pixmap.isNull()) {
                  qDebug() << "Failed to capture the window.";
                  continue;
              }
      
              QImage image = pixmap.toImage();
              cv::Mat mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
              cv::imshow("Live View", mat);
      
              if (cv::waitKey(30) == 27) {
                  break;
              }
          }
      }
      
      int main(int argc, char *argv[]) {
          QApplication app(argc, argv);
      
          // Print available windows
          WindowListModel model;
          for (int i = 0; i < model.rowCount(); i++) {
              QModelIndex index = model.index(i);
              if (index.isValid()) {
                  QString windowDesc = model.data(index, Qt::DisplayRole).toString();
                  std::cout << i + 1 << ". " << windowDesc.toStdString() << std::endl;
              }
          }
      
          Screenshot screenshot("Settings"); //The name of the window from the printed list
          screenshot.displayLiveView();
      
          return 0;
      }
      
      1 Reply Last reply
      0
      • J jaouad100

        I'm trying to get a live view of a specific window using Qt6.6. So far I have succeed to do that for the whole screen. However, when I implemented the code for a specific window I get stuck at capturing the window screen as QPixmap. The object is QWindowCapture but it doesn't have a method for capturing or something similar. Once I get that, I'll convert it into OpenCV format for further processing which is what I have done with screen capturing. That's my goal why I need capturing.

        Here is the code if you want to try it:

        #include <QApplication>
        #include <QScreen>
        #include <QPixmap>
        #include <QImage>
        #include <opencv2/opencv.hpp>
        #include <QAbstractListModel>
        #include <QCapturableWindow>
        #include <QWindowCapture>
        
        QT_USE_NAMESPACE
        
        class WindowListModel : public QAbstractListModel
        {
            Q_OBJECT
        
        public:
            explicit WindowListModel(QObject *parent = nullptr);
        
            int rowCount(const QModelIndex &parent = QModelIndex()) const override;
            QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
        
            QCapturableWindow window(const QModelIndex &index) const;
        
        public Q_SLOTS:
            void populate();
        
        private:
            QList<QCapturableWindow> windowList;
        };
        
        class Screenshot {
        public:
            void displayLiveView();
        
        private:
            QPixmap grabScreen();
        };
        
        QPixmap Screenshot::grabScreen() {
            QScreen *screen = QGuiApplication::primaryScreen();
            if (!screen)
                return QPixmap();
        
            return screen->grabWindow(0);
        }
        
        void Screenshot::displayLiveView() {
            while (true) {
                QPixmap pixmap = grabScreen();
                if (pixmap.isNull()) {
                    qDebug() << "Failed to capture the screen.";
                    continue;
                }
                QImage image = pixmap.toImage();
                cv::Mat mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
                cv::imshow("Live View", mat);
                
                // Break if 'ESC' is pressed
                if (cv::waitKey(30) == 27) {
                    break;
                }
            }
        }
        
        void captureAndShowWindow(const QString& windowName) {
            // Obtain a list of available windows
            WindowListModel windowListModel;
            windowListModel.populate();
        
            QCapturableWindow targetWindow; // Window we are looking for
        
            bool windowFound = false;
            for (int i = 0; i < windowListModel.rowCount(); i++) {
                QModelIndex index = windowListModel.index(i);
                if (index.isValid()) {
                    QString currentWindowDesc = windowListModel.data(index, Qt::DisplayRole).toString();
                    if (currentWindowDesc.contains(windowName)) {
                        targetWindow = windowListModel.window(index);
                        windowFound = true;
                        break;
                    }
                }
            }
        
            if (!windowFound) {
                qDebug() << "Window not found!";
                return;
            }
        
            // Capture the specific window
            QWindowCapture windowCapture;
            windowCapture.setWindow(targetWindow);
            //STUCK
        }
        
        int main(int argc, char *argv[]) {
            QApplication app(argc, argv);
        
            // Print available windows
            WindowListModel model;
            for (int i = 0; i < model.rowCount(); i++) {
                QModelIndex index = model.index(i);
                if (index.isValid()) {
                    QString windowDesc = model.data(index, Qt::DisplayRole).toString();
                    std::cout << i + 1 << ". " << windowDesc.toStdString() << std::endl;
                }
            }
        
            Screenshot screenshot;
            screenshot.displayLiveView();
            captureAndShowWindow("Settings");
        
            return 0;
        }
        

        The CMakeLists:

        cmake_minimum_required(VERSION 3.10)
        
        project(ScreenshotApp)
        
        # Set up the required version of Qt 
        set(CMAKE_AUTOMOC ON)
        set(CMAKE_AUTORCC ON)
        set(CMAKE_AUTOUIC ON)
        
        include_directories(include)
        
        list(APPEND CMAKE_PREFIX_PATH "/home/user/Qt/6.6.0/gcc_64/lib/cmake")
        
        find_package(Qt6 COMPONENTS Widgets Multimedia REQUIRED)
        find_package(OpenCV 4.7.0 REQUIRED)
        
        set_property(SOURCE main.cpp PROPERTY SKIP_AUTOMOC ON)
        
        add_executable(main main.cpp ${SOURCES})
        target_link_libraries(main Qt6::Widgets ${OpenCV_LIBS} Qt6::Multimedia)
        

        I'm open for other solutions or using different version of Qt.

        SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        Are you thinking about something like QWidget::render ?

        On a side note, QObject based classes are not copyable so storing them by value in a container should trigger an error.

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

        J 1 Reply Last reply
        2
        • SGaistS SGaist

          Hi,

          Are you thinking about something like QWidget::render ?

          On a side note, QObject based classes are not copyable so storing them by value in a container should trigger an error.

          J Offline
          J Offline
          jaouad100
          wrote on last edited by
          #3

          @SGaist Not really, I was thinking about QPixmap just because I can get an QImage
          and then to OpenCV easily.

          For the note you're referring to QList<QCapturableWindow> windowList;?

          SGaistS 1 Reply Last reply
          0
          • J jaouad100

            @SGaist Not really, I was thinking about QPixmap just because I can get an QImage
            and then to OpenCV easily.

            For the note you're referring to QList<QCapturableWindow> windowList;?

            SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #4

            You can use a QImage as a target for render. If you push things a bit, you can create a QImage that wraps the buffer of your cv::Mat and paint on it so you would have less operations to do.

            Yes, that's my note target.

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

            J 1 Reply Last reply
            1
            • SGaistS SGaist

              You can use a QImage as a target for render. If you push things a bit, you can create a QImage that wraps the buffer of your cv::Mat and paint on it so you would have less operations to do.

              Yes, that's my note target.

              J Offline
              J Offline
              jaouad100
              wrote on last edited by
              #5

              @SGaist I need some guidance for implementing this, can you help me with few steps and the functions I need to use, please?

              Okay for note, I'll correct that. Thank you for pointing that out.

              jsulmJ 1 Reply Last reply
              0
              • J jaouad100

                @SGaist I need some guidance for implementing this, can you help me with few steps and the functions I need to use, please?

                Okay for note, I'll correct that. Thank you for pointing that out.

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #6

                @jaouad100 Create a QImage using your image data: https://doc.qt.io/qt-6/qimage.html#QImage-3
                Paint on this QImage: https://doc.qt.io/qt-6/qpainter.html

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

                1 Reply Last reply
                2
                • J Offline
                  J Offline
                  jaouad100
                  wrote on last edited by
                  #7

                  The trick is to get targetWindowId and feed that to QScreen grabWindow. This will give you QPixmap format which is easily converted into OpenCV cv::Mat.

                  For that I picked a class which is called private in Qt source code because it is not part of their API.

                  class QCapturableWindowPrivate : public QSharedData {
                  public:
                      using Id = size_t;
                  
                      QString description;
                      Id id = 0;
                  
                      static const QCapturableWindowPrivate *handle(const QCapturableWindow &window)
                      {
                          return window.d.get();
                      }
                  
                      QCapturableWindow create() { return QCapturableWindow(this); }
                  };
                  
                  class Screenshot {
                  public:
                      Screenshot(const QString& windowName);
                      void displayLiveView();
                  
                  private:
                      QPixmap grabWindow();
                      WId targetWindowId = 0;
                      QWindowCapture windowCapture;
                  };
                  
                  Screenshot::Screenshot(const QString& windowName) {
                      WindowListModel windowListModel;
                      windowListModel.populate();
                  
                      QCapturableWindow targetWindow; // Window we are looking for
                  
                      bool windowFound = false;
                      for (int i = 0; i < windowListModel.rowCount(); i++) {
                          QModelIndex index = windowListModel.index(i);
                          if (index.isValid()) {
                              QString currentWindowDesc = windowListModel.data(index, Qt::DisplayRole).toString();
                              if (currentWindowDesc.contains(windowName)) {
                                  targetWindow = windowListModel.window(index);
                                  windowFound = true;
                                  break;
                              }
                          }
                      }
                  
                      if (!windowFound) {
                          qDebug() << "Window not found!";
                          return;
                      }
                  
                      windowCapture.setWindow(targetWindow);
                  
                      auto handle = QCapturableWindowPrivate::handle(targetWindow);
                      targetWindowId = handle ? handle->id : 0;
                  }
                  
                  QPixmap Screenshot::grabWindow() {
                      if (targetWindowId == 0) return QPixmap();
                  
                      QScreen *screen = QGuiApplication::primaryScreen();
                      if (!screen) return QPixmap();
                  
                      return screen->grabWindow(targetWindowId);
                  }
                  
                  void Screenshot::displayLiveView() {
                      while (true) {
                          QPixmap pixmap = grabWindow();
                          if (pixmap.isNull()) {
                              qDebug() << "Failed to capture the window.";
                              continue;
                          }
                  
                          QImage image = pixmap.toImage();
                          cv::Mat mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
                          cv::imshow("Live View", mat);
                  
                          if (cv::waitKey(30) == 27) {
                              break;
                          }
                      }
                  }
                  
                  int main(int argc, char *argv[]) {
                      QApplication app(argc, argv);
                  
                      // Print available windows
                      WindowListModel model;
                      for (int i = 0; i < model.rowCount(); i++) {
                          QModelIndex index = model.index(i);
                          if (index.isValid()) {
                              QString windowDesc = model.data(index, Qt::DisplayRole).toString();
                              std::cout << i + 1 << ". " << windowDesc.toStdString() << std::endl;
                          }
                      }
                  
                      Screenshot screenshot("Settings"); //The name of the window from the printed list
                      screenshot.displayLiveView();
                  
                      return 0;
                  }
                  
                  1 Reply Last reply
                  0
                  • J jaouad100 has marked this topic as solved on

                  • Login

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