Pyqt在尝试显示opencv视频流时崩溃

问题描述 投票:0回答:1

我尝试了this回答的代码,并在一段时间(2-10秒)之后崩溃,错误Process finished with exit code -1073740771 (0xC000041D),有时与0xC0000005崩溃。如果我试图拖动窗口,它会立即崩溃。然而,当我把time.sleep(0.1)放在run时它工作正常。如果我使用短于0.1的睡眠,它会再次崩溃。

from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel,QMessageBox
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot, Qt
import cv2
import sys
import time

class CamThread(QThread):
    changemap = pyqtSignal('QImage')

    def run(self):
        cap = cv2.VideoCapture(0)
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

        while True:
            ret, img_rgb = cap.read()
            if ret:
                self.rgb = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2RGB)
                self.convert = QImage(self.rgb.data, self.rgb.shape[1], self.rgb.shape[0], QImage.Format_RGB888)
                self.p = self.convert.scaled(640, 480, Qt.KeepAspectRatio)
                self.changemap.emit(self.p)
                #time.sleep(0.1)


class App(QWidget):
    def __init__(self):
        super().__init__()
        self.title = 'webcam'

        self.initUI()

    @pyqtSlot('QImage')
    def setImage(self, image):
        self.label.setPixmap(QPixmap.fromImage(image))

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(100, 100, 640, 480)
        self.resize(640, 480)
        self.label = QLabel(self)
        self.label.resize(640, 480)
        thr = CamThread(self)
        thr.changemap.connect(self.setImage)
        thr.start()

app = QApplication(sys.argv)
win = App()
#win.setAttribute(Qt.WA_DeleteOnClose, True)
win.show()
app.exit(app.exec_())

我认为问题出在信号/插槽的某个地方但是却找不到任何相关的东西。

  • Windows 10
  • Python - 3.7
  • Pyqt - 5.12
  • OpenCV - 3.4.5.20
python python-3.x opencv pyqt5 qthread
1个回答
0
投票

修复了它使用QMutexQWaitCondition来防止主线程已经更新时的更新调用。显然,问题在于此。 eyllanesc,如你所见,我是新来的,我应该在原创帖子中回答一下吗?

from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QMessageBox
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot, Qt, QMutex, QWaitCondition
import cv2
import sys
import time


class CamThread(QThread):
    changemap = pyqtSignal('QImage')

    def __init__(self, mutex, condition):
        super().__init__()
        self.mutex = mutex
        self.condition = condition

    def run(self):
        cap = cv2.VideoCapture(0)
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
        while True:
            try:
                ret, img_rgb = cap.read()
                if ret:
                    rgb = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2RGB)

                    #any other image processing here

                    convert = QImage(rgb.data, rgb.shape[1], rgb.shape[0], QImage.Format_RGB888)
                    p = convert.scaled(640, 480, Qt.KeepAspectRatio)
                    self.changemap.emit(p)
                    self.condition.wait(self.mutex)

            except:
                print('error')


class App(QWidget):
    time = 0

    def __init__(self):
        super().__init__()
        self.title = 'webcam'
        self.mutex = QMutex()
        self.condition = QWaitCondition()
        self.initUI()

    @pyqtSlot('QImage')
    def setImage(self, image):
        self.mutex.lock()
        try:
            self.label.setPixmap(QPixmap.fromImage(image))
        finally:
            self.mutex.unlock()
            self.condition.wakeAll()

    def initUI(self):
        self.mutex.lock()
        self.setWindowTitle(self.title)
        self.setGeometry(100, 100, 640, 480)
        self.resize(640, 480)
        self.label = QLabel(self)
        self.label.resize(640, 480)
        self.thr = CamThread(mutex = self.mutex,condition=self.condition)
        self.thr.changemap.connect(self.setImage)
        self.thr.start()


app = QApplication(sys.argv)
win = App()
win.show()
app.exit(app.exec_())

注:在此示例中,您仍需要正确停止线程并关闭相机连接。

© www.soinside.com 2019 - 2024. All rights reserved.