Numpy trước QImage Crashing
Đoạn mã sau bị treo khi nhấp vào nút hoặc sau một vài lần nhấp khi tín hiệu được phát ra từ luồng và bị mắc vào gui chính.
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_())
Chương trình không bị lỗi nếu chiều cao và chiều rộng được đặt thành số nhỏ, chẳng hạn như 3. Chương trình cũng không bị lỗi nếu chúng ta chuyển đổi qimage thành qpixmap trước khi phát ra và thay đổi loại tín hiệu thành QPixmap. Chương trình ban đầu được viết để lấy hình ảnh từ webcam bằng opencv. Mảng numpy do opencv tạo ra cũng bị lỗi đối với kích thước hình ảnh lớn.
Hệ điều hành được sử dụng là Windows10, phiên bản pyqt là 5.12.3
Bất kỳ ý tưởng nào có thể là lý do cho vụ tai nạn?
Trả lời
Trong Linux với PyQt5 5.15, tôi không tái tạo sự cố, nhưng lỗi đó là phổ biến và xảy ra vì việc truyền "dữ liệu" không sao chép thông tin mà là dữ liệu được chia sẻ, vì vậy tại một số điểm cv_img và tất cả các đối tượng liên quan bị phá hủy bao gồm cả đến " dữ liệu "để khi truyền nó thông qua tín hiệu và cài đặt nó trong QLabel rằng" dữ liệu "được đọc nhưng nó không còn bộ nhớ dự trữ. Giải pháp trong trường hợp này là sao chép "dữ liệu":
qim = QtGui.QImage(
cv_img.data.tobytes(), w, h, bytes_per_line, QtGui.QImage.Format_RGB888
)
hoặc sao chép QImage.
return qim.copy()