5

I have been trying to capture video using PyQt4 GUI and OpenCV. I created some buttons like "Start", "End" etc to control the capturing. Starting is fine, but I can't stop the capture. To stop the capture, I need to break the while loop in startCapture() function below, I couldn't achieve it.

Currently, endCapture() destroys the window, but startCapture while loop simply creates it and continue the capturing. Only option is to break that loop.

Below is the code I used:

import cv2
import numpy as np
from PyQt4 import QtGui, QtCore

def startCapture(cap):
    print "pressed start"
    while(True):
        ret, frame = cap.read()
        cv2.imshow("Capture", frame)
        cv2.waitKey(5)
    cv2.destroyAllWindows() 

def endCapture(cap):
    print "pressed End"
    cv2.destroyAllWindows()

def quitCapture(cap):
    print "pressed Quit"
    cv2.destroyAllWindows()
    cap.release()
    QtCore.QCoreApplication.quit()

class Window(QtGui.QWidget):
    def __init__(self):

        c = cv2.VideoCapture(0)

        QtGui.QWidget.__init__(self)
        self.setWindowTitle('Control Panel')

        self.start_button = QtGui.QPushButton('Start',self)
        self.start_button.clicked.connect(lambda : startCapture(c, True))

        self.end_button = QtGui.QPushButton('End',self)
        self.end_button.clicked.connect(lambda : endCapture(c))

        self.quit_button = QtGui.QPushButton('Quit',self)
        self.quit_button.clicked.connect(lambda : quit(c))

        vbox = QtGui.QVBoxLayout(self)
        vbox.addWidget(self.start_button)
        vbox.addWidget(self.end_button)
        vbox.addWidget(self.quit_button)

        self.setLayout(vbox)
        self.setGeometry(100,100,200,200)
        self.show()

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    sys.exit(app.exec_())

Can any one suggest how to break that loop and exit the capturing?

Abid Rahman K
  • 51,886
  • 31
  • 146
  • 157
  • Create some kind of class or global variable that is checked in the loop of startCapture. and is changed when endCapture is called – M4rtini Jan 16 '14 at 18:36
  • @Abid, Is it worked? I am having the same problem. How did you solve this issue? – haccks Oct 04 '17 at 16:22

2 Answers2

4
class Capture():
    def __init__(self):
        self.capturing = False
        self.c = cv2.VideoCapture(0)

    def startCapture(self):
        print "pressed start"
        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):
        print "pressed End"
        self.capturing = False
        # cv2.destroyAllWindows()

    def quitCapture(self):
        print "pressed Quit"
        cap = self.c
        cv2.destroyAllWindows()
        cap.release()
        QtCore.QCoreApplication.quit()

in Window:

self.capture = Capture()
self.start_button = QtGui.QPushButton('Start',self)
self.start_button.clicked.connect(self.capture.startCapture)

self.end_button = QtGui.QPushButton('End',self)
self.end_button.clicked.connect(self.capture.endCapture)

self.quit_button = QtGui.QPushButton('Quit',self)
self.quit_button.clicked.connect(self.capture.quitCapture)
M4rtini
  • 13,186
  • 4
  • 35
  • 42
  • There is a bug in the class `quitCapture(self)`: Capturing of new frames is not stopped during _quit_ which results in an error, add `self.capturing = False` after `cap = self.c`. – bastelflp Sep 20 '15 at 23:29
  • I run this code and after pressing "start" button "end" and "quit" is not working. – haccks Oct 04 '17 at 16:16
4

The answer above is great, but for for a beginner like me it's hard to see where the part 'in Window' should go and how much of the original code should remain. Here is the full working code based on the information above:

import cv2
from PyQt4 import QtGui, QtCore


class Capture():
    def __init__(self):
        self.capturing = False
        self.c = cv2.VideoCapture(0)

    def startCapture(self):
        print "pressed start"
        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):
        print "pressed End"
        self.capturing = False

    def quitCapture(self):
        print "pressed Quit"
        cap = self.c
        cv2.destroyAllWindows()
        cap.release()
        QtCore.QCoreApplication.quit()


class Window(QtGui.QWidget):
    def __init__(self):

        QtGui.QWidget.__init__(self)
        self.setWindowTitle('Control Panel')

        self.capture = Capture()
        self.start_button = QtGui.QPushButton('Start',self)
        self.start_button.clicked.connect(self.capture.startCapture)

        self.end_button = QtGui.QPushButton('End',self)
        self.end_button.clicked.connect(self.capture.endCapture)

        self.quit_button = QtGui.QPushButton('Quit',self)
        self.quit_button.clicked.connect(self.capture.quitCapture)

        vbox = QtGui.QVBoxLayout(self)
        vbox.addWidget(self.start_button)
        vbox.addWidget(self.end_button)
        vbox.addWidget(self.quit_button)

        self.setLayout(vbox)
        self.setGeometry(100,100,200,200)
        self.show()


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    sys.exit(app.exec_())
catox
  • 101
  • 2
  • There is a bug in the class `quitCapture(self)`: Capturing of new frames is not stopped during _quit_ which results in an error, add `self.capturing = False` after `cap = self.c`. – bastelflp Sep 20 '15 at 23:29
  • Great program, thanks. Unfortunately it does not close the Window with the three butteons when pressing "quit", even not when adding the content of bastelflp's remark. – tfv Apr 27 '16 at 16:59