ВБ
April 16, 2021, 6:31 a.m.

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

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


main.py

  1. import os
  2. import sys
  3. import cv2
  4. import numpy as np
  5. from PyQt5 import QtGui, QtCore, QtQuick, QtQml
  6. import PyCVQML
  7.  
  8.  
  9. if __name__ == '__main__':
  10.  
  11. app = QtGui.QGuiApplication(sys.argv)
  12.  
  13. PyCVQML.registerTypes()
  14. QtQml.qmlRegisterType(PyCVQML.CVCapture, "Filters", 1, 0, "GrayFilter")
  15.  
  16. view = QtQuick.QQuickView()
  17. view.setTitle("PyCVQML Example")
  18. dir_path = os.path.dirname(os.path.realpath(__file__))
  19. view.setSource(QtCore.QUrl.fromLocalFile(QtCore.QDir(dir_path).absoluteFilePath("main.qml")))
  20. view.show()
  21. sys.exit(app.exec_())

main.qml

  1. import QtQuick 2.15
  2. import PyCVQML 1.0
  3. import Filters 1.0
  4. import QtQuick.Controls 2.15
  5.  
  6. Item {
  7. width: 800
  8. height: 600
  9.  
  10. CVItem {
  11. id: imageWriter
  12. anchors.fill: parent
  13. image: capture.image
  14. }
  15.  
  16.  
  17. CVCapture{
  18. id: capture
  19. index: 0
  20. filters: [max_rgb_filter, gray_filter]
  21. Component.onCompleted: capture.start()
  22. }
  23. }

PyCVQML/cvcapture.py

  1. import numpy as np
  2. import threading
  3.  
  4. import cv2
  5.  
  6. from PyQt5 import QtCore, QtGui, QtQml
  7.  
  8. gray_color_table = [QtGui.qRgb(i, i, i) for i in range(256)]
  9.  
  10.  
  11. class CVAbstractFilter(QtCore.QObject):
  12. def process_image(self, src):
  13. dst = src
  14. return dst
  15.  
  16.  
  17. class CVCapture(QtCore.QObject):
  18. started = QtCore.pyqtSignal()
  19. imageReady = QtCore.pyqtSignal()
  20. indexChanged = QtCore.pyqtSignal()
  21.  
  22. def __init__(self, parent=None):
  23. super(CVCapture, self).__init__(parent)
  24. self._image = QtGui.QImage()
  25. self._index = 0
  26.  
  27. self.m_videoCapture = cv2.VideoCapture()
  28. self.m_timer = QtCore.QBasicTimer()
  29. self.m_filters = []
  30. self.m_busy = False
  31.  
  32. @QtCore.pyqtSlot()
  33. @QtCore.pyqtSlot(int)
  34. def start(self, *args):
  35. if args:
  36. self.setIndex(args[0])
  37. self.m_videoCapture.release()
  38. self.m_videoCapture = cv2.VideoCapture(self._index)
  39. if self.m_videoCapture.isOpened():
  40. self.m_timer.start(0, self)
  41. self.started.emit()
  42.  
  43. @QtCore.pyqtSlot()
  44. def stop(self):
  45. self.m_timer.stop()
  46.  
  47. def timerEvent(self, e):
  48. if e.timerId() != self.m_timer.timerId():
  49. return
  50. ret, frame = self.m_videoCapture.read()
  51. if not ret:
  52. self.m_timer.stop()
  53. return
  54. if not self.m_busy:
  55. threading.Thread(target=self.process_image, args=(np.copy(frame),)).start()
  56.  
  57. @QtCore.pyqtSlot(np.ndarray)
  58. def process_image(self, frame):
  59. self.m_busy = True
  60. for f in self.m_filters:
  61. frame = f.process_image(frame)
  62. image = CVCapture.ToQImage(frame)
  63. self.m_busy = False
  64. QtCore.QMetaObject.invokeMethod(self,
  65. "setImage",
  66. QtCore.Qt.QueuedConnection,
  67. QtCore.Q_ARG(QtGui.QImage, image))
  68.  
  69. @staticmethod
  70. def ToQImage(im):
  71. if im is None:
  72. return QtGui.QImage()
  73. if im.dtype == np.uint8:
  74. if len(im.shape) == 2:
  75. qim = QtGui.QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QtGui.QImage.Format_Indexed8)
  76. qim.setColorTable(gray_color_table)
  77. return qim.copy()
  78.  
  79. elif len(im.shape) == 3:
  80. if im.shape[2] == 3:
  81. w, h, _ = im.shape
  82. rgb_image = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
  83. flip_image = cv2.flip(rgb_image, 1)
  84. qim = QtGui.QImage(flip_image.data, h, w, QtGui.QImage.Format_RGB888)
  85. return qim.copy()
  86. return QtGui.QImage()
  87.  
  88. def image(self):
  89. return self._image
  90.  
  91. @QtCore.pyqtSlot(QtGui.QImage)
  92. def setImage(self, image):
  93. if self._image == image:
  94. return
  95. self._image = image
  96. self.imageReady.emit()
  97.  
  98. def index(self):
  99. return self._index
  100.  
  101. def setIndex(self, index):
  102. if self._index == index:
  103. return
  104. self._index = index
  105. self.indexChanged.emit()
  106.  
  107. @QtCore.pyqtProperty(QtQml.QQmlListProperty)
  108. def filters(self):
  109. return QtQml.QQmlListProperty(CVAbstractFilter, self, self.m_filters)
  110.  
  111.  
  112.  
  113.  
  114. image = QtCore.pyqtProperty(QtGui.QImage, fget=image, notify=imageReady)
  115. index = QtCore.pyqtProperty(int, fget=index, fset=setIndex, notify=indexChanged)

PyCVQML/cvitem.py

  1. from PyQt5 import QtCore, QtGui, QtQuick
  2.  
  3.  
  4. class CVItem(QtQuick.QQuickPaintedItem):
  5. imageChanged = QtCore.pyqtSignal()
  6.  
  7. def __init__(self, parent=None):
  8. super(CVItem, self).__init__(parent)
  9. ## self.setRenderTarget(QtQuick.QQuickPaintedItem.FramebufferObject)
  10. self.m_image = QtGui.QImage()
  11.  
  12. def paint(self, painter):
  13. if self.m_image.isNull():
  14. return
  15. image = self.m_image.scaled(self.size().toSize())
  16. painter.drawImage(QtCore.QPoint(), image)
  17.  
  18. def image(self):
  19. return self.m_image
  20.  
  21. def setImage(self, image):
  22. if self.m_image == image:
  23. return
  24. self.m_image = image
  25. self.imageChanged.emit()
  26. self.update()
  27.  
  28. image = QtCore.pyqtProperty(QtGui.QImage, fget=image, fset=setImage, notify=imageChanged)

PyCVQML/ init .py

  1. from PyQt5 import QtQml
  2.  
  3. from .cvcapture import CVCapture, CVAbstractFilter
  4. from .cvitem import CVItem
  5.  
  6.  
  7. def registerTypes(uri="PyCVQML"):
  8. QtQml.qmlRegisterType(CVCapture, uri, 1, 0, "CVCapture")
  9. QtQml.qmlRegisterType(CVItem, uri, 1, 0, "CVItem")
1

Do you like it? Share on social networks!

0

Comments

Only authorized users can post comments.
Please, Log in or Sign up
  • Last comments
  • AK
    April 1, 2025, 11:41 a.m.
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    March 9, 2025, 9:02 p.m.
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    March 9, 2025, 4:14 p.m.
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
  • ИМ
    Nov. 22, 2024, 9:51 p.m.
    Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
  • Evgenii Legotckoi
    Oct. 31, 2024, 11:37 p.m.
    Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup