【问题标题】:Video Playback is Slow - Python 3.6, OpenCV 3, PyQT 5视频播放速度很慢 - Python 3.6、OpenCV 3、PyQT 5
【发布时间】:2017-05-08 10:45:34
【问题描述】:

我正在使用 Python 3.6、OpenCV3 和 PyQT5 在 Windows 中编写专门的视频播放器。但是,播放以每秒 30.0 帧录制的视频文件(从我的笔记本电脑网络摄像头录制)时,播放速度很慢。

我将我的应用程序剥离到播放视频的最简单部分。然后,我将应用程序中的播放循环从每帧 15 毫秒更改为每帧 34 毫秒,并记录了每个循环时间。接下来,我计算了每个循环速度下 232 帧播放的平均循环时间。结果令人费解。对于 15 毫秒到 19 毫秒的循环,应用程序的行为与预期一样,但当应用程序指定循环为 20 毫秒到 31 毫秒时,应用程序的行为是稳定的 31.2 毫秒。然后,当应用程序指定的循环慢于 31 毫秒时,循环时间再次跳跃。

Application = 15msec,   Average Result = 15.0msec,   Difference = 0.0msec  
Application = 16msec,   Average Result = 16.0msec,   Difference = 0.0msec  
Application = 17msec,   Average Result = 17.0msec,   Difference = 0.0msec  
Application = 18msec,   Average Result = 18.0msec,   Difference = 0.0msec  
Application = 19msec,   Average Result = 19.0msec,   Difference = 0.0msec  
Application = 20msec,   Average Result = 31.2msec,   Difference = 11.2msec  
Application = 21msec,   Average Result = 31.2msec,   Difference = 10.2msec  
Application = 22msec,   Average Result = 31.2msec,   Difference = 9.2msec  
Application = 23msec,   Average Result = 31.2msec,   Difference = 8.2msec  
Application = 24msec,   Average Result = 31.2msec,   Difference = 7.2msec  
Application = 25msec,   Average Result = 31.2msec,   Difference = 6.2msec  
Application = 26msec,   Average Result = 31.2msec,   Difference = 5.2msec  
Application = 27msec,   Average Result = 31.2msec,   Difference = 4.2msec  
Application = 28msec,   Average Result = 31.2msec,   Difference = 3.2msec  
Application = 29msec,   Average Result = 31.2msec,   Difference = 2.2msec  
Application = 30msec,   Average Result = 31.2msec,   Difference = 1.2msec  
Application = 31msec,   Average Result = 31.2msec,   Difference = 0.2msec  
Application = 32msec,   Average Result = 39.1msec,   Difference = 7.1msec  
Application = 33msec,   Average Result = 46.8msec,   Difference = 13.8msec  
Application = 34msec,   Average Result = 46.8msec,   Difference = 12.8msec  

我还计时了执行nextFrameSlot(self) 方法需要多长时间。执行平均需要 6 毫秒,因此不会对循环造成任何延迟。

我希望播放速度为真实速率,应该是 1/(帧速率)。

有人对为什么会发生这种情况有任何建议吗?这是代码。 (我没有包含 pydesigner 创建的 GUI 代码)。

from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QTimer
from time import time
import sys
import cv2
import vidtest        # GUI Module created by pydesigner

class VideoCapture(QMainWindow, vidtest.Ui_MainWindow):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)  # This is defined in design.py file automatically
        self.btnLoadFile.clicked.connect(self.loadVideoFile)
        self.btnStartPlay.clicked.connect(self.start)
        self.btnStop.clicked.connect(self.closeApplication)
        self.durations = []

    def nextFrameSlot(self):
        ret, frame = self.cap.read()
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        x = frame.shape[1]
        y = frame.shape[0]
        img = QImage(frame, x, y, QImage.Format_RGB888)
        pix = QPixmap.fromImage(img)
        self.vidWindow.setPixmap(pix)
        a = time()  # Used to record loop time
        self.durations.append(a)  # Used to record loop time

    def start(self):
        self.timer = QTimer()
        print("Rate = ", self.vid_rate)
        self.timer.timeout.connect(self.nextFrameSlot)
        self.timer.start(self.vid_rate)

    def loadVideoFile(self):
        self.videoFileName = "stopwatch.avi"
        self.cap = cv2.VideoCapture(str(self.videoFileName))
        self.frame_rate = self.cap.get(cv2.CAP_PROP_FPS)
        self.vid_rate = 34       # reset this integer from 15 through 34
        self.nextFrameSlot()      

    def closeApplication(self):
        for i in self.durations:
            print (i)
        self.cap.release()
        sys.exit(0)

def main():
    app = QApplication(sys.argv)
    form = VideoCapture()
    form.show()
    app.exec_()

if __name__ == '__main__':
    main()

【问题讨论】:

  • 31.2ms 的值有点可疑,因为 Windows 的默认计时器分辨率是 15.6ms。您是否尝试将QTimerTimerType 属性设置为PreciseTimer
  • PreciseTimer 解决了这个问题。谢谢!现在效果很好。

标签: python loops opencv video pyqt


【解决方案1】:

谢谢,用户 3419537!你的建议奏效了。

我需要在函数start(self) 中的语句self.timer = QTimer() 之后指定self.timer.setTimerType(Qt.PreciseTimer)。默认情况下,QTimer() 使用粗略计时器。

【讨论】:

    猜你喜欢
    • 2014-02-07
    • 2017-09-15
    • 2013-06-18
    • 2018-08-28
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多