即使关闭pyqt应用程序,网络摄像头实例也不会释放

时间:2019-03-30 14:22:49

标签: python python-3.x opencv pyqt pyqt5

我开发了一个包含按钮的应用程序。单击按钮后,它将开始运行网络摄像头以无限循环使用OpenCV捕获帧。当用户按下“ Q”时,程序将释放网络摄像头实例。当我关闭该应用程序时,该应用程序成功关闭,但网络摄像头实例未释放并继续运行。关闭应用程序后,如何确保释放网络摄像头资源。

Webcam.py:-

import cv2

def hello():

    camera = cv2.VideoCapture(0)
    top, right, bottom, left = 10, 350, 225, 590
    num_frames = 0

    while True:
        _, frame = camera.read()

        clone = frame.copy()
        roi = frame[top:bottom, right:left]

        cv2.rectangle(clone, (left, top), (right, bottom), (0, 255, 0), 2)
        num_frames += 1
        cv2.imshow("Video Feed", clone)

        keypress = cv2.waitKey(1) & 0xFF

        if keypress == ord("q"):
            break

    camera.release()
    cv2.destroyAllWindows()


if __name__ == "__main__":
    hello()

Application.py:-

from PyQt5 import QtCore, QtGui, QtWidgets
from Webcam import hello
import sys

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):

        self.window = MainWindow
        self.window.setObjectName("self.window")
        self.window.resize(800, 600)

        self.centralwidget = QtWidgets.QWidget(self.window)
        self.centralwidget.setObjectName("centralwidget")

        self.startButton = QtWidgets.QPushButton(self.centralwidget)
        self.startButton.setText("&Start")
        self.startButton.clicked.connect(self.open_cam)

        self.window.setCentralWidget(self.centralwidget)

        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def open_cam(self):
        hello()

class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None):

        super(MyWindow, self).__init__(parent)
        self.setupUi(self)

    def closeEvent(self, event):
        result = QtWidgets.QMessageBox.question(self,
                      "Confirm Exit...",
                      "Are you sure you want to exit ?",
                      QtWidgets.QMessageBox.Yes| QtWidgets.QMessageBox.No)
        event.ignore()
        if result == QtWidgets.QMessageBox.Yes:
            event.accept()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:1)

这可能是相机问题。我会尝试根据示例https://stackoverflow.com/a/11449901/8150685来更改相机的实现方式。我也建议您将相机更改为一个类,以便您可以控制它的设置方式以及它的消亡方式。

注意:我不在装有Qt的计算机上,因此未经过测试。我可能需要进行一些调试,否则可能无法正常工作。

import cv2

class Camera:
    def __init__(self):

        self.alive = True
        self.vc = None


    def run(self):

        self.vc = cv2.VideoCapture(0)
        if self.vc.isOpened(): # try to get the first frame
            self.rval, self.frame = self.vc.read()
        else:
            self.rval = False

        while self.rval:
            cv2.imshow("preview", self.frame)
            self.rval, self.frame = self.vc.read()
            key = cv2.waitKey(20)
            if key == ord("q"): # exit on q
                break
        self.destroy()

    def destroy(self):
        if self.alive and self.vc:
            cv2.destroyWindow("preview")
            self.vc.release()
            self.alive = False

现在在Qt中,您可以创建Camera对象。

from PyQt5 import QtCore, QtGui, QtWidgets
from Webcam import Camera
import sys

class Ui_MainWindow(object):
    def setupUi(self, MainWindow, camera):

        self.camera = camera
        self.window = MainWindow
        self.window.setObjectName("self.window")
        self.window.resize(800, 600)

        self.centralwidget = QtWidgets.QWidget(self.window)
        self.centralwidget.setObjectName("centralwidget")

        self.startButton = QtWidgets.QPushButton(self.centralwidget)
        self.startButton.setText("&Start")
        self.startButton.clicked.connect(self.open_cam)

        self.window.setCentralWidget(self.centralwidget)

        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def open_cam(self):
        self.camera.run() # Run the camera

class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self, camera, parent=None):
        self.camera = camera
        super(MyWindow, self).__init__(parent)
        self.setupUi(self, self.camera) # Pass our camera pointer

    def closeEvent(self, event):
        result = QtWidgets.QMessageBox.question(self,
                      "Confirm Exit...",
                      "Are you sure you want to exit ?",
                      QtWidgets.QMessageBox.Yes| QtWidgets.QMessageBox.No)
        event.ignore()
        if result == QtWidgets.QMessageBox.Yes:
            self.camera.destroy() # Destroy the camera if it is not already
            event.accept()


if __name__ == "__main__":
    cam = Camera()
    app = QtWidgets.QApplication(sys.argv)
    w = MyWindow(cam)
    w.show()
    sys.exit(app.exec_())