PyQt5 – Reproducción de secuencia de imágenes en QGraphicsView (Fuga de memoria misteriosa)

Estoy tratando de procesar una secuencia de imágenes y hacer un video de los resultados utilizando OpenCV y PyQt5. Tengo un código que recorre un directorio, lee las imágenes y trata de mostrarlas en un QGraphicsView .

 def on_start(self): for f in self.image_list: img = cv2.imread(f) img = cv2qimage(img, False) self.scene.set_qimage(img) 

self.scene hereda de QGraphicsScene .

  def set_qimage(self, qimage): self.pixmap = QPixmap.fromImage(qimage) self.addPixmap(self.pixmap) 

El problema es que cada vez que llamo addPixmap() la imagen se agrega sobre todas las demás imágenes y pronto me quedo sin memoria y todo se bloquea. El código actual no incluye ninguno de los pasos de procesamiento, simplemente convierte el número de ndarry en una QImage y agrega el QPixmap a la escena.

¿Cuál es la forma correcta de actualizar QGraphicsScene para que pueda transmitir una secuencia de imágenes?

Cada vez que utiliza addPixmap() está creando un nuevo QGraphicsPixmapItem agregando memoria innecesariamente. La solución es crear un QGraphicsPixmapItem y reutilizarlo. Además, la tarea de procesamiento puede bloquear el subproceso principal, por lo que debe usar un subproceso para realizar la tarea pesada y enviar el QImage través de señales.

 class ProcessWorker(QObject): imageChanged = pyqtSignal(QImage) def doWork(self): for f in self.image_list: img = cv2.imread(f) img = cv2qimage(img, False) self.imageChanged.emit(img) QThread.msleep(1) class Widget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) lay = QVBoxLayout(self) gv = QGraphicsView() lay.addWidget(gv) scene = QGraphicsScene(self) gv.setScene(scene) self.pixmap_item = QGraphicsPixmapItem() scene.addItem(self.pixmap_item) self.workerThread = QThread() self.worker = ProcessWorker() self.worker.moveToThread(self.workerThread) self.workerThread.finished.connect(self.worker.deleteLater) self.workerThread.started.connect(self.worker.doWork) self.worker.imageChanged.connect(self.setImage) self.workerThread.start() @pyqtSlot(QImage) def setImage(self, image): pixmap = QPixmap.fromImage(image) self.pixmap_item.setPixmap(pixmap) if __name__ == '__main__': app = QApplication(sys.argv) w = Widget() w.show() sys.exit(app.exec_())