Numpy a QImage si blocca
Il codice seguente si arresta in modo anomalo facendo clic sul pulsante o dopo pochi clic quando il segnale viene emesso dal thread e catturato nella GUI principale.
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_())
Il programma non si blocca se l'altezza e la larghezza sono impostate su un numero piccolo, diciamo 3. Il programma non si blocca anche se convertiamo qimage in qpixmap prima di emettere e cambiamo il tipo di segnale in QPixmap. Il programma è stato originariamente scritto per ottenere immagini dalla webcam utilizzando opencv. Anche l'array numpy creato da opencv si arresta in modo anomalo per immagini di grandi dimensioni.
Il sistema operativo utilizzato è Windows10, la versione di pyqt è 5.12.3
Qualche idea su quale potrebbe essere la ragione dell'incidente?
Risposte
In Linux con PyQt5 5.15 non riproduco il problema, ma quell'errore è comune e si verifica perché il passaggio di "dati" non copia le informazioni ma piuttosto i dati sono condivisi, quindi ad un certo punto cv_img e tutti gli oggetti associati vengono distrutti incluso a " data "quindi quando lo si trasmette attraverso il segnale e lo si imposta nella QLabel che" data "viene letto ma non ha più memoria riservata. La soluzione in questo caso è copiare "dati":
qim = QtGui.QImage(
cv_img.data.tobytes(), w, h, bytes_per_line, QtGui.QImage.Format_RGB888
)
o copia il file QImage.
return qim.copy()