Numpy zu QImage Crashing
Der folgende Code stürzt beim Klicken auf die Schaltfläche oder nach einigen Klicks ab, wenn das Signal vom Thread ausgegeben und in der Haupt-GUI abgefangen wird.
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, w, 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,width,3],dtype=np.uint8)
cv_img.fill(255)
print("image shape: ", cv_img.shape)
qimg = convert_np_qimage(cv_img, width, 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_())
Das Programm stürzt nicht ab, wenn Höhe und Breite auf eine kleine Zahl von beispielsweise 3 eingestellt sind. Das Programm stürzt auch nicht ab, wenn wir qimage vor dem Senden in qpixmap konvertieren und den Signaltyp in QPixmap ändern. Das Programm wurde ursprünglich geschrieben, um mit opencv Bilder von der Webcam zu erhalten. Das von opencv erstellte numpy-Array stürzt auch bei großen Bildgrößen ab.
Das verwendete Betriebssystem ist Windows10, die pyqt-Version ist 5.12.3
Irgendeine Idee, was der Grund für den Absturz sein könnte?
Antworten
Unter Linux mit PyQt5 5.15 reproduziere ich das Problem nicht, aber dieser Fehler tritt häufig auf und tritt auf, weil die Übergabe von "Daten" nicht die Informationen kopiert, sondern die Daten gemeinsam genutzt werden. Daher werden cv_img und alle zugehörigen Objekte irgendwann zerstört, einschließlich " Daten "Wenn Sie es also über das Signal übertragen und im QLabel einstellen, werden" Daten "gelesen, es ist jedoch kein Speicher mehr reserviert. Die Lösung in diesem Fall besteht darin, "Daten" zu kopieren:
qim = QtGui.QImage(
cv_img.data.tobytes(), w, h, bytes_per_line, QtGui.QImage.Format_RGB888
)
oder kopieren Sie das QImage.
return qim.copy()