Numpy到QImage崩溃

问题描述

当线程中发出信号并捕获到主gui中时,以下代码在单击按钮或单击几下后崩溃。

from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtGui import QPixmap,QImage
from PyQt5.QtCore import pyqtSignal,pyqtSlot,Qt,QThread
import numpy as np
import time
from PyQt5.QtWidgets import QApplication,QDialog,QPushButton,QVBoxLayout


def convert_np_qimage(cv_img,width,height):
    h,w,ch = cv_img.shape
    bytes_per_line = ch * w
    qim = QtGui.QImage(cv_img.data,h,bytes_per_line,QtGui.QImage.Format_RGB888)
    print(qim.size())
    return qim

class VideoThread(QThread):
    change_qimage_signal = pyqtSignal(QImage)
    
    def __init__(self):
        super().__init__()

    def run(self):
        print("run")
        width = 1280
        height = 1280
        
        cv_img = np.zeros([height,3],dtype=np.uint8)
        cv_img.fill(255)
        print("image shape: ",cv_img.shape)

        qimg = convert_np_qimage(cv_img,height)
        self.change_qimage_signal.emit(qimg)
        print("emitted")

        
    def stop(self):
        self.wait()

import sys

class Dialog(QDialog):

    def __init__(self):
        super(Dialog,self).__init__()
        Dialog.resize(self,640,480)
        
        button=QPushButton("Click")
        button.clicked.connect(self.startThread)
        
        mainLayout = QVBoxLayout()
        mainLayout.addWidget(button)
        
        
        self.setLayout(mainLayout)
        self.setWindowTitle("QImage Example")
        
    def startThread(self):
        self.thread = VideoThread()
        self.thread.change_qimage_signal.connect(self.getPixmap)
        self.thread.start()      
        
    def getPixmap(self,qimg):
        print("got qimage")
        qpixmap = QPixmap.fromImage(qimg)
        

if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog = Dialog()
    sys.exit(dialog.exec_())

如果高度和宽度设置为小数值(例如3),则程序不会崩溃。 如果我们在发射并更改信号之前将qimage转换为qpixmap,该程序也不会崩溃 输入到QPixmap。 最初编写该程序是为了使用opencv从网络摄像头获取图像。创建的numpy数组 对于大图像,opencv也会崩溃。

使用的操作系统是Windows10,pyqt版本是5.12.3

您知道崩溃的原因是什么吗?

解决方法

在带有PyQt5 5.15的Linux中,我没有重现该问题,但是该错误很常见,并且由于传递“数据”不复制信息而是共享数据而发生,因此在某些时候cv_img和所有相关对象被破坏了包括“数据”,因此在通过信号传输并将其设置在QLabel中时,将读取“数据”,但不再保留内存。在这种情况下,解决方案是复制“数据”:

qim = QtGui.QImage(
    cv_img.data.tobytes(),w,h,bytes_per_line,QtGui.QImage.Format_RGB888
)

或复制QImage。

return qim.copy()

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...