Min*_*ink 4 python multithreading matplotlib multiprocessing pyqtgraph
我试图在我用Python设计的GUI上绘制图像.完整的程序将从相机收集图像数据,然后在GUI上显示图像.我已经探索过使用matplotlib,但它对于我的应用来说太慢了.我需要快速更新的情节(最好尽可能快地从相机中获取,一次是半秒或秒).这对pyqt来说很有挑战性,因为即使使用QThread,情节似乎也只能在主线程上更新,这会导致我的程序停止并且GUI无法被用户访问.
我读到pyqtgraph假设是一个比matplotlib快得多的绘图库.所以我尝试了它并且喜欢它,但它在显示图像时似乎与matplotlib有同样的问题.它会停止整个GUI.我做了一些研究并遇到了这个问题:没有paintEvent绘画,其中一个答案提出使用QtProcess().因此,我的问题是,是否有可能(如果是这样,你能提供一些示例代码)将QtProcess()实现到GUI中,即如何在一个单独的进程中运行GUI?(另外,如果有一种方法可以使用matplotlib,那将非常有帮助.)
这是我设计用来测试我的问题的简单示例.我从pyqtgraph的示例中获取了一个示例脚本,并将pyqtgraph图导入pyqt小部件.然后按下pushButton时,它显示的图表.如果您运行脚本,您会注意到第一个绘图需要很长时间才能加载(6或7秒).再次按下按钮,似乎加载速度更快.我正在QThread()中进行所有数据生成,但是绘图似乎需要主线程才能工作,即使它是在QThread中完成的.我想做与本例中完全相同的事情,除了使用QtProcess()来处理绘图.
欢迎任何有关策划或可能的替代方案的任何其他建议.谢谢
GUI脚本:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'GUI.ui'
#
# Created: Fri Jun 28 14:40:22 2013
# by: PyQt4 UI code generator 4.9.5
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 534)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayout_2 = QtGui.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.scrollArea = QtGui.QScrollArea(self.centralwidget)
self.scrollArea.setFrameShape(QtGui.QFrame.NoFrame)
self.scrollArea.setFrameShadow(QtGui.QFrame.Plain)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
self.scrollAreaWidgetContents = QtGui.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 780, 514))
self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents"))
self.widgetPlot = QtGui.QWidget(self.scrollAreaWidgetContents)
self.widgetPlot.setGeometry(QtCore.QRect(20, 10, 741, 451))
self.widgetPlot.setObjectName(_fromUtf8("widgetPlot"))
self.pushButtonPlot = QtGui.QPushButton(self.scrollAreaWidgetContents)
self.pushButtonPlot.setGeometry(QtCore.QRect(340, 480, 75, 23))
self.pushButtonPlot.setObjectName(_fromUtf8("pushButtonPlot"))
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.gridLayout.addWidget(self.scrollArea, 1, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonPlot.setText(QtGui.QApplication.translate("MainWindow", "Plot", None, QtGui.QApplication.UnicodeUTF8))
Run Code Online (Sandbox Code Playgroud)
包装:
import numpy as np
import scipy
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from GUI import Ui_MainWindow
class MyForm(QMainWindow):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.imv = pg.ImageView()
vbox = QVBoxLayout()
vbox.addWidget(self.imv)
self.ui.widgetPlot.setLayout(vbox)
self.plot_thread = plotData()
self.connect(self.ui.pushButtonPlot, SIGNAL("clicked()"), lambda : self.plot_thread.input(self.imv))
def threadPlot(self):
self.plot_thread.input(self.imv)
def plot(self):
## Create random 3D data set with noisy signals
self.img = scipy.ndimage.gaussian_filter(np.random.normal(size=(200, 200)), (5, 5)) * 20 + 100
self.img = self.img[np.newaxis,:,:]
decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
data = np.random.normal(size=(100, 200, 200))
data += self.img * decay
data += 2
## Add time-varying signal
sig = np.zeros(data.shape[0])
sig[30:] += np.exp(-np.linspace(1,10, 70))
sig[40:] += np.exp(-np.linspace(1,10, 60))
sig[70:] += np.exp(-np.linspace(1,10, 30))
sig = sig[:,np.newaxis,np.newaxis] * 3
data[:,50:60,50:60] += sig
self.imv.setImage(data, xvals=np.linspace(1., 3., data.shape[0]))
class plotData(QThread):
def __init__(self,parent=None):
QThread.__init__(self,parent)
self.exiting = False
def input(self, imv):
self.imv = imv
self.start()
def collectImage(self):
## Create random 3D data set with noisy signals
self.img = scipy.ndimage.gaussian_filter(np.random.normal(size=(200, 200)), (5, 5)) * 20 + 100
self.img = self.img[np.newaxis,:,:]
decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
data = np.random.normal(size=(100, 200, 200))
data += self.img * decay
data += 2
## Add time-varying signal
sig = np.zeros(data.shape[0])
sig[30:] += np.exp(-np.linspace(1,10, 70))
sig[40:] += np.exp(-np.linspace(1,10, 60))
sig[70:] += np.exp(-np.linspace(1,10, 30))
sig = sig[:,np.newaxis,np.newaxis] * 3
data[:,50:60,50:60] += sig
self.imv.setImage(data, xvals=np.linspace(1., 3., data.shape[0]))
def run(self):
self.collectImage()
self.emit(SIGNAL("Done"))
app = QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)
我试图尝试使用QtProcess()(不成功,我不知道如何将QtProcess()小部件导入Qt GUI):
import numpy as np
import scipy
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from GUI import Ui_MainWindow
class MyForm(QMainWindow):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.proc = mp.QtProcess()
self.remotepg = self.proc._import('pyqtgraph')
self.win = self.remotepg.plot()
self.imv = self.win.plot([1,4,2,3], [4,6,3,4], pen=None, symbol='o')
vbox = QVBoxLayout()
vbox.addWidget(self.imv)
self.ui.widgetPlot.setLayout(vbox)
app = QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)
Luk*_*uke 10
在后台工作时,有三种通用方法可以保持GUI响应:
本主题在其他地方进行了广泛讨论,因此我将其留在那里.
考虑到这一点,您发布的代码存在一些问题:
最后,要遵循一条重要规则:如果遇到性能问题,请分析您的代码.在知道导致问题的原因之前,您无法解决问题.