Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. 2200% CPU Usage from processed camera feed implementation
Qt 6.11 is out! See what's new in the release blog

2200% CPU Usage from processed camera feed implementation

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
7 Posts 4 Posters 283 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.
  • O Offline
    O Offline
    OyvindNordbo
    wrote last edited by
    #1

    [QML] Poor FPS and 15–20s camera control delay when displaying ROS2-processed feed (YOLOv8 + LiDAR) in QML – Qt 5.15

    Hi everyone,

    I'm working on a student project where I'm redesigning an existing robot GUI from Qt Widgets to QML. I'm fairly new to QML, Qt, and ROS2, so bear with me.

    Setup:

    • Qt 5.15.13 (fixed version to match the existing system)
    • ROS2 for inter-process communication
    • A classification node (camera_classified.py) that fuses LiDAR data and YOLOv8 to produce a processed camera feed published on the ROS topic camera/classified (bounding boxes around targets)
    • The raw feed comes in on camera/raw

    The problem:
    My new QML-based GUI suffers from noticeably lower FPS than the previous Widgets-based GUI, and camera control inputs have a 15–20 second delay. Both systems share the exact same backend (camera_classified.py), so the issue must be in my QML implementation.

    Note: the high CPU usage (~2200%) from the classification node is expected and present in both the old and new system — that is not the issue as its the same for the old system. We have no GPU on our dev PC's, but the camera feed from the old GUI is ≈15 fps, and the delay is sub 2sec.

    My question:
    Has anyone integrated a ROS2 image topic into QML, especially where the image source involves heavy ML preprocessing? I'm looking for advice on:

    • Best practices for bridging ROS2 image messages to a QML image provider
    • Whether QQuickImageProvider or a custom QAbstractVideoSurface is the right approach at Qt 5.15
    • How to avoid bottlenecks that could cause frame drops or input lag (e.g. unnecessary frame copies, blocking the UI thread, missing throttling)

    I'm happy to share relevant code snippets — just let me know what would be most helpful to see.

    Thanks in advance!

    1 Reply Last reply
    0
    • GrecKoG Offline
      GrecKoG Offline
      GrecKo
      Qt Champions 2018
      wrote last edited by
      #2

      so the issue must be in my QML implementation.

      Maybe tell us a bit more about your QML implementation.

      1 Reply Last reply
      0
      • O Offline
        O Offline
        OyvindNordbo
        wrote last edited by
        #3

        I'm using a class inherited by QQuickPaintedItems.

        this is the function used for painting:

        void paint(QPainter* painter) override{
        std::lock_guardstd:mutex lock(m_mutex);
        if(!m_frame->drawImage(boundingRect(), m_frame);
        }
        }

        I belive this might be the issue. My theory is that Qt uses ffmpeg lib as default to enable cam feed. This method routes all video feed through the CPU, not the GPU.

        My dev PC uses a powerful i9, and there is no GPU which could explain the lagg issues. If my theory is right however, installing a GPU won't fix it as easily.

        Ronel_qtmasterR GrecKoG 2 Replies Last reply
        0
        • B Offline
          B Offline
          Bob64
          wrote last edited by
          #4

          What triggers the call to paint()?

          1 Reply Last reply
          0
          • O OyvindNordbo

            I'm using a class inherited by QQuickPaintedItems.

            this is the function used for painting:

            void paint(QPainter* painter) override{
            std::lock_guardstd:mutex lock(m_mutex);
            if(!m_frame->drawImage(boundingRect(), m_frame);
            }
            }

            I belive this might be the issue. My theory is that Qt uses ffmpeg lib as default to enable cam feed. This method routes all video feed through the CPU, not the GPU.

            My dev PC uses a powerful i9, and there is no GPU which could explain the lagg issues. If my theory is right however, installing a GPU won't fix it as easily.

            Ronel_qtmasterR Offline
            Ronel_qtmasterR Offline
            Ronel_qtmaster
            wrote last edited by
            #5

            @OyvindNordbo I see, in fact paint event is called each second. Your problem is that you do not release the memory occupied by the Image you are drawing hence the cpu activity will continue to increase . You can free that memory using the constructor of the image. Something like this might help.

            QImage Image;
            drawImage(rect, Image);
            Image = QImage();

            O 1 Reply Last reply
            0
            • O OyvindNordbo

              I'm using a class inherited by QQuickPaintedItems.

              this is the function used for painting:

              void paint(QPainter* painter) override{
              std::lock_guardstd:mutex lock(m_mutex);
              if(!m_frame->drawImage(boundingRect(), m_frame);
              }
              }

              I belive this might be the issue. My theory is that Qt uses ffmpeg lib as default to enable cam feed. This method routes all video feed through the CPU, not the GPU.

              My dev PC uses a powerful i9, and there is no GPU which could explain the lagg issues. If my theory is right however, installing a GPU won't fix it as easily.

              GrecKoG Offline
              GrecKoG Offline
              GrecKo
              Qt Champions 2018
              wrote last edited by
              #6

              @OyvindNordbo said in 2200% CPU Usage from processed camera feed implementation:

              I'm using a class inherited by QQuickPaintedItem

              Yeah that won't get you far.

              In Qt 5.15 use VideoOutput with your own QObject as its source and expose a videoSurface property accepting a QAbstractVideoSurface

              1 Reply Last reply
              2
              • Ronel_qtmasterR Ronel_qtmaster

                @OyvindNordbo I see, in fact paint event is called each second. Your problem is that you do not release the memory occupied by the Image you are drawing hence the cpu activity will continue to increase . You can free that memory using the constructor of the image. Something like this might help.

                QImage Image;
                drawImage(rect, Image);
                Image = QImage();

                O Offline
                O Offline
                OyvindNordbo
                wrote last edited by OyvindNordbo
                #7

                @Ronel_qtmaster @GrecKo

                Thank you both for the suggestions — I'll work through them and report back.

                Unfortunately I can't share much code as I initially said due to project confidentiality, but here's as much context as I can give (feel free to ask for more if there's any confusion):

                Architecture overview:

                • The backend runs a ROS2 classification node using Ultralytics YOLOv8 + PyTorch. This is understandably CPU-heavy.
                • My GUI class subscribes to a ROS topic that fires a signal each time the classification of one frame completes.
                • A camera bridge class is connected to the GUI class and forwards frames to QML.
                • The QML GUI itself runs as a dedicated ROS2 node, launched inside a QThread.

                Comparison with the old Widget-based GUI:
                The previous implementation used QPixmap inside a standard Qt Widgets GUI. It worked — the FPS dropped from ~30 to ~10 due to the ML overhead, but it was fully usable. My QML implementation is significantly worse: ~1 FPS with a ~20-second rendering delay, making camera control completely unusable.

                Since the backend is identical in both cases, the bottleneck must be in how I'm bridging frames from the ROS2 subscription into QML.

                Potential issue I'm investigating:
                I suspect the QML rendering pipeline is either blocking on frame delivery, accumulating a backlog of unprocessed frames, or doing unnecessary work on the UI thread — but I haven't pinpointed it yet.

                Could there be a potential fault in how I configure the main.cpp file? I've provided the core logic from my implementation below.

                int main( argc, *argv[])
                {

                qputenv("QSG_RENDER_LOOP", "thread"); //tried to use basic, virtually no difference
                rclcpp::init(argc, argv);
                qRegisterMetaType<QImage>("QImage")
                

                .....
                QApplication app(argc, argv);
                .....
                QNode qnode;
                if (!qnode.init()) return -1;
                ....//Initializing camera
                auto cameraProvider = new CameraBridge();
                engine.rootContext()->setContextProperty("cameraBridge", cameraProvider)
                ......
                engine.load(url);
                if (engine.rootObjects().isEmpty()) return -1;

                int result = app.exec();
                rclcpp::shutdown();
                qnode.wait();
                return result;
                

                }

                @Ronel_qtmaster — I tried applying your suggestion to my paint function but didn't see an improvement. It's possible I'm not applying it at the right point in the pipeline, but I belive my implementation is correct.

                @GrecKo — I'll implement your approach and report back today or tomorrow.

                Fallback plan:
                If I can't resolve this in QML, I may try embedding the old QPixmap-based camera widget into my QML app using QQuickWidget or similar. I know mixing Widgets and QML is generally discouraged in that direction, but it may be the pragmatic solution here. Any experience or tips with that approach would be welcomed.

                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