Ich versuche, einige Daten von einer Kamera in Echtzeit mit OpenCV zu zeichnen. Das Echtzeit-Plotten (mit matplotlib) scheint jedoch nicht zu funktionieren.
Ich habe das Problem in diesem einfachen Beispiel isoliert:
fig = plt.figure()
plt.axis([0, 1000, 0, 1])
i = 0
x = list()
y = list()
while i < 1000:
temp_y = np.random.random()
x.append(i)
y.append(temp_y)
plt.scatter(i, temp_y)
i += 1
plt.show()
Ich würde erwarten, dass dieses Beispiel 1000 Punkte einzeln darstellt. Was tatsächlich passiert, ist, dass das Fenster mit dem ersten angezeigten Punkt (ok damit) angezeigt wird und dann darauf wartet, dass die Schleife beendet ist, bevor der Rest des Diagramms ausgefüllt wird.
Irgendwelche Gedanken, warum ich nicht sehe, dass Punkte einzeln besetzt sind?
plt.axis()
sondern zwei Listen x und y erstellen undplt.plot(x,y)
2. in Ihrer Schleife neue Datenwerte anhängen die zwei Listen 3. Anrufplt.gca().lines[0].set_xdata(x); plt.gca().lines[0].set_ydata(y); plt.gca().relim(); plt.gca().autoscale_view(); plt.pause(0.05);
Wenn Sie an Echtzeit-Plots interessiert sind, empfehlen wir Ihnen, sich die Animations-API von matplotlib anzusehen . Insbesondere die Verwendung
blit
, um zu vermeiden, dass der Hintergrund in jedem Frame neu gezeichnet wird, kann zu erheblichen Geschwindigkeitsgewinnen führen (~ 10x):Ausgabe:
quelle
plt.show()
und in die Animationsschleife eintretenplt.draw()
. Ich habe diese Änderungen zum obigen Code hinzugefügt.blit()
scheinbar "Verbesserung des Echtzeit-Plots"? Wenn Sie einen matplotlib-Entwickler / Blog haben, der das Warum / den Zweck / die Absicht / die Motivation bespricht, wäre das großartig. (Anscheinend würde diese neue Blit-Operation Matplotlib von der Verwendung nur für Offline- oder sehr langsam wechselnde Daten konvertieren. Jetzt können Sie Matplotlib mit sehr schnell aktualisierten Daten verwenden ... fast wie ein Oszilloskop).Ich weiß, dass ich etwas spät dran bin, um diese Frage zu beantworten. Trotzdem habe ich vor einiger Zeit Code erstellt, um Live-Diagramme zu zeichnen, die ich gerne teilen möchte:
Code für PyQt4:
Ich habe kürzlich den Code für PyQt5 neu geschrieben.
Code für PyQt5:
Probieren Sie es einfach aus. Kopieren Sie diesen Code, fügen Sie ihn in eine neue Python-Datei ein und führen Sie ihn aus. Sie sollten ein schönes, sich reibungslos bewegendes Diagramm erhalten:
quelle
dataSendLoop
Thread im Hintergrund weiter lief, wenn Sie das Fenster schließen. Also habe ich dasdaemon = True
Schlüsselwort hinzugefügt , um dieses Problem zu lösen.conda install pyqt=4
hat der Trick.show
ist wahrscheinlich nicht die beste Wahl dafür. Was ich tun würde, istpyplot.draw()
stattdessen zu verwenden. Möglicherweise möchten Sie auch eine kleine Zeitverzögerung (z. B.time.sleep(0.05)
) in die Schleife aufnehmen, damit Sie sehen können, wie die Diagramme ausgeführt werden. Wenn ich diese Änderungen an Ihrem Beispiel vornehme, funktioniert dies für mich und ich sehe, dass jeder Punkt einzeln angezeigt wird.quelle
Keine der Methoden hat bei mir funktioniert. Aber ich habe festgestellt, dass dieser Echtzeit-Matplotlib-Plot nicht funktioniert, während er sich noch in einer Schleife befindet
Alles was Sie brauchen, ist hinzuzufügen
und dann konnte man die neuen Handlungen sehen.
Ihr Code sollte also so aussehen, und es wird funktionieren
quelle
Die besten (und viele andere) Antworten wurden aufgebaut
plt.pause()
, aber das war eine alte Art, die Handlung in matplotlib zu animieren. Es ist nicht nur langsam, sondern führt auch dazu, dass bei jedem Update der Fokus erfasst wird (es fiel mir schwer, den Plot-Python-Prozess zu stoppen).TL; DR: Möglicherweise möchten Sie verwenden
matplotlib.animation
( wie in der Dokumentation erwähnt ).Nachdem ich verschiedene Antworten und Codeteile durchgesehen hatte, erwies sich dies für mich als eine reibungslose Möglichkeit, eingehende Daten unendlich zu zeichnen.
Hier ist mein Code für einen schnellen Start. Es zeichnet die aktuelle Zeit mit einer Zufallszahl in [0, 100] alle 200 ms unendlich auf und behandelt gleichzeitig die automatische Neuskalierung der Ansicht:
Sie können auch
blit
nach einer noch besseren Leistung suchen, wie in der FuncAnimation-Dokumentation .Ein Beispiel aus der
blit
Dokumentation:quelle
for i in range(1000): x,y = some func_func()
. Hier werdensome_func()
Online-x,y
Datenpaare generiert , die ich zeichnen möchte, sobald sie verfügbar sind. Ist es möglich, dies mit zu tunFuncAnimation
. Mein Ziel ist es, die durch die Daten definierte Kurve Schritt für Schritt mit jeder Iteration zu erstellen.pyploy.show()
sollte blockieren. Wenn Sie Daten anhängen möchten, rufen Sie diese ab und aktualisieren Sie sie in derupdate
Funktion.pyplot.show
in einer Schleife aufrufen , wird die Schleife durch diesen Aufruf blockiert und nicht fortgesetzt. Wenn Sie Daten Schritt für Schritt an die Kurve anhängen möchten, geben Sie Ihre Logik einupdate
, die jeweils aufgerufen wird,interval
damit sie auch Schritt für Schritt ausgeführt wird.Ich weiß, dass diese Frage alt ist, aber es gibt jetzt ein Paket namens drawow auf GitHub als "python-drawow". Dies bietet eine Oberfläche ähnlich der von MATLAB gezeichneten - Sie können eine Figur einfach aktualisieren.
Ein Beispiel für Ihren Anwendungsfall:
Python-Drawow ist ein dünner Wrapper
plt.draw
, bietet jedoch die Möglichkeit, nach der Anzeige der Abbildung zu bestätigen (oder zu debuggen).quelle
Das Problem scheint zu sein, dass Sie erwarten
plt.show()
, das Fenster anzuzeigen und dann zurückzukehren. Das macht es nicht. Das Programm stoppt an diesem Punkt und wird erst fortgesetzt, wenn Sie das Fenster schließen. Sie sollten dies testen können: Wenn Sie das Fenster schließen und dann ein anderes Fenster angezeigt wird.Um dieses Problem zu beheben, rufen
plt.show()
Sie einfach einmal nach Ihrer Schleife auf. Dann erhalten Sie die komplette Handlung. (Aber kein "Echtzeit-Plotten")Sie können versuchen, das Schlüsselwortargument
block
wie folgt festzulegen :plt.show(block=False)
einmal am Anfang und dann.draw()
zum Aktualisieren verwenden.quelle
Hier ist eine Version, die ich auf meinem System arbeiten musste.
Die gezeichnete Linie (makeFig) kann durch eine makeFig () ersetzt werden. plt.draw () Sequenz und es funktioniert immer noch OK.
quelle
Wenn Sie Ihren Thread zeichnen und nicht einfrieren möchten, wenn mehr Punkte gezeichnet werden, sollten Sie plt.pause () und nicht time.sleep () verwenden.
Ich benutze den folgenden Code, um eine Reihe von xy-Koordinaten zu zeichnen.
quelle
Eine andere Möglichkeit ist, mit Bokeh zu gehen . IMO, es ist eine gute Alternative, zumindest für Echtzeit-Plots. Hier ist eine Bokeh-Version des Codes in der Frage:
und zum Ausführen:
bokeh zeigt das Ergebnis in einem Webbrowser über Websocket-Kommunikation. Dies ist besonders nützlich, wenn Daten von Remote-Headless-Serverprozessen generiert werden.
quelle
Ein beispielhafter Anwendungsfall zum Zeichnen der CPU-Auslastung in Echtzeit.
quelle