ВБ
Владимир Борисов15 апреля 2021 г. 20:31

Помогите переложить код QML OpenCV c PyQt5 на PySide2

Структура проекта
├── main.py
├── main.qml
└── PyCVQML
................├── cvcapture.py
................├── cvitem.py
................└── init .py


main.py

import os
import sys
import cv2
import numpy as np
from PyQt5 import QtGui, QtCore, QtQuick, QtQml
import PyCVQML


if __name__ == '__main__':

    app = QtGui.QGuiApplication(sys.argv)

    PyCVQML.registerTypes()
    QtQml.qmlRegisterType(PyCVQML.CVCapture, "Filters", 1, 0, "GrayFilter")

    view = QtQuick.QQuickView()
    view.setTitle("PyCVQML Example")
    dir_path = os.path.dirname(os.path.realpath(__file__))
    view.setSource(QtCore.QUrl.fromLocalFile(QtCore.QDir(dir_path).absoluteFilePath("main.qml")))
    view.show()
    sys.exit(app.exec_())

main.qml

import QtQuick 2.15
import PyCVQML 1.0
import Filters 1.0
import QtQuick.Controls 2.15

Item {
    width: 800
    height: 600

    CVItem  {
        id: imageWriter
        anchors.fill: parent
        image: capture.image
    }


    CVCapture{
        id: capture
        index: 0
        filters: [max_rgb_filter, gray_filter]
        Component.onCompleted: capture.start()
        }
}

PyCVQML/cvcapture.py

import numpy as np
import threading

import cv2

from PyQt5 import QtCore, QtGui, QtQml

gray_color_table = [QtGui.qRgb(i, i, i) for i in range(256)]


class CVAbstractFilter(QtCore.QObject):
    def process_image(self, src):
        dst = src
        return dst


class CVCapture(QtCore.QObject):
    started = QtCore.pyqtSignal()
    imageReady = QtCore.pyqtSignal()
    indexChanged = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(CVCapture, self).__init__(parent)
        self._image = QtGui.QImage()
        self._index = 0

        self.m_videoCapture = cv2.VideoCapture()
        self.m_timer = QtCore.QBasicTimer()
        self.m_filters = []
        self.m_busy = False

    @QtCore.pyqtSlot()
    @QtCore.pyqtSlot(int)
    def start(self, *args):
        if args:
            self.setIndex(args[0])
        self.m_videoCapture.release()
        self.m_videoCapture = cv2.VideoCapture(self._index)
        if self.m_videoCapture.isOpened():
            self.m_timer.start(0, self)
            self.started.emit()

    @QtCore.pyqtSlot()
    def stop(self):
        self.m_timer.stop()

    def timerEvent(self, e):
        if e.timerId() != self.m_timer.timerId():
            return
        ret, frame = self.m_videoCapture.read()
        if not ret:
            self.m_timer.stop()
            return
        if not self.m_busy:
            threading.Thread(target=self.process_image, args=(np.copy(frame),)).start()

    @QtCore.pyqtSlot(np.ndarray)
    def process_image(self, frame):
        self.m_busy = True
        for f in self.m_filters:
            frame = f.process_image(frame)
        image = CVCapture.ToQImage(frame)
        self.m_busy = False
        QtCore.QMetaObject.invokeMethod(self,
                                        "setImage",
                                        QtCore.Qt.QueuedConnection,
                                        QtCore.Q_ARG(QtGui.QImage, image))

    @staticmethod
    def ToQImage(im):
        if im is None:
            return QtGui.QImage()
        if im.dtype == np.uint8:
            if len(im.shape) == 2:
                qim = QtGui.QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QtGui.QImage.Format_Indexed8)
                qim.setColorTable(gray_color_table)
                return qim.copy()

            elif len(im.shape) == 3:
                if im.shape[2] == 3:
                    w, h, _ = im.shape
                    rgb_image = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
                    flip_image = cv2.flip(rgb_image, 1)
                    qim = QtGui.QImage(flip_image.data, h, w, QtGui.QImage.Format_RGB888)
                    return qim.copy()
        return QtGui.QImage()

    def image(self):
        return self._image

    @QtCore.pyqtSlot(QtGui.QImage)
    def setImage(self, image):
        if self._image == image:
            return
        self._image = image
        self.imageReady.emit()

    def index(self):
        return self._index

    def setIndex(self, index):
        if self._index == index:
            return
        self._index = index
        self.indexChanged.emit()

    @QtCore.pyqtProperty(QtQml.QQmlListProperty)
    def filters(self):
        return QtQml.QQmlListProperty(CVAbstractFilter, self, self.m_filters)




    image = QtCore.pyqtProperty(QtGui.QImage, fget=image, notify=imageReady)
    index = QtCore.pyqtProperty(int, fget=index, fset=setIndex, notify=indexChanged)

PyCVQML/cvitem.py

from PyQt5 import QtCore, QtGui, QtQuick


class CVItem(QtQuick.QQuickPaintedItem):
    imageChanged = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(CVItem, self).__init__(parent)
        ## self.setRenderTarget(QtQuick.QQuickPaintedItem.FramebufferObject)
        self.m_image = QtGui.QImage()

    def paint(self, painter):
        if self.m_image.isNull():
            return
        image = self.m_image.scaled(self.size().toSize())
        painter.drawImage(QtCore.QPoint(), image)

    def image(self):
        return self.m_image

    def setImage(self, image):
        if self.m_image == image:
            return
        self.m_image = image
        self.imageChanged.emit()
        self.update()

    image = QtCore.pyqtProperty(QtGui.QImage, fget=image, fset=setImage, notify=imageChanged)

PyCVQML/ init .py

from PyQt5 import QtQml

from .cvcapture import CVCapture, CVAbstractFilter
from .cvitem import CVItem


def registerTypes(uri="PyCVQML"):
    QtQml.qmlRegisterType(CVCapture, uri, 1, 0, "CVCapture")
    QtQml.qmlRegisterType(CVItem, uri, 1, 0, "CVItem")
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

0

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
г
  • ги
  • 23 апреля 2024 г. 15:51

C++ - Тест 005. Структуры и Классы

  • Результат:41баллов,
  • Очки рейтинга-8
l
  • laei
  • 23 апреля 2024 г. 9:19

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:10баллов,
  • Очки рейтинга-10
l
  • laei
  • 23 апреля 2024 г. 9:17

C++ - Тест 003. Условия и циклы

  • Результат:50баллов,
  • Очки рейтинга-4
Последние комментарии
k
kmssr8 февраля 2024 г. 18:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко5 февраля 2024 г. 1:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 10:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 8:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik18 декабря 2023 г. 21:01
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
G
Gar22 апреля 2024 г. 5:46
Clipboard Как скопировать окно целиком в clipb?
DA
Dr Gangil Academics20 апреля 2024 г. 7:45
Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
a
a_vlasov14 апреля 2024 г. 6:41
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел Дорофеев14 апреля 2024 г. 2:35
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrex4 апреля 2024 г. 4:47
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

Следите за нами в социальных сетях