346 Stimmen

Wie kann ich in Echtzeit in einer while-Schleife mit matplotlib plotten?

Ich versuche, einige Daten von einer Kamera in Echtzeit mit OpenCV zu zeichnen. Allerdings scheint die Echtzeit-Darstellung (mit matplotlib) 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 in diesem Beispiel 1000 Punkte einzeln dargestellt werden. Was tatsächlich passiert, ist, dass das Fenster mit dem ersten Punkt zeigt (ok mit, dass), dann wartet auf die Schleife zu beenden, bevor es den Rest des Diagramms füllt.

Haben Sie eine Idee, warum ich die Punkte nicht einzeln aufführe?

5voto

Michael Mauderer Punkte 3511

Das Problem scheint zu sein, dass Sie erwarten plt.show() um das Fenster anzuzeigen und dann zurückzukehren. Das tut es nicht. Das Programm wird an diesem Punkt angehalten und erst wieder fortgesetzt, wenn Sie das Fenster schließen. Sie sollten das testen können: Wenn Sie das Fenster schließen, sollte sich ein neues Fenster öffnen.

Um dieses Problem zu lösen, rufen Sie einfach plt.show() einmal nach Ihrer Schleife. Dann erhalten Sie die vollständige Handlung. (Aber kein 'Echtzeit-Plotting')

Sie können versuchen, das Schlüsselwort-Argument block wie diese: plt.show(block=False) einmal am Anfang und dann mit .draw() zu aktualisieren.

1voto

user2672474 Punkte 129

Wenn Sie zeichnen und Ihren Thread nicht einfrieren wollen, während mehr Punkte gezeichnet werden, sollten Sie plt.pause() und nicht time.sleep() verwenden.

Ich verwende den folgenden Code, um eine Reihe von xy-Koordinaten darzustellen.

import matplotlib.pyplot as plt 
import math

pi = 3.14159

fig, ax = plt.subplots()

x = []
y = []

def PointsInCircum(r,n=20):
    circle = [(math.cos(2*pi/n*x)*r,math.sin(2*pi/n*x)*r) for x in xrange(0,n+1)]
    return circle

circle_list = PointsInCircum(3, 50)

for t in range(len(circle_list)):
    if t == 0:
        points, = ax.plot(x, y, marker='o', linestyle='--')
        ax.set_xlim(-4, 4) 
        ax.set_ylim(-4, 4) 
    else:
        x_coord, y_coord = circle_list.pop()
        x.append(x_coord)
        y.append(y_coord)
        points.set_data(x, y)
    plt.pause(0.01)

1voto

yogender Punkte 317

Dies ist der richtige Weg zum Plotten Dynamische Echtzeit-Matplot-Plot-Animation mit while-Schleife

Dazu gibt es auch einen Artikel im Medium:

pip install celluloid # dies wird das Bild/die Animation aufnehmen

import matplotlib.pyplot as plt
import numpy as np
from celluloid import Camera # getting the camera
import matplotlib.animation as animation
from IPython import display
import time
from IPython.display import HTML

import warnings
%matplotlib notebook
warnings.filterwarnings('ignore')
warnings.simplefilter('ignore')

fig = plt.figure() #Empty fig object
ax = fig.add_subplot() #Empty axis object
camera = Camera(fig) # Camera object to capture the snap

def f(x):
    ''' function to create a sine wave'''
    return np.sin(x) + np.random.normal(scale=0.1, size=len(x))

l = []

while True:
    value = np.random.randint(9) #random number generator
    l.append(value) # appneds each time number is generated
    X = np.linspace(10, len(l)) # creates a line space for x axis, Equal to the length of l

    for i in range(10): #plots 10 such lines
        plt.plot(X, f(X))

    fig.show() #shows the figure object
    fig.canvas.draw() 
    camera.snap() # camera object to capture teh animation
    time.sleep(1)

Und zum Sparen usw:

animation = camera.animate(interval = 200, repeat = True, repeat_delay = 500)
HTML(animation.to_html5_video())
animation.save('abc.mp4') # to save 

Ausgabe ist:

enter image description here

0voto

Jaakko Punkte 3954

Live-Plot mit kreisförmigem Puffer unter Beibehaltung des Linienstils:

import os
import time
import psutil
import collections

import matplotlib.pyplot as plt

pts_n = 100
x = collections.deque(maxlen=pts_n)
y = collections.deque(maxlen=pts_n)
(line, ) = plt.plot(x, y, linestyle="--")

my_process = psutil.Process(os.getpid())
t_start = time.time()
while True:
    x.append(time.time() - t_start)
    y.append(my_process.cpu_percent())

    line.set_xdata(x)
    line.set_ydata(y)
    plt.gca().relim()
    plt.gca().autoscale_view()
    plt.pause(0.1)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X