Memory leak (OpenCV + QML)



  • Hi! I’m trying to display OpenCV Mat in QML image.

    I grab frames from camera with OpenCV, the frames are displayed successfully in QML, but memory usage increases with time. How can I fix it? Here is the my code:

    main.cpp

    #include <QGuiApplication>
    #include "videoprovider.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        VideoProvider videoProvider;
    
        return app.exec();
    }
    

    VideoProvider.h

    #ifndef VIDEOPROVIDER_H
    #define VIDEOPROVIDER_H
    
    #include <QObject>
    #include <QFuture>
    #include <QImage>
    #include <QQmlApplicationEngine>
    #include <QQuickImageProvider>
    #include <opencv2/opencv.hpp>
    
    class VideoProvider : public QObject, public QQuickImageProvider
    {
        Q_OBJECT
    public:
        explicit VideoProvider();
        QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize);
    
    signals:
        void frameChanged();
    
    public slots:
        void framePainted();
    
    private:
        QQmlApplicationEngine engine;
        bool readyfor;
        cv::Mat mat;
        QImage outputImage;
        void process();
    };
    
    #endif // VIDEOPROVIDER_H
    

    VideoProvider.cpp

    #include <QQmlContext>
    #include <QtConcurrent/QtConcurrent>
    #include <QDebug>
    #include <QThread>
    #include "videoprovider.h"
    #include <QQuickImageProvider>
    
    VideoProvider::VideoProvider() : QQuickImageProvider (QQuickImageProvider :: Pixmap)
    {
        engine.rootContext()->setContextProperty("videoProvider", this);
    
        engine.addImageProvider(QLatin1String ("videoCapture"), this);
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        readyfor = true;
    
        QtConcurrent::run(this, VideoProvider::process);
    }
    
    void VideoProvider::framePainted()
    {
        readyfor = true;
    }
    
    void VideoProvider::process()
    {
        cv::VideoCapture capture(0);
    
        while(true){
    
            QThread::currentThread()->msleep(80);
    
            if(!readyfor) continue;
    
            mat.release();
    
            capture >> mat;
    
            if(mat.empty())
            {
                qDebug()<<"disconnect";
            }
            else
            {
                readyfor = false;
    
                cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);
    
                outputImage = QImage((uchar*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
    
                emit frameChanged();
            }
        }
    
        capture.release();
    }
    
    QPixmap VideoProvider::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize)
    {
        return QPixmap::fromImage(outputImage);
    }
    

    main.qml

    import QtQuick 2.6
    import QtQuick.Window 2.2
    
    Window
    {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
        id: root
    
        Image {
            id: videoLayer
            anchors.fill: parent
            cache: false
    
            onSourceChanged:{
                videoProvider.framePainted();
            }
        }
     
        Connections
        {
            target: videoProvider
            property int frameCounter: 0
    
            onFrameChanged:
            {
                videoLayer.source = "image://videoCapture/hoge" + frameCounter;
                frameCounter ^= 1;
            }
        }
    }
    

    I found that it happened when I send signal (emit frameChanged();) to QML.



  • @DYYF have you tried any other examples for OpenCV + QML? i.e. here or here?
    I'm not sure why, but I don't like your videoprocessor object launching the QML engine. All the examples I've used to so far run the QML engine from main.cpp


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.