【问题标题】:Playing image sequence in QGraphicsView (Mysterious Memory Leak)在 QGraphicsView 中播放图像序列(神秘的内存泄漏)
【发布时间】:2018-12-10 07:23:12
【问题描述】:

我正在尝试使用 OpenCV 和 PyQt5 处理图像序列并制作结果视频。我有一些代码循环遍历目录,读取图像,然后尝试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 继承自 QGraphicsScene

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

问题是每次我调用addPixmap() 时,图像都会添加到所有其他图像之上,很快我的内存就会耗尽,一切都崩溃了。 当前代码不包含任何处理步骤,它只是将 numpy ndarry 转换为 QImage 并将 QPixmap 添加到场景中。

更新 QGraphicsScene 以便我可以流式传输一系列图像的正确方法是什么?

【问题讨论】:

  • 我正在尝试制作 10-30 fps 左右的视频。
  • 我正在使用 OpenCV 进行处理。
  • @eyllanesc 处理可能需要一段时间,但现在我有一个最小的示例,就是将图像从 numpy 数组转换为 QImage,然后将 QPixmap 添加到场景中。

标签: python opencv pyqt pyqt5 qgraphicsview


【解决方案1】:

每次使用addPixmap() 时,您都会创建一个新的QGraphicsPixmapItem,从而不必要地添加内存。解决方案是创建一个QGraphicsPixmapItem 并重用它。另外处理任务会阻塞主线程,所以必须使用线程来完成繁重的任务,并通过信号发送QImage

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

【讨论】:

    猜你喜欢
    • 2013-07-25
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    相关资源
    最近更新 更多