You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Qt Creator的Python Qt Quick应用中通过OpenCV向QML MediaPlayer推流

实现方案

核心思路:不使用MediaPlayer组件接收自定义帧数据,直接将OpenCV处理后的帧转为Qt支持的图像格式,通过属性绑定同步到QML端渲染,性能更高,更适配安防监控多路流的扩展需求。

1. 修改后端main.py代码

你需要在原有MainWindow类中新增视频采集逻辑、图像转换逻辑和供QML绑定的帧属性:

import sys
import os
import datetime
import cv2
from pathlib import Path
from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtProperty
from PyQt5.QtGui import QImage
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtGui import QGuiApplication

class MainWindow(QObject):
    # 帧更新信号
    frameChanged = pyqtSignal(QImage)
    
    def __init__(self):
        QObject.__init__(self)
        # 原有时间更新逻辑保留
        self.timer = QTimer()
        self.timer.timeout.connect(lambda: self.setTime())
        self.timer.start(1000)
        
        # 新增OpenCV视频采集逻辑
        self.capture = cv2.VideoCapture(0) # 填0为本地摄像头,填RTSP地址即可拉取监控流
        self._cv_frame = QImage()
        
        # 视频帧采集定时器,30fps对应33ms间隔,可根据实际帧率调整
        self.frame_timer = QTimer()
        self.frame_timer.timeout.connect(self.updateFrame)
        self.frame_timer.start(33)

    # 新增帧属性供QML绑定
    @pyqtProperty(QImage, notify=frameChanged)
    def cvFrame(self):
        return self._cv_frame

    # 新增帧采集转换逻辑
    def updateFrame(self):
        ret, frame = self.capture.read()
        if not ret:
            return
        # OpenCV默认BGR格式,需转为RGB
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        # 转QImage
        height, width, channel = frame_rgb.shape
        bytes_per_line = channel * width
        q_image = QImage(frame_rgb.data, width, height, bytes_per_line, QImage.Format_RGB888)
        # 更新属性并发射信号
        if self._cv_frame != q_image:
            self._cv_frame = q_image
            self.frameChanged.emit(self._cv_frame)

    # 原有时间逻辑保留
    def setTime(self):
        now = datetime.datetime.now()
        formatDate = now.strftime("Time: %H:%M:%S %p of %Y/%m/%d")
        self.printTime.emit(formatDate)

    # 原有printTime信号定义,若之前代码已存在可忽略
    printTime = pyqtSignal(str)

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    main = MainWindow()
    engine.rootContext().setContextProperty("backend", main)

    engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml"))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

2. 修改QML端代码

将原有MediaPlayer+VideoOutput的组合替换为Image组件,绑定后端暴露的cvFrame属性即可:

Image {
    id: cvFrameDisplay
    anchors.fill: parent
    source: backend.cvFrame
    fillMode: Image.PreserveAspectFit // 按需调整填充模式
}

// 原有时间显示的Connections逻辑保留
Connections{
    target: backend
    function onPrintTime(time){
        labelDate.text = time
    }
}

扩展多路流说明

后续需要接入多路监控流时,可单独封装一个CVStreamWorker类继承QObject,每个流实例化一个该类的对象,分别注册到QML上下文或者注册为QML可实例化类型,每个对象对应一个QML端的Image组件即可,无需修改现有核心逻辑。

注意:如果需要对帧进行AI检测、叠加OSD信息等操作,直接在updateFrame方法中拿到OpenCV的frame对象处理后再转QImage即可,无需额外改适配逻辑。

内容的提问来源于stack exchange,提问作者Cizhu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 04:24:07