【发布时间】:2021-04-09 13:21:37
【问题描述】:
当在QListWidget 中选择时,我的 GUI 能够自动播放视频。但是,视频播放速度不是正常速度,而是非常快。我以 720p Mp4 视频为例,放在某个文件夹中。我尝试使用cv2.CAP_PROP_FPS 和cv2.CAP_PROP_BUFFERSIZE,但它们都不起作用。我在QThread 和convert_cv_qt 函数中使用了pyqtSignal,我在其他指南中看到了这些函数。 如何以正常速度/帧速率播放视频?
import os
import cv2
import numpy as np
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtMultimedia import QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QThread
class VideoThread(QThread):
change_pixmap_signal = pyqtSignal(np.ndarray)
def __init__(self, parent=None):
super(VideoThread, self).__init__(parent)
self.get_file_dir = self.parent().file_dir #Get the file_dir from UI_MainWindow
def run(self):
cap = cv2.VideoCapture(self.get_file_dir)
while True:
ret, cv_img = cap.read()
if ret:
self.change_pixmap_signal.emit(cv_img)
cap.release()
class Ui_MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Ui_MainWindow, self).__init__(parent)
self.setupUI()
def setupUI(self):
MainWindow.resize(1720, 863)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)
self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
self.tabWidget.setTabPosition(QtWidgets.QTabWidget.North)
self.tabWidget.setTabShape(QtWidgets.QTabWidget.Triangular)
self.tabWidget.setElideMode(QtCore.Qt.ElideNone)
self.tabWidget.setTabsClosable(False)
self.tabWidget.setMovable(True)
self.tab = QtWidgets.QWidget()
self.videoimage = QtWidgets.QLabel(self.tab)
self.videoimage.setGeometry(QtCore.QRect(0, 10, 1280, 720))
self.listWidget = QtWidgets.QListWidget(self.tab)
self.listWidget.setGeometry(QtCore.QRect(1290, 60, 391, 241))
self.listWidget.setObjectName("listWidget")
self.listWidget.itemClicked.connect(self.itemclick)
self.tabWidget.addTab(self.tab, "")
self.tabWidget.setTabText(0, "Testing")
self.verticalLayout_2.addWidget(self.tabWidget)
MainWindow.setCentralWidget(self.centralwidget)
self.listvideos()
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
@pyqtSlot(np.ndarray)
def listvideos(self):
file_extension = ['avi','mp4','mov']
arr = os.listdir('D:\\Files\\VSCODE\\APPS\\HDTS\\videos')
for i in arr:
for fe in file_extension:
if i[-3:] == fe:
item = QtWidgets.QListWidgetItem(str(i))
self.listWidget.addItem(item)
def itemclick(self):
try:
self.thread.terminate()
except:
print("Nothing to terminate!")
item = self.listWidget.currentItem()
self.file_dir = 'D:\\Files\\VSCODE\\APPS\\HDTS\\videos\\' + item.text()
print(self.file_dir)
self.thread = VideoThread(self)
self.thread.change_pixmap_signal.connect(self.update_image)
self.thread.start()
def update_image(self, cv_img):
qt_img = self.convert_cv_qt(cv_img)
self.videoimage.setPixmap(qt_img)
def convert_cv_qt(self, cv_img):
rgb_image = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
h, w, ch = rgb_image.shape
bytes_per_line = ch * w
convert_to_Qt_format = QtGui.QImage(rgb_image.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)
p = convert_to_Qt_format.scaled(1280, 720, Qt.KeepAspectRatio)
return QtGui.QPixmap.fromImage(p)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
MainWindow.show()
sys.exit(app.exec_())
【问题讨论】:
-
请考虑您对
setupUi的实现不是很好,最重要的是因为它在全局MainWindow上运行(使用全局变量通常被认为是不好的做法,导致由于实施不佳),而且还因为它可能会导致类和实例出现问题。真的,不要那样做。Ui_MainWindow已经是 QMainWindow 的子类,因此您应该仅使用它,而不创建另一个 QMainWindow 实例;然后将setupUi中对MainWindow的所有引用更改为self。 -
在我学习的过程中,我会尽力听从您的建议。谢谢。
标签: python-3.x opencv pyqt5