opencv 我怎样才能摆脱错误”信号11:在PyQt5应用程序中使用SIGSEGV来控制网络摄像头?

uinbv5nw  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(100)

我正在写一个应用程序来控制一个带有人脸识别的多储物柜保险箱,我遇到了一个问题,我已经成功地复制了一个小得多的应用程序(代码如下)。在更新#3的文章末尾有更短的代码
为了合并PyQt 5和OpenCV,我遵循了tutorial by docPhil99 on GitHub
每当我尝试使用QThread关闭和打开网络摄像头几次后,我得到一个错误:Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
我在MacOS 13.2.1 OpenCV 4.7.0 PyQt 5上使用来自Anaconda的PyCharm CE和Python 3.10

class VideoThread(QThread):
    change_pixmap_signal = pyqtSignal(np.ndarray)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.cv_img = None
        self.ret = None
        self.camera_needed = False

    def run(self):
        # capture from webcam
        self.camera_needed = True
        self.cap = cv2.VideoCapture(0)
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
        while self.camera_needed:
            self.ret, self.cv_img = self.cap.read()
            if self.ret:
                self.change_pixmap_signal.emit(self.cv_img)

    def stop(self):
        self.cap.release()
        self.camera_needed = False
        self.exit(0)

class TestWindowForCameraOpenAndClose(QWidget):

    def __init__(self):
        super().__init__()

        self.video_thread = VideoThread()
        self.video_thread.change_pixmap_signal.connect(self.refresh_video)

        self.ui()

    def ui(self):
        layout = QHBoxLayout()

        self.camera_preview = QLabel(self)
        self.camera_preview.resize(480, 320)

        turn_on_btn = QPushButton('ON', self)
        turn_on_btn.clicked.connect(self.turn_on)

        turn_off_btn = QPushButton('OFF', self)
        turn_off_btn.clicked.connect(self.turn_off)

        layout.addWidget(self.camera_preview)
        layout.addWidget(turn_on_btn)
        layout.addWidget(turn_off_btn)

        self.setLayout(layout)
        self.show()

    def turn_on(self):
        self.video_thread.start()

    def turn_off(self):
        self.video_thread.stop()

    @pyqtSlot(np.ndarray)
    def refresh_video(self, cv_img):
        qt_img = self.convert_cv_qt(cv_img)
        self.camera_preview.setPixmap(qt_img)

    def convert_cv_qt(self, cv_img):
        rgb_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
        h, w, ch = rgb_img.shape
        bytes_per_line = ch * w
        qt_format = QtGui.QImage(rgb_img.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)
        p = qt_format.scaled(480, 320, Qt.KeepAspectRatio)
        return QPixmap.fromImage(p)

app = QApplication(sys.argv)
w = TestWindowForCameraOpenAndClose()
w.show()
app.exec()

这个程序显然非常简化,但它给出了同样的错误。
我期望它在按开时打开网络摄像头,在按关时关闭。
---- UPDATE ---- Try/except在这里似乎没有帮助,因为它没有捕获这个错误。

  • 更新#2 -当在PyCharm中的Windows 10上运行相同的代码时,Python 3.10从Anaconda而不是分段错误,我得到了这个错误,但程序继续。[ WARN:0@16.708] global cap_msmf.cpp:1759 CvCapture_MSMF::grabFrame videoio(MSMF): can't grab frame. Error: -2147483638
    ----更新#3 ----我试着在OpenCV中只测试相机
import cv2

camera_preview = cv2.VideoCapture(0)
if not camera_preview.isOpened():
    exit()

while (True):
    camera_preview = cv2.VideoCapture(0)
    ret, frame = camera_preview.read()
    if not ret:
        break
    cv2.imshow('frame', frame)

    if cv2.waitKey(0):
        break

camera_preview.release()
cv2.destroyAllWindows()

这应该会给予我一个视频预览,但我只得到一个静态帧,没有视频。然而,此处不存在分段故障错误。
我开始觉得这是OpenCV的错误。
老实说,我没有什么想法,可悲的是,我还没有完全理解QThreads,我没有时间完成我的大学课程申请。提前谢谢你,阿图尔

44u64gxh

44u64gxh1#

变化

def stop(self):

        self.cap.release()
        self.camera_needed = False
        self.exit(0)

致:

def stop(self):

        self.camera_needed = False
        self.wait()
        self.cap.release()

解决了这个问题。
看来,主要的问题是事情的顺序-我试图释放相机,而线程仍在使用其数据。

相关问题