Método 1 de c++ em qt para obter exibição em tempo real da imagem qml - herdando QQuickPaintedItem

Obtenha fluxo de vídeo rtsp ou fonte de vídeo por meio de c++ opencv e exiba vídeo em tempo real em qml.

1. Carregue imagens dinamicamente através de QQuickPaintedItem em QML

Em QML, você pode usar QQuickPaintedItempara criar drawables personalizados. Ao herdar QQuickPaintedItema classe, podemos carregar imagens dinamicamente e desenhá-las em QML. Neste blog, aprenderemos como carregar QQuickPaintedIteme desenhar imagens.

1. opecv obtém a imagem do stream de vídeo

.proIntroduzir opencv no arquivo

#windows
INCLUDEPATH +=D:\soft\opencv3.4.0\OpenCV-MinGW-Build-OpenCV-3.4.5\include
              D:\soft\opencv3.4.0\OpenCV-MinGW-Build-OpenCV-3.4.5\include\opencv
              D:\soft\opencv3.4.0\OpenCV-MinGW-Build-OpenCV-3.4.5\include\opencv2


LIBS +=D:\soft\opencv3.4.0\OpenCV-MinGW-Build-OpenCV-3.4.5\x86\mingw\bin\libopencv_*.dll

Crie uma classe de thread myThreadpara obter fotos
myThread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include "QThread"
#include <QTimer>
#include <QImage>
#include <QMutex>

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>

#include<QtNetwork/QNetworkRequest>
#include<QtNetwork/QNetworkReply>
#include<QtNetwork/QNetworkAccessManager>

class myThread : public QThread
{
    
    
    Q_OBJECT

public:
    explicit myThread(QObject *parent = nullptr);
    myThread(QString url);

protected:
    void run() override;


private:

    cv::VideoCapture video;         // 视频抓取
    cv::Mat src_frame;              // mat类用于存储矩阵类型数据,这里用来存储图像
    QString rtsp;                   // rtsp地址
    bool isStop=false;              // 线程是否运行
    QImage image;

    QNetworkAccessManager * manager;


signals:

    void sendArray(QImage qimg); // 发送图片的信号
    void sendImg(QImage qimg);         // 发送空白图片

public slots:

    void getFrame();            // 获取图像
    void closeFrame();          // 关闭画面
    void closeThread();         // 关闭线程
};

#endif // MYTHREAD_H

myThread.cpp

#include "mythread.h"
#include "QDebug"


myThread::myThread(QObject *parent) : QThread(parent)
{
    
    

    manager=new QNetworkAccessManager(this);
}

myThread::myThread(QString url)
{
    
    
    rtsp=url;

}

void myThread::run()
{
    
    

    qDebug() << "线程开始执行:"<< QThread::currentThread()<<rtsp;
    //  rtsp读取网络视频
    video=cv::VideoCapture(rtsp.toStdString());
    if(video.isOpened())
    {
    
    
        while (!isStop) {
    
    
            getFrame();
            msleep(25);
        }
        if(isStop){
    
    
            closeFrame();
            isStop=false;
        }
    }
}

// 关闭线程
void myThread::closeThread(){
    
    

    isStop=true;
    qDebug() << __FUNCTION__;
}

// 关闭画面
void myThread::closeFrame(){
    
    
    qDebug() << __FUNCTION__;
    emit sendImg(QImage(":/Image/Button/013.png"));
}

// 图像处理
void myThread::getFrame()
{
    
    

    video>>src_frame; //从视频取帧
    // mat to qimage
    if(src_frame.rows>0 && src_frame.cols>0){
    
    
        if(src_frame.channels() == 3) {
    
    
            // RGB image
            cvtColor(src_frame,src_frame,CV_BGR2RGB);
            image = QImage((const uchar*)(src_frame.data),  //(const unsigned char*)
                           src_frame.cols,src_frame.rows,
                           src_frame.cols*src_frame.channels(),   //new add
                           QImage::Format_RGB888);
        }

        else {
    
    
            // gray image
            image = QImage((const uchar*)(src_frame.data),
                           src_frame.cols,src_frame.rows,
                           src_frame.cols*src_frame.channels(),
                           QImage::Format_Indexed8);
        }

        // 发送信号
        emit sendArray(image);
    }else{
    
    
        qDebug() << __FUNCTION__<<"null";

    }
}



2. Crie um item de desenho personalizado –ShowImage.h

Primeiro, precisamos criar uma classe de item drawable personalizada. Nesta aula, substituiremos QQuickPaintedItemos paintmétodos para implementar a lógica do desenho.

ShowImage.h

#ifndef SHOWIMAGE_H
#define SHOWIMAGE_H

#include <QObject>
#include <QQuickPaintedItem>
#include <QImage>
#include <QPainter>

#include <mythread.h>

// qml 实时加载图片第一种方式--继承QQuickPaintedItem,自定义绘制
class ShowImage : public QQuickPaintedItem
{
    
    
    Q_OBJECT
public:
    explicit ShowImage(QQuickItem *parent = nullptr);

public slots:
    void updateImage(const QImage &);
    void start_camera(QString rtsp);
    void close_camera();

signals:
    void close_thread();

protected:
    void paint(QPainter *painter);

private:
    QImage m_imageThumb;
    QImage image_null=QImage(":/image/test.png");  // 默认图片
    myThread *m_thread=nullptr;  

};

#endif // SHOWIMAGE_H

3. Implemente itens de desenho personalizados

Em seguida, precisamos implementar a lógica para itens de desenho personalizados.
ShowImage.cpp

#include "showimage.h"

ShowImage::ShowImage(QQuickItem *parent)
{
    
    
    //默认图片
    m_imageThumb = image_null;
}

// 更新图片
void ShowImage::updateImage(const QImage &image)
{
    
    
    m_imageThumb = image;
    update();
}
// 开启视频捕获
void ShowImage::start_camera(QString rtsp)
{
    
    
    if(m_thread!=nullptr){
    
    
        close_camera();
    }
    m_thread=new myThread(rtsp);
    connect(m_thread,&myThread::sendArray,this,&ShowImage::updateImage);
    connect(m_thread,&myThread::sendImg,this,&ShowImage::updateImage);
    connect(this,&ShowImage::close_thread,m_thread,&myThread::closeThread);
    m_thread->start();

}
// 关闭视频捕获
void ShowImage::close_camera()
{
    
    
    qDebug() <<__FUNCTION__;
    emit close_thread();
    if(m_thread!=nullptr){
    
    
        m_thread->quit();
        m_thread->wait();
        delete m_thread;
        m_thread=nullptr;
    }
}

// 图片绘制
void ShowImage::paint(QPainter *painter)
{
    
    
    if(!m_imageThumb.isNull()){
    
    
        painter->drawImage(this->boundingRect(), m_imageThumb);
    }else{
    
    
        painter->drawImage(this->boundingRect(), QImage(image_null));
    }
}




4. Registre a classe de desenho personalizada em main.cpp

main.cppRegistre classes personalizadas em qml para uso

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <showimage.h>
#include "myimageprovider.h"

int main(int argc, char *argv[])
{
    
    
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    // 获取上下文对象
    QQmlContext *context=engine.rootContext();
    // 注册自定义类
    qmlRegisterType<ShowImage>("ShowImage",1,0,"ShowImage");

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
    
    
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
    
    return app.exec();
}

5. Use classe de desenho personalizada em qml

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0

import ShowImage 1.0  // 导入自定义模块
Window {
    
    
    visible: true
    width: screenW
    height: 480
    title: qsTr("Hello World")

    // 第一种方式--使用自定义模块
    ShowImage{
    
    
        anchors.fill: parent
        id : showimg
        transformOrigin: Item.Center
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
    }

    Button {
    
    
        id:ok
        text: "相机"
        anchors.left: parent.left
        anchors.leftMargin: 20
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 50
        width: parent.width*0.2
        height: 50

        signal start_time_qml()   // 定义信号
        Connections {
    
    			  // 连接信号与槽
            target: ok
            onStart_time_qml: {
    
    
                showimg.start_camera("rtsp://admin:[email protected]/smart265/ch1/main/av_stream")
            }
        }
        onClicked: {
    
    
            ok.start_time_qml()
        }
    }

    Button {
    
    
        id:video
        text: "视频源"
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 50
        width: parent.width*0.2
        height: 50
        x:parent.width*0.32

        signal start_video_qml()
        Connections {
    
    
            target: video
            onStart_video_qml: {
    
    
                showimg.start_camera("H:\\360MoveData\\Users\\Administrator\\Desktop\\11.mp4")
            }
        }
        onClicked: {
    
    
            video.start_video_qml()
        }
    }

    Button {
    
    
        id:clear
        text: "关闭"
        anchors.right: parent.right
        anchors.rightMargin: 20
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 50
        width: parent.width*0.2
        height: 50
        x:parent.width*0.62

        signal clear_time_qml()
        Connections {
    
    
            target: clear
            onClear_time_qml: {
    
    
                showimg.close_camera()
            }
        }
        onClicked: {
    
    
            clear.clear_time_qml()
        }
    }
}

6. Execute o programa

Agora, você pode executar o aplicativo e clicar no botão correspondente para carregar e exibir a imagem dinamicamente. Ao clicar no botão, o método ShowImageserá utilizado updateImagepara carregar a figura com o caminho especificado e desenhá-la na interface.

insira a descrição da imagem aqui

Veja a reprodução de um vídeo como exemplo:

qml exibição em tempo real

QQuickPaintedItemEste é o passo básico para carregar imagens dinamicamente em QML . Você pode personalizar ainda mais a funcionalidade e a aparência dos itens de desenho personalizados, conforme necessário.

Espero que este blog seja útil para você! Se você tiver alguma dúvida, sinta-se à vontade para perguntar.

Código fonte

Acho que você gosta

Origin blog.csdn.net/ljn1046016768/article/details/131332297
Recomendado
Clasificación