2017-08-29 5 views
2

Ich arbeite an einem Projekt, auf dem ich ein Bild von 320 * 250 Pixeln und dies 60 Mal pro Sekunde wenn möglich auf einem Fenster einer GUI plotten soll. Also versuche ich, dies zu tun mit matplotlib 2.0.2, Python 3.6 und PyQt5 (weil ich beginnen, diese Tools und die Arbeit an einem anderen Projekt mit, dies zu wissen), auf folgende Weise:Matplotlib, Bild mit imshow schneller aktualisieren

import sys, random, matplotlib 
from PyQt5 import QtCore, QtGui, QtWidgets 

matplotlib.use('Qt5Agg') 
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 
import matplotlib.pyplot as plt 

class SecondWindow(QtWidgets.QWidget): 
    def __init__(self, parent=None): 
     super(SecondWindow, self).__init__(parent) 
     self.setupUi(self) 

    def setupUi(self, Form): 
     Form.setObjectName("Form") 
     Form.resize(800, 600) 

     self.figure = plt.figure() 
     self.canvas = FigureCanvas(self.figure) 
     self.axes = self.figure.add_subplot(111) 

     self.setLayout(QtWidgets.QVBoxLayout()) 
     self.layout().addWidget(self.canvas) 

     self.initialisationFigure() 

     self.timer = QtCore.QTimer(self) 
     self.timer.timeout.connect(self.majFigure) 
     self.timer.start(16) 

     self.timer2 = QtCore.QTimer(self) 
     self.timer2.timeout.connect(self.NumberRefreshPerSecond) 
     self.timer2.start(1000) 

    def NumberRefreshPerSecond(self): 
     print(self.count) 
     self.count = 0 

    def majFigure(self): 
     self.count = self.count + 1 
     self.plot.set_data([[random.random() for x in range(1, 320)] for y in range(1, 250)]) 
     # self.canvas.draw() 
     self.axes.draw_artist(self.axes.patch) 
     self.axes.draw_artist(self.plot) 
     self.canvas.update() 
     self.canvas.flush_events() 

    def initialisationFigure(self): 
     self.plot = self.axes.imshow([[random.random() for x in range(1,320)] for y in range(1,250)], interpolation='none') 
     self.count = 0 
     self.canvas.draw() 

    def closeEvent(self, event): 
     self.timer.stop() 

if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) 
    form = SecondWindow() 
    form.show() 
    sys.exit(app.exec_()) 

Ich habe optimiert wie ich die Interpolation ausschalten kann, und nur einmal die Figur zeichnen, aber mit diesem Code wird das Programm nur 20 mal pro Sekunde aktualisiert, während der Timer korrekt auf 16ms (1/60Hz) eingestellt ist.

Ich hoffe, dass jemand mir helfen kann, mir einige Hinweise zu geben, um meinen Code zu verbessern. Ich danke Ihnen im Voraus viel!

+1

Haben Sie einen Blick hatte [matplotlib des 'animation' Modul] (https://matplotlib.org/api/ animation_api.html)? – Paul

+0

Noch nicht, ich werde jetzt und komme zurück, um dir meine neuen fps zu geben. –

+0

FYI, mit 'numpy.random.random ((250, 320))' statt der Schleife, um das Bild zu erstellen gibt einen Boost von 10-15fps auf meinem Rechner – user3419537

Antwort

3

Matplotlib produziert Publikationsqualität Plots, aber es ist leider nicht wirklich geeignet für Echtzeit-Plotten und Videos.

Wenn es keine strenge Anforderung ist, erwägen Sie die Verwendung pyqtgraph module. Es spielt gut mit pyqt5 und entwickelt Mängel von matplotlib zu decken, vor allem in Echtzeit Bereich:

Wenn Sie alles benötigen schnelle Handlung Updates tun, Video oder Echtzeit-Interaktivität, matplotlib nicht die beste Wahl ist. Dies ist (meiner Meinung nach) matplotlib größte Schwäche

(from pyqtgraph site) 

Es bekam auch zusätzliche (optional) Funktionen wie Region-of-Interest, Normalisierung und Histogramm Plotten.

Dieser Code kann produzieren ~ 160 FPS (mit Histogramm deaktiviert) auf meinem Laptop:

import sys, random, matplotlib 
from PyQt5 import QtCore, QtGui, QtWidgets 

import pyqtgraph as pg 
import numpy as np 


class SecondWindow(QtWidgets.QWidget): 
    def __init__(self, parent=None): 
     super(SecondWindow, self).__init__(parent) 
     self.setupUi(self) 

    def setupUi(self, Form): 
     Form.setObjectName("Form") 
     Form.resize(800, 600) 

     self.im_widget = pg.ImageView(self) 
     # uncomment to hide histogram 
     # self.im_widget.ui.histogram.hide() 

     self.setLayout(QtWidgets.QVBoxLayout()) 
     self.layout().addWidget(self.im_widget) 

     self.initialisationFigure() 

     self.timer = QtCore.QTimer(self) 
     self.timer.timeout.connect(self.majFigure) 
     self.timer.start(16) 

     self.timer2 = QtCore.QTimer(self) 
     self.timer2.timeout.connect(self.NumberRefreshPerSecond) 
     self.timer2.start(1000) 

    def NumberRefreshPerSecond(self): 
     print(self.count) 
     self.count = 0 

    def majFigure(self): 
     self.count = self.count + 1 
     # numpy random.rand also much faster than list comprehension 
     data = np.random.rand(320, 250) 
     self.im_widget.setImage(data) 

    def initialisationFigure(self): 
     self.count = 0 
     self.im_widget.show() 

    def closeEvent(self, event): 
     self.timer.stop() 

if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) 
    form = SecondWindow() 
    form.show() 
    sys.exit(app.exec_()) 
+0

60 fps auf meinem Computer, so ist es tatsächlich schneller. Aber ich weiß nicht pyqtgraph. Ist es einfach, mit der Figur als Matplotlib umzugehen (Labels, Zoom, Cursor, etc)? –

+1

In der Tat ist es ein Kompromiss zwischen der Schönheit der Matplotlib und der Geschwindigkeit des Pyqtgraphen. Obwohl pyqtgraph in hohem Maße konfigurierbar ist, konnte ich keine so schönen Plots wie Matplotlibs erstellen. Wie für Ihre Frage - Dinge wie Etiketten, Zoom, Cursor usw. sind vollständig konfigurierbar. Ich schlage vor, Sie installieren pyqtgraph und führen Sie seine Showcase und dann entscheiden: 'python -m pyqtgraph.examples' – 9dogs

Verwandte Themen