如何使用OpenCV和pyqt5启动和停止相机订阅源



我需要制作一个显示摄像头视频馈送的应用程序,并且我希望能够随时启动和停止馈送。到目前为止,我得到的是:我启动了一个新的内核,并运行了下面的脚本,一切都按预期进行。现在我用Windows关闭按钮关闭应用程序,再次运行脚本,我可以启动提要,但是,当我试图停止提要时,它会关闭内核。我不知道为什么会发生这种事。

编辑:我刚刚发现多次启动和停止也会导致内核崩溃。

# -*- coding: utf-8 -*-
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import cv2
class MainWindow(QWidget):
def __init__(self):
super().__init__()

self.resize(300,300)
self.globalLayout = QVBoxLayout(self)
self.feedLabel = QLabel(self)
self.feedLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.feedLabel.setStyleSheet("background-color:pink")


self.start_btn=QPushButton("Start feed", self)
self.cancel_btn = QPushButton("Cancel", self)
self.saveImg_btn=QPushButton("Save image", self)

self.select_camera=QComboBox(self)
self.select_camera.addItems(["0","1"])

buttons_widget=QWidget(self)
buttons_layout=QHBoxLayout(buttons_widget)
buttons_layout.addWidget(self.start_btn)
buttons_layout.addWidget(self.cancel_btn)
buttons_layout.addWidget(self.saveImg_btn)
buttons_layout.addWidget(self.select_camera)

self.globalLayout.addWidget(self.feedLabel)
self.globalLayout.addWidget(buttons_widget)

self.setLayout(self.globalLayout)

self.start_btn.clicked.connect(self.start_feed)
self.cancel_btn.clicked.connect(self.stop_feed)

#create a thread
self.thread = QThread()
#create a worker
self.worker = Worker()
#move worker to thread
self.worker.moveToThread(self.thread)
#run method
self.thread.started.connect(self.worker.run)

self.worker.imageUpdate.connect(self.set_new_img)

self.worker.finished.connect(self.worker_done)
self.thread.finished.connect(self.thread_done)


def start_feed(self):
self.worker.camera=cv2.VideoCapture(int(self.select_camera.currentText()), cv2.CAP_DSHOW)
self.worker.running=True

#Start the thread
self.thread.start()

def stop_feed(self):
self.worker.running = False
print("feed was asked to stop")

def worker_done(self):
print("worker finished")
self.worker.camera.release()
self.thread.quit()

def thread_done(self):
print("thread finished")

def set_new_img(self,Image):
print("it received the signal")
print(Image)
self.feedLabel.setPixmap(QPixmap.fromImage(Image))


class Worker(QObject):
finished = pyqtSignal() #signals to communicate with main
imageUpdate = pyqtSignal(QImage) #should be class attributes

def __init__(self):
super().__init__()
self.camera=None
self.running=None

def run(self):

while self.running:
ret, frame = self.camera.read()
if ret:
Image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
FlippedImage = cv2.flip(Image, 1)
ConvertToQtFormat = QImage(FlippedImage.data, FlippedImage.shape[1], FlippedImage.shape[0], QImage.Format_RGB888)
Pic = ConvertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
print("it got the pic")
self.imageUpdate.emit(Pic)

print("nfinished signal emited")   
self.finished.emit()



if __name__ == "__main__":
App = QApplication(sys.argv)
Root = MainWindow()
Root.show()
sys.exit(App.exec())
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import cv2

class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(300, 300)
self.globalLayout = QVBoxLayout(self)
self.feedLabel = QLabel(self)
self.feedLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.feedLabel.setStyleSheet("background-color:pink")
self.start_btn = QPushButton("Start feed", self)
self.cancel_btn = QPushButton("Cancel", self)
self.saveImg_btn = QPushButton("Save image", self)
self.select_camera = QComboBox(self)
self.select_camera.addItems(["0", "1"])
buttons_widget = QWidget(self)
buttons_layout = QHBoxLayout(buttons_widget)
buttons_layout.addWidget(self.start_btn)
buttons_layout.addWidget(self.cancel_btn)
buttons_layout.addWidget(self.saveImg_btn)
buttons_layout.addWidget(self.select_camera)
self.globalLayout.addWidget(self.feedLabel)
self.globalLayout.enter code hereaddWidget(buttons_widget)
self.setLayout(self.globalLayout)
self.start_btn.clicked.connect(self.start_feed)
self.cancel_btn.clicked.connect(self.stop_feed)
# create a thread
self.thread = QThread()enter code here
# create a worker
self.worker = Worker()
# move worker to thread
self.worker.moveToThread(self.thread)
# run method
self.thread.started.connect(self.worker.run)
self.worker.imageUpdate.connect(self.set_new_img)
self.worker.finished.connect(self.worker_done)
self.thread.finished.connect(self.thread_done)
def start_feed(self):
self.worker.camera = cv2.VideoCapture(int(self.select_camera.currentText()), cv2.CAP_DSHOW)
self.worker.running = True
# Start the thread
self.thread.start()
def stop_feed(self):
self.worker.camera.release()
print("feed was asked to stop")
def worker_done(self):
print("worker finished")
self.worker.camera.release()
self.thread.quit()
def thread_done(self):
print("thread finished")
def set_new_img(self, Image):
print("it received the signal")
print(Image)
self.feedLabel.setPixmap(QPixmap.fromImage(Image))

class Worker(QObject):
finished = pyqtSignal()  # signals to communicate with main
imageUpdate = pyqtSignal(QImage)  # should be class attributes
def __init__(self):
super().__init__()
self.camera = None
self.running = None
def run(self):
while self.running:
ret, frame = self.camera.read()
if ret:
Image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
FlippedImage = cv2.flip(Image, 1)
ConvertToQtFormat = QImage(FlippedImage.data, FlippedImage.shape[1], FlippedImage.shape[0],
QImage.Format_RGB888)
Pic = ConvertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
print("it got the pic")
self.imageUpdate.emit(Pic)
print("nfinished signal emited")
self.finished.emit()

if __name__ == "__main__":
App = QApplication(sys.argv)
Root = MainWindow()
Root.show()
sys.exit(App.exec())`enter code here`

最新更新