qml_puthon_user
qml_puthon_userЖел. 6, 2019, 7:10 Т.Ж.

подружить qml и opencv

OpenCV, qml, Python 3, QML

Доброго времени суток.
Пытаюсь сделать отображение с веб-камеры в графическом интерфейсе написанном на qml.
Код программы:

#системные библиотеки
import cv2
import numpy as np
import sys
import threading

#PyQt библиотеки
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtQml import *
from PyQt5.QtQuick import *


class MyImageProvider(QQuickImageProvider):
    def __init__(self):
        super(MyImageProvider, self).__init__(QQuickImageProvider.Image)

    def requestImage(self, p_str, size):
        cap = cv2.VideoCapture(0)
        while True:
            ret, frame = cap.read()
            #image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            height, width, channel = frame.shape
            #step = channel * width
            img = QImage(frame, width, height, QImage.Format_RGB888)
            #img.fill(Qt.green)
            return img, img.size()
            cv2.waitKey(1)

if __name__ == '__main__':
    app = QGuiApplication(sys.argv)
    MyImageProvider()
    engine = QQmlApplicationEngine()
    engine.addImageProvider("myprovider", MyImageProvider())
    engine.load(QUrl.fromLocalFile("tst.qml"))
    if len(engine.rootObjects()) == -1:
        sys.exit(-1)
    sys.exit(app.exec_())

Вот код формы:

import QtQuick 2.12
import QtQuick.Window 2.12

Window{
    visible: true
    width: 800
    height: 600
    title: ("QML OPENCV")
    color: "green"
    Image
    {
         //anchors.fill : parent
         source: "image://myprovider/test.png"
    }
}

Читал статью про слоты и сигналы в python , но пока не могу сообразить, как это всё складывается воедино.
Представленный код отображает окно с веб-камерой и окно qml интерфейста.

Есть на C++ образец... Я в нём не силён, подсобите перевести на python3. :)
Утечка памяти (OpenCV + QML)

Нашёл пример с изображением:
QQuickImageProvider PyQt5
С помощью этого примера почти получилось добиться желаемого результата. Получается, что отображается только последний снятый кадр веб-камерой, а не поток. Есть идеи, как сделать поток из кадров в форму qml?

Спасибо!

Вот такой набросок пока что получился.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

21
Evgenii Legotckoi
  • Жел. 9, 2019, 3:21 Т.Ж.

Добрый день.
Да... OpenCV, конечно, интересная тема. Но вот я от неё далёк.
QQuickImageProvider использутеся для предоставления изображений, но точно не для потока этих самых изображений. В каком-то смысле все те примеры выглядят как костыли, поскольку QQuickImageProvider используется не по своему прямому назначению. Но тем не менее это должно работать.

Обратите своё внимание на то, что в примере с утечкой памяти имеется сигнал, который сообщает об изменении изображения на каждый новый кадр. Вам нужно сделать тоже самое. Вам нуэно использовать сигналы и слоты для этого. Не помню, вы уже кажется смотрели ту статью по сигналам и слотам PyQt5 - Урок 007. Работаем с QML QtQuick (Сигналы и слоты)

    qml_puthon_user
    • Жел. 9, 2019, 3:27 Т.Ж.

    Добрый.
    Да, я пытался связаться через сигналы и слоты, но у меня не выходит перевести программу с плюсов на питон. Если не затруднит помочь в переводе, то есть вероятность, что получится написать конечный результат. :)

      Evgenii Legotckoi
      • Жел. 9, 2019, 3:45 Т.Ж.

      Думаю, что в QQuickImageProvider следует добавить сигнал, что-то вроде такого

      class MyImageProvider(QQuickImageProvider):
          frameChanged = pyqtSignal()
      

      А потом как минимум подключить к этому сигналу обработчик в QML и посмотреть, сыпется ли что-то нибудь в консоль QML

      Window
      {
          visible: true
          width: 640
          height: 480
          title: ("QML OPENCV")
          color: "green"
          id: root
      
          // ...
      
          Connections
          {
              target: myprovider
              property int frameCounter: 0
      
              onFrameChanged:
              {
                  frameCounter ^= 1;
                  console.log(frameCounter); // проверяем здесь изменение счётчика
              }
          }
      }
      

      Тогда уже можно будет пытаться сообразить что-нибудь дальше

        qml_puthon_user
        • Жел. 9, 2019, 4:06 Т.Ж.

        А через "console.log" Вы куда выводите сообщения? В PyCharm? Я работаю в основном в стандартной IDLE Python. Такое не срабатывает в стандартной IDLE. PyCharm у меня стоит.

          Evgenii Legotckoi
          • Жел. 9, 2019, 4:12 Т.Ж.

          вообще - это тоже должно сыпаться в консоль и без разницы, какую IDE использовать. К IDE это не должно иметь никакого отношения. Если вывода нет, то скорее всего не работает.

          А да, ещё этот сигнал нужно вызывать

          class MyImageProvider(QQuickImageProvider):
              frameChanged = pyqtSignal()
          
              def __init__(self):
                  super(MyImageProvider, self).__init__(QQuickImageProvider.Image)
          
              def requestImage(self, p_str, size):
                  cap = cv2.VideoCapture(0)
                  while True:
                      ret, frame = cap.read()
                      #image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                      height, width, channel = frame.shape
                      #step = channel * width
                      img = QImage(frame, width, height, QImage.Format_RGB888)
                      #img.fill(Qt.green)
                      self.frameChanged.emit() # вызвать сигнал
                      return img, img.size() # а вот из-за этого у вас выполняется выход из функции, 
                      cv2.waitKey(1) # до выполнения этого кода метод никогда не доходит
          

          И кстати сам запрос изображения у вас как-то странно написан

            qml_puthon_user
            • Жел. 9, 2019, 4:18 Т.Ж.

            Вы сейчас разбираете некий костыль, посоветовали с сигналами и слотами поработать, вот и хочу с ними разобраться, если так имеет место быть более правильное решение.) Я могу по-новому написать, чтобы было понятнее работать.

              Evgenii Legotckoi
              • Жел. 9, 2019, 4:21 Т.Ж.

              что предоставлено, с тем и работаю. не писать же мне с нуля ваш проект ))

                qml_puthon_user
                • Жел. 9, 2019, 4:33 Т.Ж.
                • (өңделген)

                Это понятное дело.)
                Я сделал вот так, чтобы проверить, работает ли счётчик.
                Код программы:

                # системные библиотеки
                import cv2
                import numpy as np
                import sys
                import threading
                
                # PyQt библиотеки
                from PyQt5.QtCore import *
                from PyQt5.QtGui import *
                from PyQt5.QtQml import *
                from PyQt5.QtQuick import *
                
                
                class MyImageProvider(QQuickImageProvider):
                    def __init__(self):
                        super(MyImageProvider, self).__init__(QQuickImageProvider.Image)
                
                    frameChanged = pyqtSignal()
                
                    def reauestSignal(self):
                
                        self.frameChanged.emit()    #вызываю сигнал
                
                if __name__ == '__main__':
                
                    # создаём экземпляр приложения
                    app = QGuiApplication(sys.argv)
                    # создаём QML движок
                    engine = QQmlApplicationEngine()
                    # создаём объект vision
                    videoProvider = MyImageProvider()
                    # и регистрируем его в контексте QML
                    engine.rootContext().setContextProperty("myprovider", videoProvider)
                    #engine.addImageProvider("myprovider", videoProvider)
                    # загружаем файл qml в движок
                    engine.load("test.qml")
                
                    engine.quit.connect(app.quit)
                    sys.exit(app.exec_())
                

                Код формы:

                import QtQuick 2.12
                import QtQuick.Window 2.12
                import QtQuick.Controls 2.12
                
                Window
                {
                    visible: true
                    width: 640
                    height: 480
                    title: ("QML OPENCV")
                    color: "green"
                    id: root
                
                    // ...
                
                    TextArea 
                    {
                        id: debug_area
                        x: 183
                        y: 361
                        width: 275
                        height: 145
                        text: qsTr("Debug\n")
                        selectByMouse: true
                    }
                
                    Connections
                    {
                        target: myprovider
                        property int frameCounter: 0
                
                        onFrameChanged:
                        {
                            frameCounter ^= 1;
                            debug_area.text += frameCounter; // проверяем здесь изменение счётчика
                        }
                    }
                }
                

                Не хочет работать.

                  qml_puthon_user
                  • Жел. 9, 2019, 7:16 Т.Ж.

                  Я сделал простой вывод текста по испусканию сигнала...
                  Чего не хватает программе?)
                  Python:

                  # системные библиотеки
                  import cv2
                  import numpy as np
                  import sys
                  import threading
                  
                  # PyQt библиотеки
                  from PyQt5.QtCore import *
                  from PyQt5.QtGui import *
                  from PyQt5.QtQml import *
                  from PyQt5.QtQuick import *
                  
                  
                  class MyImageProvider(QObject):
                      def __init__(self):
                          QObject.__init__(self)
                  
                      frameChanged = pyqtSignal()
                  
                  
                  if __name__ == '__main__':
                  
                      # создаём экземпляр приложения
                      app = QGuiApplication(sys.argv)
                      # создаём QML движок
                      engine = QQmlApplicationEngine()
                      # создаём объект vision
                      videoProvider = MyImageProvider()
                      # и регистрируем его в контексте QML
                      engine.rootContext().setContextProperty("myprovider", videoProvider)
                      #engine.addImageProvider("myprovider", videoProvider)
                      # загружаем файл qml в движок
                      engine.load("test.qml")
                  
                      engine.quit.connect(app.quit)
                      sys.exit(app.exec_())
                  
                  

                  QML:

                  import QtQuick 2.12
                  import QtQuick.Window 2.12
                  import QtQuick.Controls 2.12
                  
                  Window
                  {
                      visible: true
                      width: 640
                      height: 480
                      title: ("QML OPENCV")
                      color: "green"
                      id: root
                  
                      //здесь увидим информацию
                      TextArea 
                      {
                          id: debug_area
                          x: 183
                          y: 10
                          width: 200
                          height: 400
                          text: qsTr("Debug\n")
                          selectByMouse: true
                      }
                      Button
                      {
                          x: 10
                          y: 10
                          width: 100
                          height: 50
                          text: qsTr("Debug Btn")
                          onClicked:
                          {
                              debug_area.text += "BTN is WORK\n"
                          }
                      }
                      Connections
                      {
                          target: myprovider
                          property int frameCounter: 0
                  
                          onFrameChanged:
                          {
                              debug_area.text = "Signal is work"
                              //frameCounter += 1;
                              //debug_area.text = frameCounter; // проверяем здесь изменение счётчика
                          }
                      }
                  }
                  
                    qml_puthon_user
                    • Жел. 12, 2019, 11:05 Т.Ж.

                    Есть на qml что-то типа window.onload? Чтобы при загрузке формы срабатывал сигнал. По нажатию кнопки всё прекрасно работает... А вот при загрузке формы нет...

                      qml_puthon_user
                      • Жел. 12, 2019, 11:49 Т.Ж.

                      Да, с console.log() я разобрался, счётчик ничего не показывает

                        Evgenii Legotckoi
                        • Жел. 13, 2019, 3:42 Т.Ж.

                        У всех компонентов есть встраиваемый обработчик Component.onCompleted, который выполняется, когда объект полностью создан

                        Window {
                            Component.onCompleted: {
                                console.log("Window Completed Running!")
                            }
                        }
                        
                          Evgenii Legotckoi
                          • Жел. 13, 2019, 3:43 Т.Ж.

                          Наверное сигнал всё-таки не вызывается правильно

                            qml_puthon_user
                            • Жел. 13, 2019, 3:53 Т.Ж.

                            А не подскажете, как вызвать правильно? :)

                              qml_puthon_user
                              • Жел. 16, 2019, 7:42 Т.Ж.
                              • (өңделген)

                              Сделал вот такой вариант и он работает, только мне непонятно, почему в консоли пишется undefined...
                              Форма:

                              import QtQuick 2.12
                              import QtQuick.Window 2.12
                              import QtQuick.Controls 2.12
                              
                              Window
                              {
                                  visible: true
                                  width: 640
                                  height: 480
                                  title: ("QML OPENCV")
                                  color: "green"
                                  id: root
                              
                                  Component.onCompleted:
                                  {
                                      console.log("onload")
                                      console.log(myprovider.say())
                                  }
                              
                                  Connections
                                  {
                                      target: myprovider
                              
                                      /*onFrameChanged:
                                      {   
                                      }*/
                                  }
                              }
                              

                              Скрипт:

                              # системные библиотеки
                              import cv2
                              import numpy as np
                              import sys
                              import threading
                              
                              # PyQt библиотеки
                              from PyQt5.QtCore import *
                              from PyQt5.QtGui import *
                              from PyQt5.QtQml import *
                              from PyQt5.QtQuick import *
                              
                              
                              class MyImageProvider(QObject):
                              
                                  def __init__(self):
                                      QObject.__init__(self)
                              
                                  #frameChanged = pyqtSignal()
                              
                                  @pyqtSlot()
                                  def say(self):
                                      print("blablabla")
                              
                              if __name__ == '__main__':
                              
                                  # создаём экземпляр приложения
                                  app = QGuiApplication(sys.argv)
                                  # создаём QML движок
                                  engine = QQmlApplicationEngine()
                                  # создаём объект vision
                                  videoProvider = MyImageProvider()
                                  # и регистрируем его в контексте QML
                                  engine.rootContext().setContextProperty("myprovider", videoProvider)
                                  #engine.addImageProvider("myprovider", videoProvider)
                                  # загружаем файл qml в движок
                                  engine.load("test.qml")
                              
                                  engine.quit.connect(app.quit)
                                  sys.exit(app.exec_())
                              
                              

                                Evgenii Legotckoi
                                • Жел. 17, 2019, 2:40 Т.Ж.

                                undefined пишет потому, что метод сам по себе ничего не возвращает, то есть void, напишите так

                                Component.onCompleted:
                                {
                                    console.log("onload")
                                    console.log(myprovider)
                                }
                                
                                  qml_puthon_user
                                  • Жел. 17, 2019, 3:07 Т.Ж.

                                  Вернул код инструкции, если я правильно понял.

                                    Evgenii Legotckoi
                                    • Жел. 17, 2019, 3:10 Т.Ж.

                                    Вернулся указатель на ваш объект. Ну слот срабатывает. Вам теперь нужно дальше развить вашу задачу. У меня к сожалению нет времени разбираться с opencv, поэтому не могу ответить на некоторые вопросы.

                                      qml_puthon_user
                                      • Жел. 17, 2019, 3:16 Т.Ж.

                                      С opencv я разберусь. :) У меня пока только вопросы по сигналам и слотам.)

                                        Михаиллл
                                        • Жел. 28, 2019, 8:46 Т.Ж.
                                        • (өңделген)

                                        На сколько мне известно в opencv с камеры подпются картинки через определенное время и так выходит видео. По идее можно по получении этой картинки передавать ее в qml. Прикрепить сигнал к получению картинки или таймеру и так подовать сигнал в qml об необходимости обновления.

                                          qml_puthon_user
                                          • Жел. 28, 2019, 9:28 Т.Ж.

                                          Если смотреть глубже, то там подаётся массив байтов(bytes в питоне). Ну, а по простому, то да. Я пока не разобрался как переменную передавать в qml форму. В этой самой переменной, пускай будет frame, как раз хранится поток с веб-камеры. Как только я передам её на форму, то по идее, элемент в котором будет "отображаться" данная переменная, нужно же перерисовывать, чтобы кадры обновлялись.

                                            Пікірлер

                                            Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
                                            Кіріңіз немесе Тіркеліңіз
                                            AD

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

                                            • Нәтиже:50ұпай,
                                            • Бағалау ұпайлары-4
                                            m
                                            • molni99
                                            • Қаз. 26, 2024, 1:37 Т.Ж.

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

                                            • Нәтиже:80ұпай,
                                            • Бағалау ұпайлары4
                                            m
                                            • molni99
                                            • Қаз. 26, 2024, 1:29 Т.Ж.

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

                                            • Нәтиже:20ұпай,
                                            • Бағалау ұпайлары-10
                                            Соңғы пікірлер
                                            ИМ
                                            Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
                                            Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                            Evgenii Legotckoi
                                            Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
                                            Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                            A
                                            ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
                                            Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                            ИМ
                                            Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
                                            Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                            d
                                            dblas5Шілде 5, 2024, 11:02 Т.Ж.
                                            QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                            Енді форумда талқылаңыз
                                            m
                                            moogoҚар. 22, 2024, 7:17 Т.Ж.
                                            Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
                                            Evgenii Legotckoi
                                            Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
                                            добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                            t
                                            tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
                                            google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                                            NSProject
                                            NSProjectМаусым 4, 2022, 3:49 Т.Ж.
                                            Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

                                            Бізді әлеуметтік желілерде бақылаңыз