我正在尝试处理图像序列,并使用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以便流式传输图像序列的正确方法?
答案 0 :(得分: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_())