Как запустить видео в контейнере PyQt?
В контейнере QVideoWidget на PyQt5 нужно запустить видео с компа, на котором должны искаться объекты через TensorFlow (openCV,cv2).
Проблема в том, что при нажатии кнопки видео показывает только один кадр и больше ничего.
В чем может быть проблема? Делал в PyCharm, Python 3.7.
from PyQt5 import QtCore, QtGui, QtWidgets, uiс
import os
import cv2
import numpy as np
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QLabel, QVBoxLayout
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtGui import QImage, QPixmap
class ThreadOpenCV(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, source):
super().__init__()
def run(self):
# MODEL_NAME = 'inference_graph'
VIDEO_NAME = '20201024161726.mp4'
#
# # Grab path to current working directory
CWD_PATH = os.getcwd()
PATH_TO_VIDEO = os.path.join(CWD_PATH, VIDEO_NAME)
cap = cv2.VideoCapture(PATH_TO_VIDEO)
while True:
ret, frame = cap.read()
if ret:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame_expanded = np.expand_dims(frame_rgb, axis=0)
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgbImage.shape
bytesPerLine = ch * w
convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
self.changePixmap.emit(p)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
class Widget(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi('fire_detection.ui', self)
self.show()
self.label_video = QLabel()
layout = QVBoxLayout()
layout.addWidget(self.label_video)
self.widget.setLayout(layout)
self.thread = ThreadOpenCV('20201024161726.mp4')
self.thread.changePixmap.connect(self.setImage)
self.btn1.clicked.connect(self.playVideo)
def playVideo(self):
self.thread.start()
def setImage(self, image):
self.label_video.setPixmap(QPixmap.fromImage(image))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
mw = Widget()
mw.show()
sys.exit(app.exec_())
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
cap.release() - Закрывает видеофайл или записывающее устройство.
import sys
import os
import cv2
import numpy as np
from PyQt5 import QtCore, QtGui, QtWidgets #, uiс
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QLabel, QVBoxLayout, QPushButton, QWidget
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtGui import QImage, QPixmap
class ThreadOpenCV(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, source):
super().__init__()
self.source = source
def run(self):
# VIDEO_NAME = '20201024161726.mp4'
CWD_PATH = os.getcwd()
PATH_TO_VIDEO = os.path.join(CWD_PATH, self.source) # VIDEO_NAME)
cap = cv2.VideoCapture(PATH_TO_VIDEO)
while True:
ret, frame = cap.read()
if ret:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame_expanded = np.expand_dims(frame_rgb, axis=0) # ? frame_expanded
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgbImage.shape
bytesPerLine = ch * w
convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
self.changePixmap.emit(p)
if cv2.waitKey(1) == ord('q'):
break
self.msleep(20) # +++
# Закрывает видеофайл или записывающее устройство.
# cap.release() # ---
# ? Уничтожает все окна HighGUI.
# ? Функция destroyAllWindows уничтожает все открытые окна HighGUI.
cv2.destroyAllWindows()
class Widget(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
# uic.loadUi('fire_detection.ui', self)
# self.show()
self.centralWidget = QWidget() # +++
self.setCentralWidget(self.centralWidget) # +++
self.label_video = QLabel('QLabel')
layout = QVBoxLayout(self.centralWidget) # +++ self.centralWidget
layout.addWidget(self.label_video)
# self.widget.setLayout(layout)
self.thread = ThreadOpenCV('Samonastrojka.avi') # <---- ('20201024161726.mp4')
self.thread.changePixmap.connect(self.setImage)
self.btn1 = QPushButton('Загрузить видео')
self.btn1.clicked.connect(self.playVideo)
layout.addWidget(self.btn1)
def playVideo(self):
self.thread.start()
def setImage(self, image):
self.label_video.setPixmap(QPixmap.fromImage(image))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
mw = Widget()
mw.show()
sys.exit(app.exec_())
