Issue
I’m using Python 3.6, OpenCV3, and PyQT5 to write a specialized video player in Windows. However, the playback is slow when playing a video file that was recorded at 30.0 frames per second (recorded off my laptop webcam).
I stripped my application to the barest part for playing video. I then varied the playback loop in my application from 15 milliseconds per frame to 34 milliseconds per frame and recorded each loop time. Next, I computed the average loop time for 232 frames of playback at each loop speed. The results are puzzling. The application behaved as expected for loops of 15 ms through 19ms, but then was a steady 31.2 ms when the application specified the loop be at 20 ms through 31 ms. Then the loop time jumped again when the application specified loops slower than 31 msec.
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
I also timed how long it takes to execute the nextFrameSlot(self)
method. It takes an average of 6msec to execute, so it should not induce any delay to the loops.
I want the playback speed to be at the true rate, which should be 1/(frame rate).
Does anyone have any suggestions why this is happening? Here is the code. (I didn’t include the GUI code that pydesigner created).
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()
Solution
Thanks, user3419537! Your suggestion worked.
I needed to specify self.timer.setTimerType(Qt.PreciseTimer)
after the statement self.timer = QTimer()
in the function start(self)
. By default, QTimer() uses a coarse timer.
Answered By - slalomchip
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.