【问题标题】:Load an opencv video frame by frame using PyQT使用 PyQT 逐帧加载 opencv 视频
【发布时间】:2017-01-11 04:42:29
【问题描述】:

我正在尝试加载一个 mat 文件(具有被跟踪对象的位置坐标)并加载一个视频文件。要加载视频文件,我使用的是 opencv。我制作了一个 GUI 来加载它们。只要有人按下开始按钮,视频就会开始播放,暂停就会停止。

这里是它的 gui:

这是我遇到的两个问题:

  1. 视频被加载到不同的窗口中。我希望它出现在具有“开始”和“暂停”按钮的主窗口
  2. 我想添加 2 个按钮(“下一帧”和“上一帧”),让我可以逐帧浏览视频。下一帧按钮移至下一帧,上一帧将视频移至上一帧。

代码如下:

import sys
import scipy.io as sio
from PyQt4 import QtGui, QtCore
import cv2

class QtCapture(QtGui.QWidget):
    def __init__(self, filename):
        super(QtGui.QWidget, self).__init__()

        self.cap = cv2.VideoCapture(str(filename))

        self.video_frame = QtGui.QLabel()
        lay = QtGui.QVBoxLayout()
        lay.setMargin(0)
        lay.addWidget(self.video_frame)
        self.setLayout(lay)

    def nextFrameSlot(self):
        ret, frame = self.cap.read()
        # My webcam yields frames in BGR format
        frame = cv2.cvtColor(frame, cv2.cv.CV_BGR2RGB)
        img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888)
        pix = QtGui.QPixmap.fromImage(img)
        self.video_frame.setPixmap(pix)

    def start(self):
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.nextFrameSlot)
        self.timer.start(1000./30)

    def pause(self):
        self.timer.stop()

    def deleteLater(self):
        self.cap.release()
        super(QtGui.QWidget, self).deleteLater()

class ControlWindow(QtGui.QMainWindow):
    def __init__(self):
        super(ControlWindow, self).__init__()
        self.setGeometry(50, 50, 800, 600)
        self.setWindowTitle("PyTrack")

        self.capture = None

    self.matPosFileName = None
    self.videoFileName = None
    self.positionData = None
        self.updatedPositionData  = {'red_x':[], 'red_y':[], 'green_x':[], 'green_y': [], 'distance': []}
    self.updatedMatPosFileName = None

    self.isVideoFileLoaded = False
    self.isPositionFileLoaded = False

        self.quitAction = QtGui.QAction("&Exit", self)
        self.quitAction.setShortcut("Ctrl+Q")
        self.quitAction.setStatusTip('Close The App')
        self.quitAction.triggered.connect(self.closeApplication)

        self.openMatFile = QtGui.QAction("&Open Position File", self)
        self.openMatFile.setShortcut("Ctrl+Shift+T")
        self.openMatFile.setStatusTip('Open .mat File')
        self.openMatFile.triggered.connect(self.loadPosMatFile)

    self.openVideoFile = QtGui.QAction("&Open Video File", self)
        self.openVideoFile.setShortcut("Ctrl+Shift+V")
        self.openVideoFile.setStatusTip('Open .h264 File')
        self.openVideoFile.triggered.connect(self.loadVideoFile)

        self.mainMenu = self.menuBar()

        self.fileMenu = self.mainMenu.addMenu('&File')
    self.fileMenu.addAction(self.openMatFile)
    self.fileMenu.addAction(self.openVideoFile)
        self.fileMenu.addAction(self.quitAction)

    self.imageCaptureWindow = QtGui.QWidget(self)
        self.start_button = QtGui.QPushButton('Start', self.imageCaptureWindow)
        self.start_button.clicked.connect(self.startCapture)
    self.start_button.setGeometry(0,10,40,30)
        self.pause_button = QtGui.QPushButton('Pause', self.imageCaptureWindow)
    self.pause_button.setGeometry(50,10,40,30)

        self.setCentralWidget(self.imageCaptureWindow)

        self.show()

    def startCapture(self):
        if not self.capture and self.isPositionFileLoaded and self.isVideoFileLoaded:
            self.capture = QtCapture(self.videoFileName)
            self.pause_button.clicked.connect(self.capture.pause)
            self.capture.setParent(self)
            self.capture.setWindowFlags(QtCore.Qt.Tool)
        self.capture.start()
        self.capture.show()

    def endCapture(self):
        self.capture.deleteLater()
        self.capture = None

    def loadPosMatFile(self):
    try:
            self.matPosFileName = str(QtGui.QFileDialog.getOpenFileName(self, 'Select .mat position File'))
            self.positionData = sio.loadmat(self.matPosFileName)
        self.isPositionFileLoaded = True
    except:
        print "Please select a .mat file"

    def loadVideoFile(self):
    try:
            self.videoFileName = QtGui.QFileDialog.getOpenFileName(self, 'Select .h264 Video File')
        self.isVideoFileLoaded = True
    except:
        print "Please select a .h264 file"

    def closeApplication(self):
        choice = QtGui.QMessageBox.question(self, 'Message','Do you really want to exit?',QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        if choice == QtGui.QMessageBox.Yes:
            print("Closing....")
            sys.exit()
        else:
            pass


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = ControlWindow()
    sys.exit(app.exec_())

我该怎么做呢?感谢您的帮助!

【问题讨论】:

    标签: python opencv pyqt pyqt4


    【解决方案1】:

    这是上述问题的解决方案:

    import sys
    import scipy.io as sio
    from PyQt4 import QtGui, QtCore
    import cv2
    
    
    class VideoCapture(QtGui.QWidget):
        def __init__(self, filename, parent):
            super(QtGui.QWidget, self).__init__()
            self.cap = cv2.VideoCapture(str(filename))
            self.video_frame = QtGui.QLabel()
            parent.layout.addWidget(self.video_frame)
    
        def nextFrameSlot(self):
            ret, frame = self.cap.read()
            frame = cv2.cvtColor(frame, cv2.cv.CV_BGR2RGB)
            img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888)
            pix = QtGui.QPixmap.fromImage(img)
            self.video_frame.setPixmap(pix)
    
        def start(self):
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.nextFrameSlot)
            self.timer.start(1000.0/30)
    
        def pause(self):
            self.timer.stop()
    
        def deleteLater(self):
            self.cap.release()
            super(QtGui.QWidget, self).deleteLater()
    
    
    class VideoDisplayWidget(QtGui.QWidget):
        def __init__(self,parent):
            super(VideoDisplayWidget, self).__init__(parent)
    
        self.layout = QtGui.QFormLayout(self)
    
            self.startButton = QtGui.QPushButton('Start', parent)
            self.startButton.clicked.connect(parent.startCapture)
            self.startButton.setFixedWidth(50)
            self.pauseButton = QtGui.QPushButton('Pause', parent)
            self.pauseButton.setFixedWidth(50)
            self.layout.addRow(self.startButton, self.pauseButton)
    
            self.setLayout(self.layout)
    
    
    class ControlWindow(QtGui.QMainWindow):
        def __init__(self):
            super(ControlWindow, self).__init__()
            self.setGeometry(50, 50, 800, 600)
            self.setWindowTitle("PyTrack")
    
            self.capture = None
    
            self.matPosFileName = None
            self.videoFileName = None
            self.positionData = None
            self.updatedPositionData  = {'red_x':[], 'red_y':[], 'green_x':[], 'green_y': [], 'distance': []}
            self.updatedMatPosFileName = None
    
                self.isVideoFileLoaded = False
            self.isPositionFileLoaded = False
    
            self.quitAction = QtGui.QAction("&Exit", self)
            self.quitAction.setShortcut("Ctrl+Q")
            self.quitAction.setStatusTip('Close The App')
            self.quitAction.triggered.connect(self.closeApplication)
    
            self.openMatFile = QtGui.QAction("&Open Position File", self)
            self.openMatFile.setShortcut("Ctrl+Shift+T")
            self.openMatFile.setStatusTip('Open .mat File')
            self.openMatFile.triggered.connect(self.loadPosMatFile)
    
            self.openVideoFile = QtGui.QAction("&Open Video File", self)
            self.openVideoFile.setShortcut("Ctrl+Shift+V")
            self.openVideoFile.setStatusTip('Open .h264 File')
            self.openVideoFile.triggered.connect(self.loadVideoFile)
    
            self.mainMenu = self.menuBar()
            self.fileMenu = self.mainMenu.addMenu('&File')
            self.fileMenu.addAction(self.openMatFile)
            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.isPositionFileLoaded 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 loadPosMatFile(self):
            try:
                self.matPosFileName = str(QtGui.QFileDialog.getOpenFileName(self, 'Select .mat position File'))
                self.positionData = sio.loadmat(self.matPosFileName)
                self.isPositionFileLoaded = True
            except:
                print "Please select a .mat file"
    
        def loadVideoFile(self):
            try:
                self.videoFileName = QtGui.QFileDialog.getOpenFileName(self, 'Select .h264 Video File')
                self.isVideoFileLoaded = True
            except:
                print "Please select a .h264 file"
    
        def closeApplication(self):
            choice = QtGui.QMessageBox.question(self, 'Message','Do you really want to exit?',QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
            if choice == QtGui.QMessageBox.Yes:
                print("Closing....")
                sys.exit()
            else:
                pass
    
    
    if __name__ == '__main__':
        import sys
        app = QtGui.QApplication(sys.argv)
        window = ControlWindow()
        window.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 这似乎没有解决将播放向后移动一帧的问题。
    猜你喜欢
    • 2015-08-28
    • 2019-12-31
    • 2013-11-08
    • 2018-01-27
    • 2014-05-30
    • 2020-07-13
    • 1970-01-01
    • 2013-09-28
    • 2016-07-15
    相关资源
    最近更新 更多