Video Speed is too first in PyQt5, Opencv - python-3.x

When i run this code the video speed is very fast. Maybe it is happening because of the frame rate(because different frame rate is used for HD and FHD). How can i solve the issue and fixed the frame rate.i use cap.set(15,-.8) to slow down the frame rate but it doesn't work.The video size is 1080p(full HD).
import sys
import cv2
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
import datetime
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 Video'
self.left = 100
self.top = 100
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.resize(1800, 1200)
# create a label
# create a label
label = QLabel(self)
label.move(280, 120)
label.resize(640, 480)
label1 = QLabel(self)
label1.move(580, 620)
self.th = Thread(self)
self.th.changePixmap.connect(label.setPixmap)
self.th.changeLabel.connect(label1.setText)
self.th.start()
def closeEvent(self, event):
self.th.stop()
QWidget.closeEvent(self, event)
class Thread(QThread):
changePixmap = pyqtSignal(QPixmap)
changeLabel = pyqtSignal(str)
def __init__(self, parent=None):
QThread.__init__(self, parent=parent)
self.isRunning = True
def run(self):
cap = cv2.VideoCapture('a.mp4')
while self.isRunning:
ret, frame = cap.read()
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
convertToQtFormat = QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888)
convertToQtFormat = QPixmap.fromImage(convertToQtFormat)
p = convertToQtFormat.scaled(640, 400, Qt.KeepAspectRatio)
self.changePixmap.emit(p)
now = datetime.datetime.now()
sec = now.second
self.changeLabel.emit(str(sec))
def stop(self):
self.isRunning = False
self.quit()
self.wait()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())

Related

How to record the video from a webcam in a pyqt5 gui using OpenCV and QThread?

I'm trying to make pyqt5 Gui that shows a webcam live feed, records the feed at the same time, and saves it locally when closed. I managed to acheieve this using Timer(QTimer) in pyqt gui but When I try to implement it using Qthread (Which I really require) only the live feed is working.
Whenever I add Code required for recording video and run the program it says Python has Stopped Working and closes. Here is my Code:
import cv2
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QVBoxLayout
from PyQt5.QtCore import QThread, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QImage, QPixmap
class Thread(QThread):
changePixmap = pyqtSignal(QImage)
def run(self):
self.cap = cv2.VideoCapture(0)
self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
self.codec = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
self.writer = cv2.VideoWriter('output.avi', self.codec, 30.0, (self.width, self.height))
while self.cap.isOpened():
ret, self.frame = self.cap.read()
if ret:
self.frame = cv2.flip(self.frame, 1)
rgbimage = cv2.cvtColor(self.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)
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
self.title = 'Camera'
self.initUI()
def initUI(self):
self.label = QLabel(self)
lay = QVBoxLayout()
lay.addWidget(self.label)
self.setLayout(lay)
self.th = Thread()
self.th.changePixmap.connect(self.setImage)
self.th.start()
self.show()
#pyqtSlot(QImage)
def setImage(self, image):
self.label.setPixmap(QPixmap.fromImage(image))
self.th.writer.write(image)
def main():
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I tried placing the .write() inside the run() of Thread class as well which is showing the same error. Can you guys point out What I'm doing wrong and how to make it work. I'm new to python and pyqt.
Thanks in Advance.
You need to separate threads. First thread is for signal, second is for the record and the main thread is for GUI. Try the following code. There is a button to start/stop the record.
import sys
import cv2
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, pyqtSlot
from PyQt5 import QtWidgets, QtCore, QtGui
#https://ru.stackoverflow.com/a/1150993/396441
class Thread1(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, *args, **kwargs):
super().__init__()
def run(self):
self.cap1 = cv2.VideoCapture(0, cv2.CAP_DSHOW)
self.cap1.set(3,480)
self.cap1.set(4,640)
self.cap1.set(5,30)
while True:
ret1, image1 = self.cap1.read()
if ret1:
im1 = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB)
height1, width1, channel1 = im1.shape
step1 = channel1 * width1
qImg1 = QImage(im1.data, width1, height1, step1, QImage.Format_RGB888)
self.changePixmap.emit(qImg1)
class Thread2(QThread):
def __init__(self, *args, **kwargs):
super().__init__()
self.active = True
def run(self):
if self.active:
self.fourcc = cv2.VideoWriter_fourcc(*'XVID')
self.out1 = cv2.VideoWriter('output.avi', self.fourcc, 30, (640,480))
self.cap1 = cv2.VideoCapture(0, cv2.CAP_DSHOW)
self.cap1.set(3, 480)
self.cap1.set(4, 640)
self.cap1.set(5, 30)
while self.active:
ret1, image1 = self.cap1.read()
if ret1:
self.out1.write(image1)
self.msleep(10)
def stop(self):
self.out1.release()
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(660, 520)
self.control_bt = QPushButton('START')
self.control_bt.clicked.connect(self.controlTimer)
self.image_label = QLabel()
self.saveTimer = QTimer()
self.th1 = Thread1(self)
self.th1.changePixmap.connect(self.setImage)
self.th1.start()
vlayout = QVBoxLayout(self)
vlayout.addWidget(self.image_label)
vlayout.addWidget(self.control_bt)
#QtCore.pyqtSlot(QImage)
def setImage(self, qImg1):
self.image_label.setPixmap(QPixmap.fromImage(qImg1))
def controlTimer(self):
if not self.saveTimer.isActive():
# write video
self.saveTimer.start()
self.th2 = Thread2(self)
self.th2.active = True
self.th2.start()
# update control_bt text
self.control_bt.setText("STOP")
else:
# stop writing
self.saveTimer.stop()
self.th2.active = False
self.th2.stop()
self.th2.terminate()
# update control_bt text
self.control_bt.setText("START")
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
you placed the .write() inside the run() of Thread class is right way.
like:
...
while self.cap.isOpened():
ret, self.frame = self.cap.read()
if ret:
self.frame = cv2.flip(self.frame, 1)
rgbimage = cv2.cvtColor(self.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)
# put your writer() here, make sure your param is frame
# not converted to QtImage format
self.writer.write(rgbimage)
self.changePixmap.emit(p)
...

PyQt5 switch between windows

I want to create menu based on tiles. Now I need PyQt5 concept how to switch MainWindow to Window1/Window2/... with back option to MainWindow. The only thing I've achieved is opening a new window on top. I'd rather have separate windows, where I could define different functions.
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
from PyQt5.QtCore import pyqtSlot
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "App"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
self.InitUI()
def InitUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
buttonWindow1 = QPushButton('Window1', self)
buttonWindow1.move(100, 100)
buttonWindow1.clicked.connect(self.buttonWindow1_onClick)
buttonWindow2 = QPushButton('Window2', self)
buttonWindow2.move(100, 200)
buttonWindow2.clicked.connect(self.buttonWindow2_onClick)
self.show()
#pyqtSlot()
def buttonWindow1_onClick(self):
self.statusBar().showMessage("Switched to window 1")
#pyqtSlot()
def buttonWindow2_onClick(self):
self.statusBar().showMessage("Switched to window 2")
if __name__ == '__main__':
app=QApplication(sys.argv)
ex=Window()
sys.exit(app.exec_())
Try it:
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "App"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
self.InitUI()
def InitUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
buttonWindow1 = QPushButton('Window1', self)
buttonWindow1.move(100, 100)
buttonWindow1.clicked.connect(self.buttonWindow1_onClick)
self.lineEdit1 = QLineEdit("Type here what you want to transfer for [Window1].", self)
self.lineEdit1.setGeometry(250, 100, 400, 30)
buttonWindow2 = QPushButton('Window2', self)
buttonWindow2.move(100, 200)
buttonWindow2.clicked.connect(self.buttonWindow2_onClick)
self.lineEdit2 = QLineEdit("Type here what you want to transfer for [Window2].", self)
self.lineEdit2.setGeometry(250, 200, 400, 30)
self.show()
#pyqtSlot()
def buttonWindow1_onClick(self):
self.statusBar().showMessage("Switched to window 1")
self.cams = Window1(self.lineEdit1.text())
self.cams.show()
self.close()
#pyqtSlot()
def buttonWindow2_onClick(self):
self.statusBar().showMessage("Switched to window 2")
self.cams = Window2(self.lineEdit2.text())
self.cams.show()
self.close()
class Window1(QDialog):
def __init__(self, value, parent=None):
super().__init__(parent)
self.setWindowTitle('Window1')
self.setWindowIcon(self.style().standardIcon(QStyle.SP_FileDialogInfoView))
label1 = QLabel(value)
self.button = QPushButton()
self.button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
self.button.setIcon(self.style().standardIcon(QStyle.SP_ArrowLeft))
self.button.setIconSize(QSize(200, 200))
layoutV = QVBoxLayout()
self.pushButton = QPushButton(self)
self.pushButton.setStyleSheet('background-color: rgb(0,0,255); color: #fff')
self.pushButton.setText('Click me!')
self.pushButton.clicked.connect(self.goMainWindow)
layoutV.addWidget(self.pushButton)
layoutH = QHBoxLayout()
layoutH.addWidget(label1)
layoutH.addWidget(self.button)
layoutV.addLayout(layoutH)
self.setLayout(layoutV)
def goMainWindow(self):
self.cams = Window()
self.cams.show()
self.close()
class Window2(QDialog):
def __init__(self, value, parent=None):
super().__init__(parent)
self.setWindowTitle('Window2')
self.setWindowIcon(self.style().standardIcon(QStyle.SP_FileDialogInfoView))
label1 = QLabel(value)
self.button = QPushButton()
self.button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
self.button.setIcon(self.style().standardIcon(QStyle.SP_ArrowLeft))
self.button.setIconSize(QSize(200, 200))
layoutV = QVBoxLayout()
self.pushButton = QPushButton(self)
self.pushButton.setStyleSheet('background-color: rgb(0,0,255); color: #fff')
self.pushButton.setText('Click me!')
self.pushButton.clicked.connect(self.goMainWindow)
layoutV.addWidget(self.pushButton)
layoutH = QHBoxLayout()
layoutH.addWidget(label1)
layoutH.addWidget(self.button)
layoutV.addLayout(layoutH)
self.setLayout(layoutV)
def goMainWindow(self):
self.cams = Window()
self.cams.show()
self.close()
if __name__ == '__main__':
app=QApplication(sys.argv)
ex=Window()
sys.exit(app.exec_())
Try this:
from file2 import Ui_Dialog2 #------>import the class for next window
def buttonWindow1_onClick(self):
self.window=QtWidgets.QMainWindow()
self.ui=Ui_Dialog2() #------------->creating an object
self.ui.setupUi(self.window)
self.window.show()
Here the Ui_Dialog2() represents that your are creating an object for new window (in your case creating object for Window1 for switch MainWindow to Window1 ).So when you click the next button this function is called so an object is created for the next window and the window will be opened.

PyQt change picture with keyboard button

this is my first post here and I haven't seen it anywhere so hopefully it is ok. I am trying to change the displayed image with a keyboard click (think slideshow). This is my code so far:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
import os
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'Document Analysis'
self.left = 30
self.top = 30
self.width = 640
self.height = 480
self.imagenumber=0
self.initUI()
def keyPressEvent(self, event):
key=event.key()
if key==Qt.Key_Right:
self.imagenumber=self.imagenumber+1
self.showimage(self.imagenumber)
self.show()
else:
super(self).keyPressEvent(event)
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.showimage(0)
self.show()
def showimage(self,imagenumber):
label = QLabel(self)
directory = "C:\\Desktop\\Pictures"
imagelist = os.listdir(directory)
pixmap = QPixmap(directory + '\\' + imagelist[imagenumber])
label.setPixmap(pixmap)
self.resize(pixmap.width() + 500, pixmap.height())
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
It seems to be sort of getting somewhere, the first image displays just fine, and I know imagenumber does change, and when I stopped it from showing at first it resized the window but still didn't show the image. Any suggestions on what I am doing wrong?
This is part of a larger project which is the reason for the extra space on the side of the picture, but help would be appreciated.
You're close. Try the following...
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
import os
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'Document Analysis'
self.left = 30
self.top = 30
self.width = 640
self.height = 480
self.imagenumber=0
self.initUI()
def keyPressEvent(self, event):
key=event.key()
if key==Qt.Key_Right:
self.imagenumber=self.imagenumber+1
self.showimage(self.imagenumber)
# self.show()
else:
super(self).keyPressEvent(event)
def initUI(self):
layout = QVBoxLayout()
self.setLayout(layout)
self.label = QLabel(self)
layout.addWidget(self.label)
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.showimage(0)
self.show()
def showimage(self,imagenumber):
# label = QLabel(self)
directory = "C:\\Desktop\\Pictures"
imagelist = os.listdir(directory)
pixmap = QPixmap(directory + '\\' + imagelist[imagenumber])
# label.setPixmap(pixmap)
self.label.setPixmap(pixmap)
self.resize(pixmap.width() + 500, pixmap.height())
# self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Mainly, you need a persistent label. You also only need to call show() once.

Qt5 paintEvent propagation to child widgets

I am trying to write a basic game loop in PyQt5. I have a QWidget and a QGraphicsView inside it. I use QTimer and update() to trigger the paintEvent() on QWidget and QGraphicsView. The QWidget paintEvent() gets updated but QGraphicsView paintEvent() does not.
Here is my code:
import sys, random
from PyQt5.QtWidgets import QWidget, QGridLayout, QApplication, QGraphicsView, QGraphicsScene
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPainter, QColor, QPen, QBrush, QColor
class Window(QWidget):
WIDTH = 800
HEIGHT = 480
SPEED = 500
def __init__(self):
super().__init__()
self.initUi()
self.initDisplay()
self.show()
def initUi(self):
layout = QGridLayout()
scene = GraphicsScene()
self.view = GraphicsView()
self.view.setScene(scene)
layout.addWidget(self.view)
self.setLayout(layout)
def initDisplay(self):
self.resize(Window.WIDTH, Window.HEIGHT)
self.timer = QTimer()
self.timer.setInterval(Window.SPEED)
self.timer.timeout.connect(self.timerEvent)
self.isStarted = False
self.isPaused = False
self.timer.start()
def start(self):
if self.isPaused:
return
self.isStarted = True
self.timer.start(Display.SPEED)
def pause(self):
if not self.isStarted:
return
self.isPaused = not self.isPaused
if self.isPaused:
self.timer.stop()
else:
self.timer.start(Display.SPEED)
self.update()
def paintEvent(self, event):
print('paint event ...')
def timerEvent(self):
self.update()
self.view.update()
print('timer event ...')
class GraphicsView(QGraphicsView):
def __init__(self):
super(GraphicsView, self).__init__()
def paintEvent(self, event):
self.scene().add_shapes()
print('view paint event')
class GraphicsScene(QGraphicsScene):
def __init__(self):
super(GraphicsScene, self).__init__()
def add_shapes(self):
self.setSceneRect(0.0, 0.0, 800.0, 640.0)
self.addRect(100, 100, 150, 150)
pen = QPen(Qt.SolidLine)
pen.setColor(Qt.red)
brush = QBrush(Qt.Dense3Pattern)
brush.setColor(Qt.darkGreen)
self.addEllipse(300, 300, 100, 100, pen, brush)
print('add shapes')
if __name__ == '__main__':
app = QApplication([])
window = Window()
sys.exit(app.exec_())
When I run the script I get the following output:
paint event ...
add shapes
view paint event
paint event ...
add shapes
view paint event
timer event ...
paint event ...
paint event ...
timer event ...
paint event ...
paint event ...
timer event ...
paint event ...
paint event ...
timer event ...
paint event ...
paint event ...
timer event ...
paint event ...
paint event ...
The solution is to call the paintEvent() of the base class (in this case QGraphicsView:
import sys, random
from PyQt5.QtWidgets import QWidget, QGridLayout, QApplication, QGraphicsView, QGraphicsScene
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPainter, QColor, QPen, QBrush, QColor
class Window(QWidget):
WIDTH = 800
HEIGHT = 480
SPEED = 500
def __init__(self):
super().__init__()
self.initUi()
self.initDisplay()
self.show()
def initUi(self):
layout = QGridLayout()
self.scene = GraphicsScene()
self.view = GraphicsView(self, self.scene)
layout.addWidget(self.view)
self.setLayout(layout)
def initDisplay(self):
self.resize(Window.WIDTH, Window.HEIGHT)
self.timer = QTimer()
self.timer.setInterval(Window.SPEED)
self.timer.timeout.connect(self.timerEvent)
self.isStarted = False
self.isPaused = False
self.timer.start()
def start(self):
if self.isPaused:
return
self.isStarted = True
self.timer.start(Display.SPEED)
def pause(self):
if not self.isStarted:
return
self.isPaused = not self.isPaused
if self.isPaused:
self.timer.stop()
else:
self.timer.start(Display.SPEED)
self.update()
def paintEvent(self, event):
print('paint event ...')
def timerEvent(self):
self.update()
self.view.update()
self.scene.update()
print('timer event ...')
class GraphicsView(QGraphicsView):
def __init__(self, parent, scene):
super(GraphicsView, self).__init__()
self.scene = scene
self.parent = parent
self.setScene(self.scene)
def paintEvent(self, event):
QGraphicsView.paintEvent(self, event)#########
self.setScene(self.scene)
self.scene.add_shapes()
print('view paint event')
class GraphicsScene(QGraphicsScene):
def __init__(self):
super(GraphicsScene, self).__init__()
def add_shapes(self):
self.setSceneRect(0.0, 0.0, 700.0, 450.0)
self.addRect(100, 100, 150, 150)
pen = QPen(Qt.SolidLine)
pen.setColor(Qt.red)
brush = QBrush(Qt.Dense3Pattern)
brush.setColor(Qt.darkGreen)
self.addEllipse(300, 300, 100, 100, pen, brush)
print('add shapes')
if __name__ == '__main__':
app = QApplication([])
window = Window()
sys.exit(app.exec_())

opencv pyqt video normal frame rate

I’m creating a special purpose video player in Python 3.6 using OpenCV3 and ffmepg for handling the images and using PyQt5 for the Windows environment. I chose this combination of packages because ffmpeg handles a wider variety of codecs than QtMultimedia.
I’ve run into one snag. My player does not play at regular speed – it plays at roughly ¾ of normal speed. I use QTimer.timer to loop my display engine (nextFrameSlot) at a speed of 1/framerate.
Any suggestions on how to get the video to play at regular speed? Here is an abbreviated set of code that demonstrates my problem.
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QFormLayout, QPushButton, QMainWindow
from PyQt5.QtWidgets import QAction, QMessageBox, QApplication, QFileDialog
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QTimer
import cv2
class VideoCapture(QWidget):
def __init__(self, filename, parent):
super(QWidget, self).__init__()
self.cap = cv2.VideoCapture(str(filename[0]))
self.length = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
self.frame_rate = self.cap.get(cv2.CAP_PROP_FPS)
#self.codec = self.cap.get(cv2.CAP_PROP_FOURCC)
self.video_frame = QLabel()
parent.layout.addWidget(self.video_frame)
def nextFrameSlot(self):
ret, frame = self.cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
pix = QPixmap.fromImage(img)
self.video_frame.setPixmap(pix)
def start(self):
self.timer = QTimer()
self.timer.timeout.connect(self.nextFrameSlot)
self.timer.start(1000.0/self.frame_rate)
def pause(self):
self.timer.stop()
def deleteLater(self):
self.cap.release()
super(QWidget, self).deleteLater()
class VideoDisplayWidget(QWidget):
def __init__(self,parent):
super(VideoDisplayWidget, self).__init__(parent)
self.layout = QFormLayout(self)
self.startButton = QPushButton('Start', parent)
self.startButton.clicked.connect(parent.startCapture)
self.startButton.setFixedWidth(50)
self.pauseButton = QPushButton('Pause', parent)
self.pauseButton.setFixedWidth(50)
self.layout.addRow(self.startButton, self.pauseButton)
self.setLayout(self.layout)
class ControlWindow(QMainWindow):
def __init__(self):
super(ControlWindow, self).__init__()
self.setGeometry(50, 50, 800, 600)
self.setWindowTitle("PyTrack")
self.capture = None
self.isVideoFileLoaded = False
self.quitAction = QAction("&Exit", self)
self.quitAction.setShortcut("Ctrl+Q")
self.quitAction.triggered.connect(self.closeApplication)
self.openVideoFile = QAction("&Open Video File", self)
self.openVideoFile.setShortcut("Ctrl+Shift+V")
self.openVideoFile.triggered.connect(self.loadVideoFile)
self.mainMenu = self.menuBar()
self.fileMenu = self.mainMenu.addMenu('&File')
self.fileMenu.addAction(self.openVideoFile)
self.fileMenu.addAction(self.quitAction)
self.videoDisplayWidget = VideoDisplayWidget(self)
self.setCentralWidget(self.videoDisplayWidget)
def startCapture(self):
if not self.capture and self.isVideoFileLoaded:
self.capture = VideoCapture(self.videoFileName, self.videoDisplayWidget)
self.videoDisplayWidget.pauseButton.clicked.connect(self.capture.pause)
self.capture.start()
def endCapture(self):
self.capture.deleteLater()
self.capture = None
def loadVideoFile(self):
try:
self.videoFileName = QFileDialog.getOpenFileName(self, 'Select a Video File')
self.isVideoFileLoaded = True
except:
print ("Please Select a Video File")
def closeApplication(self):
choice = QMessageBox.question(self, 'Message','Do you really want to exit?',QMessageBox.Yes | QMessageBox.No)
if choice == QMessageBox.Yes:
print("Closing....")
sys.exit()
else:
pass
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ControlWindow()
window.show()
sys.exit(app.exec_())
Solved - 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. For Windows, the coarse time is 15.6 msec intervals.

Resources