Issue
I am new to classes and PyQt5 and trying to build a video player using PyQt5 and Opencv. Using the code in OpenCV Video Capture with PyQt4 and making the changes to convert commands in PyQt4 into PyQt5 and adding a pause button, I now have a video player with pause, play, end, and quit buttons. This is the code which is working fine:
import cv2
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QPushButton,
QVBoxLayout, QFileDialog
fileName = 'C:/Users/Art/Downloads/testVideo.mp4'
class Capture():
def __init__(self):
self.capturing = False
self.c = cv2.VideoCapture(fileName)
def startCapture(self):
self.capturing = True
cap = self.c
while(self.capturing):
ret, frame = cap.read()
cv2.imshow("Capture", frame)
cv2.waitKey(5)
cv2.destroyAllWindows()
def endCapture(self):
self.capturing = False
def pauseCapture(self):
if cv2.waitKey(0) & 0xFF == ord('p'): # Pause
self.capturing = False
def quitCapture(self):
cap = self.c
cv2.destroyAllWindows()
cap.release()
QtCore.QCoreApplication.quit()
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setWindowTitle('Control Panel')
self.capture = Capture()
self.start_button = QPushButton('Start', self)
self.start_button.clicked.connect(self.capture.startCapture)
self.end_button = QPushButton('End', self)
self.end_button.clicked.connect(self.capture.endCapture)
self.pause_button = QPushButton('Pause', self)
self.pause_button.clicked.connect(self.capture.pauseCapture)
self.quit_button = QPushButton('Quit', self)
self.quit_button.clicked.connect(self.capture.quitCapture)
vbox = QVBoxLayout(self)
vbox.addWidget(self.start_button)
vbox.addWidget(self.end_button)
vbox.addWidget(self.pause_button)
vbox.addWidget(self.quit_button)
self.setLayout(vbox)
self.setGeometry(100, 100, 200, 200)
self.show()
if __name__== '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
So far, I hard coded the video file name and its path into the code (fileName). Now, I want to add a load button, that let the user select the video. Something like this:
self.load_button = QPushButton('Load', self)
self.load_button.clicked.connect(self.pick_video)
def pick_video():
dialog = QtGui.QFileDialog()
fileName = dialog.getExistingDirectory(None,
"Select Folder")
return fileName
And adding the load button to the list of existing buttons, like this:
vbox.addWidget(self.load_button)
My problem is I don't know how can I merge this into the existing code. If I put it inside Window class, it throws me an error. My question is how I can add something like this into my existing code, such that the user can select the video file after pressing a load button.
Edit: After changing the code based on @ekhumoro, I got something like this:
import cv2
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QPushButton,
QVBoxLayout, QFileDialog
class Capture():
def __init__(self):
self.capturing = False
def startCapture(self, path):
self.capturing = True
self.c = cv2.VideoCapture(path)
while self.capturing:
ret, frame = self.c.read()
cv2.imshow("Capture", frame)
cv2.waitKey(5)
cv2.destroyAllWindows()
def endCapture(self):
self.capturing = False
def pauseCapture(self):
if cv2.waitKey(0) & 0xFF == ord('p'): # Pause
self.capturing = False
def quitCapture(self):
cap = self.c
cv2.destroyAllWindows()
cap.release()
QtCore.QCoreApplication.quit()
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setWindowTitle('Control Panel')
self.capture = Capture()
self.start_button = QPushButton('Start', self)
self.start_button.clicked.connect(self.start)
self.end_button = QPushButton('End', self)
self.end_button.clicked.connect(self.capture.endCapture)
self.pause_button = QPushButton('Pause', self)
self.pause_button.clicked.connect(self.capture.pauseCapture)
self.quit_button = QPushButton('Quit', self)
self.quit_button.clicked.connect(self.capture.quitCapture)
vbox = QVBoxLayout(self)
vbox.addWidget(self.start_button)
vbox.addWidget(self.end_button)
vbox.addWidget(self.pause_button)
vbox.addWidget(self.quit_button)
self.setLayout(vbox)
self.setGeometry(100, 100, 200, 200)
self.show()
def start(self):
path = QtWidgets.QFileDialog.getOpenFileName(self)[0]
if path:
self.capture.startCapture(path)
if __name__== '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
But, when I run this code, I get this error: AttributeError: 'Window' object has no attribute 'start'. Another thing is that I want to have a separate button for this process, meaning that once the user run the code, in the window that opens, he/she can click on that button (let's call it load button), then select the video file, which I don't see in this code. Am I missing something somewhere? Or maybe the rearranged code is not what @ekhumoro meant.
Solution
Rearrange the code so that startCapture
takes a path
parameter. Then pass in the path from the file-dialog in the slot for the start button:
class Capture():
def __init__(self):
self.capturing = False
def startCapture(self, path):
self.capturing = True
self.c = cv2.VideoCapture(path)
while self.capturing:
ret, frame = self.c.read()
cv2.imshow("Capture", frame)
cv2.waitKey(5)
cv2.destroyAllWindows()
class Window(QtWidgets.QWidget):
def __init__(self):
...
self.start_button = QPushButton('Start', self)
self.start_button.clicked.connect(self.start)
...
def start(self):
path = QtWidgets.QFileDialog.getOpenFileName(self)[0]
if path:
self.capture.startCapture(path)
Here is a complete alternative implementation:
import cv2
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QPushButton,QVBoxLayout, QFileDialog
class Capture():
def __init__(self):
self.capturing = False
self.c = None
def setVideoFile(self, path):
if self.c is not None:
cv2.destroyAllWindows()
self.c.release()
self.c = cv2.VideoCapture(path)
self.startCapture()
def startCapture(self):
self.capturing = True
cap = self.c
while(self.capturing):
ret, frame = cap.read()
cv2.imshow("Capture", frame)
cv2.waitKey(5)
cv2.destroyAllWindows()
def endCapture(self):
self.capturing = False
def pauseCapture(self):
if cv2.waitKey(0) & 0xFF == ord('p'): # Pause
self.capturing = False
def quitCapture(self):
cap = self.c
cv2.destroyAllWindows()
cap.release()
QtCore.QCoreApplication.quit()
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setWindowTitle('Control Panel')
self.capture = Capture()
self.open_button = QPushButton('Open', self)
self.open_button.clicked.connect(self.open)
self.start_button = QPushButton('Start', self)
self.start_button.clicked.connect(self.capture.startCapture)
self.end_button = QPushButton('End', self)
self.end_button.clicked.connect(self.capture.endCapture)
self.pause_button = QPushButton('Pause', self)
self.pause_button.clicked.connect(self.capture.pauseCapture)
self.quit_button = QPushButton('Quit', self)
self.quit_button.clicked.connect(self.capture.quitCapture)
vbox = QVBoxLayout(self)
vbox.addWidget(self.open_button)
vbox.addWidget(self.start_button)
vbox.addWidget(self.end_button)
vbox.addWidget(self.pause_button)
vbox.addWidget(self.quit_button)
self.setLayout(vbox)
self.setGeometry(100, 100, 200, 200)
self.show()
def open(self):
path = QtWidgets.QFileDialog.getOpenFileName(self)[0]
if path:
self.capture.setVideoFile(path)
if __name__== '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
Answered By - ekhumoro
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.