Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 使用OpenCV和PyQT5播放视频太快_Python 3.x_Opencv_Pyqt5 - Fatal编程技术网

Python 3.x 使用OpenCV和PyQT5播放视频太快

Python 3.x 使用OpenCV和PyQT5播放视频太快,python-3.x,opencv,pyqt5,Python 3.x,Opencv,Pyqt5,当在QListWidget中选择时,我的GUI能够自动播放视频。但是,视频播放速度非常快,而不是正常速度。我使用720p Mp4视频作为示例,并将其放在某个文件夹中。我尝试使用cv2.CAP_PROP_FPS和cv2.CAP_PROP_BUFFERSIZE,但它们都不起作用。我正在使用QThread中的pyqtSignal和我在其他指南中看到的convert\u cv\u qt函数如何以正常速度/帧速率播放视频? import os import cv2 import numpy as np f

当在
QListWidget
中选择时,我的GUI能够自动播放视频。但是,视频播放速度非常快,而不是正常速度。我使用720p Mp4视频作为示例,并将其放在某个文件夹中。我尝试使用
cv2.CAP_PROP_FPS
cv2.CAP_PROP_BUFFERSIZE
,但它们都不起作用。我正在使用
QThread
中的
pyqtSignal
和我在其他指南中看到的
convert\u cv\u qt
函数如何以正常速度/帧速率播放视频?

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_())

当您对文件使用VideoCapture时,如果调用“cap.read()”,您将获得视频的下一帧,而不管其实际帧速率如何。因此,每次捕获帧时都应使用“msleep”:

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)
        self.msleep(1000//30) # You can change 30 with 60 if you need 60 fps.
    cap.release()

我用相同的缩进尝试了它,但它产生了一个错误:
TypeError:参数与任何重载调用都不匹配:wait(self,msecs:int=ULONG_MAX):参数1具有意外的类型“float”wait(self,QDeadlineTimer):参数1具有意外的类型“float”
@gentales17我编辑了我的答案,试试这个,它仍然玩得太快。我试了30-1000次,没有任何变化
self.wait(1000//30)
self.wait(1000//60)
self.wait(1000//100)
self.wait(1000//1000)
我不确定那是什么。我刚刚将值从30更改为60(如您所建议的),甚至是1000,但没有任何更改。我也试着改变缩进,但也没用。我的代码有问题吗?@gentales17我再次编辑,请尝试此版本。我认为“等待”不是本例中使用的正确方法。请考虑您的代码< > StuuPui < /代码>的执行不是很好,最重要的是因为它运行在全局<代码>主窗口< /代码>(使用Global通常被认为是不良执行,由于执行不力)。但这也是因为它会给类和实例带来可能的问题。真的,别那么做
Ui_MainWindow
已经从QMainWindow子类化,所以您应该只使用它,而不创建QMainWindow的另一个实例;然后将
setupUi
中对
main窗口的所有引用更改为
self
。在学习过程中,我会尽力听从您的建议。非常感谢。