Reputation: 73
The following code crashes on clicking the button or after a few clicks when the signal is emitted from thread and caught in the main 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, 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_())
The program doesn't crash if height and width are set to small number say 3. The program also doesn't crash if we convert qimage to qpixmap before emitting and change the signal type to QPixmap. The program was originally written to get images from webcam using opencv. The numpy array created by opencv crashes too for big image sizes.
The OS used is Windows10, pyqt version is 5.12.3
Any idea what might be the reason for the crash?
Upvotes: 1
Views: 257
Reputation: 243897
In Linux with PyQt5 5.15 I do not reproduce the problem, but that error is common and occurs because passing "data" does not copy the information but rather the data is shared, so at some point cv_img and all associated objects are destroyed including to "data" so when transmitting it through the signal and setting it in the QLabel that "data" is read but it no longer has reserved memory. The solution in this case is to copy "data":
qim = QtGui.QImage(
cv_img.data.tobytes(), w, h, bytes_per_line, QtGui.QImage.Format_RGB888
)
or copy the QImage.
return qim.copy()
Upvotes: 1