如何在 Qml 应用程序中显示 Opencv 相机源?

问题描述 投票:0回答:2

我正在尝试在 Qml 应用程序中显示 opencv 处理过的相机源和图像对象。

提要页面是按下按钮时使用 Loader 对象加载到主页面的单独页面,默认情况下提要页面处于非活动状态。

这是我正在使用的代码:

main.py

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 的相机源的示例,所以我需要帮助来运行它,谢谢。

python qt opencv qml qtquick2
2个回答
0
投票

首先,谢谢,我发现您的代码对我的用例很有用,因为所有类似的解决方案都是 C++。

我认为问题在于

FieldProcessingPage.qml
中的目标连接是针对类而不是渲染时默认实例化的类对象。

解决方法是创建

ImageProvider
类的对象并引用它的属性上下文以及默认的 QQuickImageProvider。

main.py

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_())

0
投票

这些代码对我帮助很大,如下所示。我使用 QML 编写一个 GUI,其输入可以是相机、视频或图像目录。我可以成功运行它,所以我认为这可能对某人有帮助,我在下面的链接中发布了我的代码。

https://stackoverflow.com/a/78825215/17601704

结果

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.