Próbuję wykreślić niektóre dane z kamery w czasie rzeczywistym za pomocą OpenCV. Wydaje się jednak, że drukowanie w czasie rzeczywistym (przy użyciu matplotlib) nie działa.
Wyizolowałem problem w tym prostym przykładzie:
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()
Spodziewałbym się, że ten przykład nakreśli 1000 punktów indywidualnie. Faktycznie dzieje się to, że okno wyskakuje z pierwszym punktem pokazującym (ok z tym), a następnie czeka na zakończenie pętli, zanim zapełni resztę wykresu.
Czy są jakieś przemyślenia, dlaczego nie widzę pojedynczych punktów?
plt.axis()
ale zamiast tego utwórz dwie listy xiy i wywołajplt.plot(x,y)
2. w swojej pętli dodaj nowe wartości danych do dwie listy 3. zadzwońplt.gca().lines[0].set_xdata(x); plt.gca().lines[0].set_ydata(y); plt.gca().relim(); plt.gca().autoscale_view(); plt.pause(0.05);
Jeśli interesuje Cię kreślenie w czasie rzeczywistym, polecam przyjrzenie się API animacji matplotlib . W szczególności użycie w
blit
celu uniknięcia przerysowywania tła na każdej klatce może zapewnić znaczne zwiększenie prędkości (~ 10x):Wynik:
źródło
plt.show()
iplt.draw()
. Dodałem te zmiany do powyższego kodu.blit()
wydaje się być „poprawa kreślenia w czasie rzeczywistym”? Jeśli masz programistę / bloga matplotlib omawiającego, dlaczego / cel / zamiar / motywacja byłaby świetna. (wygląda na to, że ta nowa operacja blit przekształciłaby Matplotlib tylko z trybu offline lub bardzo wolno zmieniających się danych, teraz możesz używać Matplotlib z bardzo szybkimi aktualizacjami danych ... prawie jak oscyloskop).Wiem, że jestem trochę spóźniony, aby odpowiedzieć na to pytanie. Niemniej jednak jakiś czas temu napisałem trochę kodu, aby drukować wykresy na żywo, które chciałbym udostępnić:
Kod dla PyQt4:
Niedawno przepisałem kod dla PyQt5.
Kod dla PyQt5:
Po prostu spróbuj. Skopiuj i wklej ten kod do nowego pliku python i uruchom go. Powinieneś otrzymać piękny, płynnie przesuwający się wykres:
źródło
dataSendLoop
wątek działał w tle po zamknięciu okna. Więc dodałemdaemon = True
słowo kluczowe, aby rozwiązać ten problem.conda install pyqt=4
udało się.show
prawdopodobnie nie jest najlepszym wyborem do tego. Co chciałbym zrobić to użyćpyplot.draw()
zamiast. Możesz także zawrzećtime.sleep(0.05)
w pętli małe opóźnienie czasowe (np. ), Aby zobaczyć przebieg wydarzeń. Jeśli dokonam tych zmian w twoim przykładzie, zadziała to dla mnie i widzę, że każdy punkt pojawia się pojedynczo.źródło
Żadna z metod nie działała dla mnie. Ale znalazłem, że ten wykres matplotlib w czasie rzeczywistym nie działa, gdy wciąż jest w pętli
Wszystko czego potrzebujesz to dodać
i wtedy można zobaczyć nowe wątki.
Twój kod powinien wyglądać tak i będzie działać
źródło
plt.pause()
Bazowano na najlepszych (i wielu innych) odpowiedziach , ale był to stary sposób animowania fabuły w matplotlib. Jest nie tylko powolny, ale także powoduje, że skupia się na każdej aktualizacji (miałem trudności z zatrzymaniem procesu drukowania w Pythonie).TL; DR: możesz użyć
matplotlib.animation
( jak wspomniano w dokumentacji ).Po przeszukaniu różnych odpowiedzi i fragmentów kodu okazało się to dla mnie płynnym sposobem nieskończonego rysowania przychodzących danych.
Oto mój kod na szybki start. Rysuje aktualny czas z losową liczbą w [0, 100) co 200 ms w nieskończoność, a także obsługuje automatyczne przeskalowanie widoku:
Możesz także eksplorować,
blit
aby uzyskać jeszcze lepszą wydajność, jak w dokumentacji FuncAnimation .Przykład z
blit
dokumentacji:źródło
for i in range(1000): x,y = some func_func()
. Tutajsome_func()
generuje sięx,y
pary danych online , które chciałbym wykreślić, gdy będą dostępne. Czy można to zrobić za pomocąFuncAnimation
. Moim celem jest budowanie krzywej zdefiniowanej przez dane krok po kroku przy każdej iteracji.pyploy.show()
powinien zablokować. Jeśli chcesz dołączyć dane, pobierz je i zaktualizuj wupdate
funkcji.pyplot.show
w pętli, pętla zostanie zablokowana przez to połączenie i nie będzie kontynuowana. Jeśli chcesz dołączać dane do krzywej krok po kroku, włącz logikęupdate
, która będzie wywoływana co,interval
aby była również krok po kroku.Wiem, że to pytanie jest stare, ale teraz dostępny jest pakiet o nazwie drawnow na GitHub jako „python-drawnow”. Zapewnia to interfejs podobny do drawnow MATLAB - możesz łatwo zaktualizować figurę.
Przykład twojego przypadku użycia:
Python-drawnow to cienkie opakowanie,
plt.draw
ale zapewnia możliwość potwierdzenia (lub debugowania) po wyświetleniu rysunku.źródło
Problem wydaje się być taki, jakiego oczekujesz
plt.show()
się pokazać okno, a następnie powrócić. Nie robi tego. Program zatrzyma się w tym momencie i wznowi dopiero po zamknięciu okna. Powinieneś być w stanie to sprawdzić: Jeśli zamkniesz okno, a następnie pojawi się kolejne okno.Aby rozwiązać ten problem, po prostu zadzwoń
plt.show()
po pętli. Następnie otrzymujesz pełną fabułę. (Ale nie „spisek w czasie rzeczywistym”)Możesz spróbować ustawić argument-słowo kluczowe w
block
ten sposób:plt.show(block=False)
raz na początku, a następnie użyj go.draw()
do aktualizacji.źródło
Oto wersja, którą mam do pracy w moim systemie.
Linia drawnow (makeFig) może być zastąpiona przez makeFig (); sekwencja plt.draw () i nadal działa OK.
źródło
Jeśli chcesz rysować, a nie zamrozić wątek w miarę rysowania większej liczby punktów, powinieneś użyć plt.pause (), a nie time.sleep ()
używam następującego kodu, aby wykreślić serię współrzędnych xy.
źródło
Inną opcją jest przejście z bokeh . IMO to dobra alternatywa przynajmniej dla wykresów w czasie rzeczywistym. Oto wersja kodu bokeh w pytaniu:
i do uruchomienia:
bokeh pokazuje wynik w przeglądarce internetowej za pośrednictwem komunikacji z gniazdem internetowym. Jest to szczególnie przydatne, gdy dane są generowane przez zdalne procesy serwera bezgłowego.
źródło
Przykładowy przypadek użycia do wykreślenia wykorzystania procesora w czasie rzeczywistym.
źródło