es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

QT creador python transmite video utilizando opencv.

Llevo algunos días trabajando en ello, buscando en línea en la documentación pero no he podido encontrar ningún ejemplo :/.

Quiero transmitir video en una página usando opencv. Estoy usando QtCreator y una aplicación QtQuick con archivos qml.

        MediaPlayer {
            id: mediaplayer
            source: "videoplayback.mp4"
        }

        VideoOutput {
            anchors.fill: parent
            source: mediaplayer
        }

        MouseArea {
            id: playArea
            anchors.fill: parent
            onPressed: mediaplayer.play();
        }

Lo que muestra esto:
enter image description here

Ahora puedo reproducir el video. Pero prefiero que la fuente provenga de mi archivo de backend main.py para que pueda trabajar en él.

El archivo main.py ahora es:
”’

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

        #QTimer
        self.timer = QTimer()
        self.timer.timeout.connect(lambda: self.setTime())
        self.timer.start(1000)

    def setTime(self):
        now = datetime.datetime.now()
        formatDate = now.strftime("Time: %H:%M:%S %p of %Y/%m/%d")
        #print(formatDate)
        self.printTime.emit(formatDate)


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

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

    engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml"))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

En el código anterior, básicamente esta línea:

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

Es la que se conecta con los archivos qml utilizando:

Connections{
    target: backend


    function onPrintTime(time){
        labelDate.text = time
    }

}

Así que en el contexto quiero mostrar video en mi página usando la fuente de opencv. Básicamente es una aplicación de sistema de vigilancia, así que quiero mostrar varias transmisiones, pero si alguien pudiera ayudarme con una sola desde la cámara web, cómo transmitirla al reproductor de medios estaré muy agradecido.

Nota: estoy trabajando con archivos qml dentro de la aplicación QT Creator. Hay varias formas de hacer esto con archivos de UI, pero eso no me ayuda :/

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para transmitir video en una página usando OpenCV en una aplicación QtQuick con archivos QML, se puede utilizar el siguiente código:

    import QtQuick 2.0
    import QtMultimedia 5.0
    import QtMultimediaWidgets 5.0
    
    Item {
        VideoOutput {
            id: videoOutput
            anchors.fill: parent
        }
    
        MediaPlayer {
            id: mediaPlayer
            videoOutput: videoOutput
    
            onStateChanged: {
                if (mediaPlayer.state === MediaPlayer.Loaded) {
                    mediaPlayer.play()
                }
            }
    
            Component.onCompleted: {
                mediaPlayer.source = "your_video_path_here"
            }
        }
    
        MouseArea {
            anchors.fill: parent
            onPressed: {
                mediaPlayer.playPause()
            }
        }
    }
    

    En este código, creamos un elemento VideoOutput para mostrar el video, un elemento MediaPlayer para controlar y reproducir el video, y un elemento MouseArea para activar/desactivar la reproducción al hacer clic.

    Para establecer la fuente de video dinámicamente desde el archivo main.py del backend, se puede agregar una propiedad a la clase MainWindow para mantener la ruta del video y actualizar la fuente del MediaPlayer con ella:

    class MainWindow(QObject):
        def __init__(self):
            QObject.__init__(self)
            self.videoPath = ""
    
            # ...
    
    if __name__ == "__main__":
        app = QGuiApplication(sys.argv)
        engine = QQmlApplicationEngine()
        main = MainWindow()
        main.videoPath = "your_video_path_here"
        engine.rootContext().setContextProperty("backend", main)
        engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml"))
    

    Luego, en el archivo QML, se puede vincular la fuente del MediaPlayer a la propiedad videoPath de MainWindow:

    MediaPlayer {
        id: mediaPlayer
        videoOutput: videoOutput
        source: backend.videoPath
    
        onStateChanged: {
            if (mediaPlayer.state === MediaPlayer.Loaded) {
                mediaPlayer.play()
            }
        }
    }
    

    Para capturar video desde una cámara web con OpenCV y mostrarlo en la página QtQuick, se puede usar la clase VideoCapture de OpenCV para capturar imágenes de la cámara y convertirlas en una imagen QImage de Qt utilizando cv2.cvtColor y QImage.fromData. Luego, se puede actualizar la fuente del MediaPlayer con una QUrl a un archivo de video temporal que contiene las imágenes capturadas.

    Aquí hay un ejemplo de clase MainWindow que captura imágenes de una cámara web y actualiza la fuente del MediaPlayer:

    import cv2
    import numpy as np
    from PySide2.QtCore import QObject, QUrl, QTimer, Signal
    from PySide2.QtGui import QImage, QPixmap
    from PySide2.QtMultimedia import QMediaPlayer, QMediaContent
    from PySide2.QtMultimediaWidgets import QVideoWidget
    
    class MainWindow(QObject):
        def __init__(self):
            QObject.__init__(self)
            self.timer = QTimer()
            self.timer.timeout.connect(lambda: self.captureVideo())
            self.timer.start(1000 // 30)
            self.capture = cv2.VideoCapture(0)
            self.videoPath = ""
    
        def captureVideo(self):
            ret, frame = self.capture.read()
            if ret:
                rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                height, width, channel = rgbImage.shape
                bytesPerLine = 3 * width
                qImage = QImage(rgbImage.data, width, height, bytesPerLine, QImage.Format_RGB888)
                self.updateVideo(qImage)
    
        def updateVideo(self, qImage):
            pixmap = QPixmap.fromImage(qImage)
            videoPath = "temp_video.mp4"
            codec = cv2.VideoWriter_fourcc(*"MP4V")
            fps = 30
            size = (qImage.width(), qImage.height())
            writer = cv2.VideoWriter(videoPath, codec, fps, size)
            frame = cv2.cvtColor(np.asarray(qImage), cv2.COLOR_RGB2BGR)
            writer.write(frame)
            writer.release()
            self.videoPath = QUrl.fromLocalFile(videoPath)
            self.updateMedia()
    
        def updateMedia(self):
            mediaPlayer = QMediaPlayer()
            mediaPlayer.setMedia(QMediaContent(self.videoPath))
            mediaPlayer.setVideoOutput(self.videoOutput)
            mediaPlayer.play()
    
        printTime = Signal(str)
    

    En esta clase MainWindow, utilizamos un QTimer para capturar imágenes desde la cámara web a 30 fps, convertirlas en una QImage y actualizar el video con el método updateVideo. Este método actualiza la fuente del MediaPlayer con una QUrl a un archivo temporal de video que contiene las imágenes capturadas.

    Luego, en el archivo QML, se puede usar el elemento MouseArea para activar el método updateMedia y reproducir el video en la página.

    Item {
        VideoOutput {
            id: videoOutput
            anchors.fill: parent
        }
    
        MouseArea {
            anchors.fill: parent
            onPressed: {
                backend.updateMedia()
            }
        }
    }
    

Comments are closed.