簡體   English   中英

如何在 Qml 應用程序中顯示 Opencv 攝像頭饋送?

[英]How to show Opencv camera feed in a Qml application?

我正在嘗試在 Qml 應用程序中顯示 opencv 處理的攝像頭饋送和 Image 對象。

提要頁面是一個單獨的頁面,在按下按鈕時使用 Loader 對象加載到主頁,提要頁面默認為非活動狀態。

這是我正在使用的代碼:

主文件

from PyQt5.QtGui import QGuiApplication, QImage
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtCore import Qt, QObject, pyqtSignal, pyqtSlot, QTimer, QUrl, QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickImageProvider, QQuickView


class CamFeedWorker(QThread):
    image_update = pyqtSignal(QImage)

    def __init__(self):
        super(CamFeedWorker, self).__init__()
        self.processor = FieldProcessor()  # Just gets the camera frame and does some processing
        self.thread_active = True


    def run(self):
        self.thread_active = True
        self.processor.init_cap()

        while self.thread_active:
            img = self.processor.frame_capture()
            qt_img = QImage(img.data,
                            img.shape[1],
                            img.shape[0],
                            QImage.Format_RGB888
                            )
            self.image_update.emit(qt_img)

    def stop(self):
        self.thread_active = False
        sleep(0.2)
        self.processor.cap.release()
        self.quit()


class ImageProvider(QQuickImageProvider):
    imageChanged = pyqtSignal(QImage)

    def __init__(self):
        super(ImageProvider, self).__init__(QQuickImageProvider.Image)

        self.cam = CamFeedWorker() 
        self.cam.image_update.connect(self.update_image)

    def requestImage(self, id, requestedSize):
        print("id: ", id)
        print("requested size: ", requestedSize)
        img = QImage(300, 300, QImage.Format_RGBA8888)
        img.fill(Qt.black)
        img = QImage("qml/pages/test.png")
        return img, img.size()

    def update_image(self, img):
        self.imageChanged.emit(img)

class MainWindow(QObject):
    def __init__(self):
        QObject.__init__(self)
        ...


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

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

    # Image provider setup for camera feed:
    engine.addImageProvider("MyImageProvider", ImageProvider())
    engine.load(QUrl.fromLocalFile("qml/pages/FieldProcessingPage.qml"))

    # Loading qml file
    engine.load(os.fspath(Path(__file__).resolve().parent / "./qml/main.qml"))

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

main.qml

一個普通頁面,每個子頁面都有加載器,還有用於激活和查看頁面以及停用其余頁面的按鈕。

FieldProcessingPage.qml

import QtQuick 2.15
import QtQuick.Controls 2.15

Item {
    id: fieldProcessingPage

    Rectangle {
        id: pageRectangle
        anchors.fill: parent
        implicitWidth: 800
        implicitHeight: 600

        Rectangle {
            id: contentRectangle
            anchors.fill: parent

            Image {
                id: feedImage
                anchors.fill: parent
                fillMode: Image.PreserveAspectFit
                cache: false
                source: "image://MyImageProvider/img"
                property bool counter: false

                function reloadImage() {
                    counter = !counter
                    source = "image://MyImageProvider/img?id=" + counter
                }
            }
        }
    }

    Connections {
        target: myImageProvider

        function onImageChanged(image) {
            feedImage.reloadImage()
        }
    }
}

運行代碼時收到以下錯誤消息:

file:qml/pages/FieldProcessingPage.qml:43:5: QML Connections: Detected function "onImageChanged" in Connections element. This is probably intended to be a signal handler but no signal of the target matches the name.
file:qml/pages/FieldProcessingPage.qml:26:13: QML Image: Failed to get image from provider: image://myimageprovider/img
file:FieldProcessingPage.qml:44: ReferenceError: myImageProvider is not defined

我實際上沒有在 python 中找到關於在 qml 上從 opencv 運行攝像頭提要的示例,所以我需要幫助才能運行它,謝謝。

首先,謝謝我發現你的代碼對我的用例很有用,因為所有類似的解決方案都是 C++。

我認為問題在於FieldProcessingPage.qml中的目標連接是針對類而不是在渲染時默認實例化的類對象。

一種解決方法是創建類ImageProvider的對象,並為屬性上下文以及默認的 QQuickImageProvider 引用它。

主文件

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

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

    # Image provider setup for camera feed:
    engine.addImageProvider("MyImageProvider", myImageProvider)
    engine.load(QUrl.fromLocalFile("qml/pages/FieldProcessingPage.qml"))

    # Loading qml file
    engine.load(os.fspath(Path(__file__).resolve().parent / "./qml/main.qml"))

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM