Numpy to QImage Crashing

Aug 29 2020

Kode berikut macet saat mengklik tombol atau setelah beberapa klik saat sinyal dipancarkan dari utas dan tertangkap di gui utama.

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_())

Program tidak akan crash jika tinggi dan lebar diset ke angka kecil 3. Program juga tidak crash jika kita mengonversi qimage ke qpixmap sebelum memancarkan dan mengubah tipe sinyal menjadi QPixmap. Program ini awalnya ditulis untuk mendapatkan gambar dari webcam menggunakan opencv. Array numpy yang dibuat oleh opencv crash juga untuk ukuran gambar yang besar.

OS yang digunakan adalah Windows10, versi pyqt 5.12.3

Tahu apa yang mungkin menjadi alasan kecelakaan itu?

Jawaban

1 eyllanesc Aug 29 2020 at 12:13

Di Linux dengan PyQt5 5.15 saya tidak mereproduksi masalah, tetapi kesalahan itu umum terjadi dan terjadi karena meneruskan "data" tidak menyalin informasi melainkan data dibagikan, jadi pada beberapa titik cv_img dan semua objek terkait dihancurkan termasuk " data "jadi ketika mentransmisikannya melalui sinyal dan mengaturnya di QLabel bahwa" data "dibaca tetapi tidak lagi memiliki memori yang dipesan. Solusi dalam kasus ini adalah menyalin "data":

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

atau salin QImage.

return qim.copy()