Video player using qml ,opencv and pyside2
I have a video stream that I want to display as simply as possible (no audio, just a sequence of frames ). my question is how to dynamically pass the emitted image to requestImage, assigning a new image every frame?
Here is the code I'm using:
main.py
import cv2
import sys
from PySide2 import QtCore
from PySide2 import QtQuick
from PySide2.QtGui import QImage, QPixmap
from PySide2.QtWidgets import QApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QThread, Signal, Slot, QUrl
class VideoThread(QThread):
changePixmapSignal = Signal(QPixmap)
def __init__(self):
QThread.__init__(self)
self.capturing = True
self.video_capture = cv2.VideoCapture("video1.mp4")
self.video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
self.video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
@Slot()
def startCapture(self):
if not self.capturing:
self.capturing = True
self.start()
@Slot()
def stopCapture(self):
if self.capturing:
self.capturing = False
self.video_capture.release()
self.quit()
def run(self):
while self.capturing:
_, frame = self.video_capture.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
pixmap = QPixmap.fromImage(image)
self.changePixmapSignal.emit(pixmap)
def qt_message_handler(mode, context, message):
if mode == QtCore.QtInfoMsg:
mode = 'Info'
elif mode == QtCore.QtWarningMsg:
mode = 'Warning'
elif mode == QtCore.QtCriticalMsg:
mode = 'critical'
elif mode == QtCore.QtFatalMsg:
mode = 'fatal'
else:
mode = 'Debug'
print("%s: %s (%s:%d, %s)" % (mode, message, context.file, context.line, context.file))
if __name__ == "__main__":
QtCore.qInstallMessageHandler(qt_message_handler)
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
# Expose the Camera class to QML
context = engine.rootContext()
video_thread = VideoThread()
context.setContextProperty("videoThread", video_thread)
qml_file = QUrl.fromLocalFile("mainview.qml")
engine.load(qml_file)
screen = engine.rootObjects()[0]
print(screen)
print(screen.findChild(QtQuick.QQuickItem, "videoFrame"))
video_thread.changePixmapSignal.connect(screen.findChild(QtQuick.QQuickItem, "videoFrame").updateFrame)
sys.exit(app.exec_())
mainview.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 640
height: 480
Image {
id: videoFrame
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
// This is the slot that updates the image source
function updateFrame(pixmap) {
videoFrame.source = pixmap
}
}
}
When I run this program I get this error :
video_thread.changePixmapSignal.connect(screen.findChild(QtQuick.QQuickItem, "videoFrame").updateFrame)
AttributeError: 'NoneType' object has no attribute 'updateFrame'
Comments
Post a Comment