【问题标题】:Pyqt crashes when trying to show opencv videostreamPyqt 在尝试显示 opencv 视频流时崩溃
【发布时间】:2019-08-13 20:34:00
【问题描述】:

我尝试了来自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

【问题讨论】:

  • self.rgb 更改为rgbself.convert 更改为convertself.p 更改为p
  • 试过了。没有任何改变
  • 在 CMD 中执行它,你应该在那里给你更多的信息
  • 仍然粉碎。在 CMD 中不显示任何内容,甚至是以前的错误。
  • 嗯,你为什么要超过100ms的图像?,相机提供30FPS的图像是30ms,你相机的FPS是多少?

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


【解决方案1】:

使用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_())

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

【讨论】:

    猜你喜欢
    • 2017-11-08
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多