天天看點

QML 中使用 QQuickImageProvider 實作圖像動态重新整理

作者:音視訊開發老舅

前言

想要在 QML 中實時顯示圖像,目前部落客已知的方法有3個,分别是繼承 QQuickItem、繼承 QQuickPaintedItem、以及使用 QQuickImageProvider。這篇文章來介紹一下如何使用 QQuickImageProvider 調用相機實時顯示圖像,友善後期自己回顧

1、使用 OpenCV 實作相機控制,圖像采集

自定義 Camera 類,通過 OpenCV 的 VideoCapture 來打開相機擷取圖像

void Camera::updateFrame()
{
    if ( m_camera.isOpened() ) {
        cv::Mat3b mat;
        m_camera >> mat;

        QImage image((const unsigned char *)(mat.data), mat.cols, mat.rows, mat.cols * 3, QImage::Format_RGB888);
        QImage ret = image.rgbSwapped();

        emit updateImage(ret.convertToFormat(QImage::Format_RGB888));
    }
}
           

2、自定義 ImageProvider 類繼承于 QQuickImageProvider

這裡需要重新實作接口 requestPixmap

QT開發交流+赀料君羊:714620761
class ImageProvider : public QQuickImageProvider
{
public:
    ImageProvider();

    void updateImage(QImage &image);    // 更新圖像

    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;

private:
    QImage m_image;
};
           

3、自定義 CameraControl 類

此類主要實作相機的控制并且當相機重新整理圖像時,能夠更新 ImageProvider 中的圖像。還需要提供打開相機的接口給QML調用

class CameraControl : public QObject
{
    Q_OBJECT
public:
    explicit CameraControl(QObject *parent = nullptr);
    ~CameraControl();

    Q_INVOKABLE void openCamera(int interval);

    inline ImageProvider *getImageProvider() { return m_imageProvider; }

signals:
    void callQmlRefeshImg();

private:
    ImageProvider *m_imageProvider;
    Camera *m_camera;
};
           
CameraControl::CameraControl(QObject *parent) : QObject(parent)
{
    m_imageProvider = new ImageProvider();

    m_camera = new Camera();
    connect(m_camera, &Camera::updateImage, [&](QImage image){
        m_imageProvider->updateImage(image);	// 更新圖像
        emit callQmlRefeshImg();	// 發送信号,讓QML也更新圖像
    });
}

CameraControl::~CameraControl()
{
    delete m_camera;
}

void CameraControl::openCamera(int interval)
{
    m_camera->openCamera(interval);
    m_camera->startWork();
}
           

4、在主函數中使用 addImageProvider 函數添加圖檔入口

CameraControl cameraCtl;
engine.rootContext()->setContextProperty("cameraCtl", &cameraCtl);
engine.addImageProvider(QLatin1String("QYCamera"), cameraCtl.getImageProvider());
           

5、在 QML 中使用全局的 cameraCtl 重新整理圖像

收到信号後修改 Image 的 source 屬性即可實作圖像不斷重新整理

Image {
    id: image
    anchors.fill: parent

    Component.onCompleted: cameraCtl.openCamera(100)    // 打開相機,每 100 ms 取一張圖檔

    Connections {
        target: cameraCtl

        // 收到信号重新整理圖檔
        onCallQmlRefeshImg: image.source = "image://QYCamera/" + Math.random()
    }
}
           

繼續閱讀