如何在QML/PySide6应用中显示OpenCV相机画面?
问题:在PySide6/QML应用中显示OpenCV相机画面
我需要在QML/PySide6应用中显示OpenCV相机画面,应用包含开始/停止流两个按钮和一个用于显示视频的Image元素。目前已能设置静态图片,但不知道如何将每一帧动态图像传递给requestImage;同时不清楚QML文件中onImageChanged函数的image属性如何与source: "image://MyImageProvider/img"关联。找不到其他OpenCV与QML/PySide6集成的示例,希望得到帮助。我更熟悉QtWidgets,刚学习QML!
初始代码
main.py
import sys from pathlib import Path import os import cv2 from PySide6.QtGui import QGuiApplication from PySide6.QtQml import QQmlApplicationEngine from PySide6.QtGui import QIcon, QPixmap, QImage from PySide6.QtWidgets import QFileDialog, QApplication from PySide6.QtCore import Qt, QThread, Signal, Slot, QObject, QSize from PySide6.QtQuick import QQuickPaintedItem, QQuickView, QQuickImageProvider class ThreadCamera(QThread): updateFrame = Signal(QImage) def __init__(self, parent=None): QThread.__init__(self, parent) def run(self): self.cap = cv2.VideoCapture(0) while self.cap.isOpened(): ret, frame = self.cap.read() if not ret: img = QImage("./images/network.png") self.updateFrame.emit(img) color_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = QImage(color_frame.data, color_frame.shape[1], color_frame.shape[0], QImage.Format_RGB888) self.updateFrame.emit(img) class ImageProvider(QQuickImageProvider): imageChanged = Signal(QImage) def __init__(self): super(ImageProvider, self).__init__(QQuickImageProvider.Image) self.cam = ThreadCamera() self.cam.updateFrame.connect(self.update_image) def requestImage(self, id, size, requestedSize): img = QImage(600, 500, QImage.Format_RGBA8888) img.fill(Qt.black) return img @Slot() def update_image(self, img): self.imageChanged.emit(img) @Slot() def start(self): print("Starting...") self.cam.start() @Slot() def killThread(self): print("Finishing...") try: self.cam.cap.release() cv2.destroyAllWindows() except: pass class MainWindow(QObject): def __init__(self): QObject.__init__(self) if __name__ == "__main__": app = QApplication(sys.argv) app.setWindowIcon(QIcon("./images/network.png")); engine = QQmlApplicationEngine() #Get Context main = MainWindow() myImageProvider = ImageProvider() engine.rootContext().setContextProperty("backend", main) engine.rootContext().setContextProperty("myImageProvider", myImageProvider) engine.addImageProvider("MyImageProvider", myImageProvider) #Load QML File engine.load(os.fspath(Path(__file__).resolve().parent / "test2.qml")) if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec())
main.qml
import QtQuick 2.15 import QtQuick.Window import QtMultimedia import QtQuick.Controls 6.3 import QtQuick.Layouts 6.3 import QtQuick.Dialogs Window { visible: true width: 600 height: 500 title: "WebCam" Image { id: feedImage width: parent.width height: parent.height - 50 fillMode: Image.PreserveAspectFit cache: false source: "image://MyImageProvider/img" property bool counter: false function reloadImage() { counter = !counter source = "image://MyImageProvider/img?id=" + counter } } RowLayout { anchors.top: feedImage.bottom anchors.horizontalCenter: feedImage.horizontalCenter Button { id: btnStartCamera text: "Start Camera" onClicked: { myImageProvider.start() } } Button { id: btnStopCamera text: "Stop Camera" onClicked: { myImageProvider.killThread() } } } Connections{ target: myImageProvider function onImageChanged(image) { console.log("emit") feedImage.reloadImage() } } }
更新后的实现(已成功显示视频流)
修改了ImageProvider类后,视频流可以正常显示,代码如下:
class ImageProvider(QQuickImageProvider): imageChanged = Signal(QImage) def __init__(self): super(ImageProvider, self).__init__(QQuickImageProvider.Image) self.cam = ThreadCamera() self.cam.updateFrame.connect(self.update_image) self.image = None def requestImage(self, id, size, requestedSize): if self.image: img = self.image else: img = QImage(600, 500, QImage.Format_RGBA8888) img.fill(Qt.black) return img @Slot() def update_image(self, img): self.imageChanged.emit(img) self.image = img @Slot() def start(self): print("Starting...") self.cam.start() @Slot() def killThread(self): print("Finishing...") try: self.cam.cap.release() cv2.destroyAllWindows() except: pass
但我不确定这种实现方式是否正确。
内容的提问来源于stack exchange,提问作者Francisco Massucci
相关产品推荐
相关产品推荐

