¿Cómo trazo en tiempo real en un ciclo while?

17 minutos de lectura

Avatar de usuario de Chris
cris

Estoy tratando de trazar algunos datos de una cámara en tiempo real usando OpenCV. Sin embargo, el trazado en tiempo real (usando matplotlib) no parece funcionar.

He aislado el problema en este simple ejemplo:

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()

Esperaría que este ejemplo trazara 1000 puntos individualmente. Lo que realmente sucede es que la ventana aparece mostrando el primer punto (está bien), luego espera a que termine el ciclo antes de llenar el resto del gráfico.

¿Alguna idea de por qué no veo puntos poblados uno a la vez?

Avatar de usuario de Velimir Mlaker
Velimir Mlaker

Aquí está la versión de trabajo del código en cuestión (requiere al menos la versión Matplotlib 1.1.0 del 2011-11-14):

import numpy as np
import matplotlib.pyplot as plt

plt.axis([0, 10, 0, 1])

for i in range(10):
    y = np.random.random()
    plt.scatter(i, y)
    plt.pause(0.05)

plt.show()

Tenga en cuenta la llamada a plt.pause(0.05)que dibuja los nuevos datos y ejecuta el ciclo de eventos de la GUI (permitiendo la interacción del mouse).

  • Esto funcionó para mí en Python2. En Python3 no lo hizo. Haría una pausa en el bucle después de representar la ventana de trazado. Pero después de mover el método plt.show() después del bucle… lo resolvió para Python3, para mí.

    – continua qa

    5 sep 2014 a las 18:36

  • Extraño, funcionó bien para mí en Python 3 (ver 3.4.0) Matplotlib (ver 1.3.1) Numpy (ver 1.8.1) Ubuntu Linux 3.13.0 de 64 bits

    – Velimir Mlaker

    12/09/2014 a las 14:58


  • en lugar de plt.show() y plt.draw() simplemente reemplace plt.draw() con plt.pause(0.1)

    – denfromufa

    25 de septiembre de 2014 a las 22:17

  • No funcionó en Win64/Anaconda matplotlib.__version__ 1.5.0. Se abrió una ventana de figura inicial, pero no mostró nada, permaneció en un estado bloqueado hasta que la cerré

    – isti_spl

    4 de febrero de 2016 a las 8:39


  • Esta respuesta requiere un conocimiento a priori de los datos x/y… que no es necesario: prefiero 1. no llamar plt.axis() pero en su lugar crea dos listas x e y y llama plt.plot(x,y) 2. en su bucle, agregue nuevos valores de datos a las dos listas 3. llame 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);

    – Trevor Boyd Smith

    13 de abril de 2016 a las 18:09


avatar de usuario de ali_m
ali_m

Si está interesado en el trazado en tiempo real, le recomiendo que investigue API de animación de matplotlib. En particular, usando blit para evitar volver a dibujar el fondo en cada cuadro puede brindarle ganancias de velocidad sustanciales (~ 10x):

#!/usr/bin/env python

import numpy as np
import time
import matplotlib
matplotlib.use('GTKAgg')
from matplotlib import pyplot as plt


def randomwalk(dims=(256, 256), n=20, sigma=5, alpha=0.95, seed=1):
    """ A simple random walk with memory """

    r, c = dims
    gen = np.random.RandomState(seed)
    pos = gen.rand(2, n) * ((r,), (c,))
    old_delta = gen.randn(2, n) * sigma

    while True:
        delta = (1. - alpha) * gen.randn(2, n) * sigma + alpha * old_delta
        pos += delta
        for ii in xrange(n):
            if not (0. <= pos[0, ii] < r):
                pos[0, ii] = abs(pos[0, ii] % r)
            if not (0. <= pos[1, ii] < c):
                pos[1, ii] = abs(pos[1, ii] % c)
        old_delta = delta
        yield pos


def run(niter=1000, doblit=True):
    """
    Display the simulation using matplotlib, optionally using blit for speed
    """

    fig, ax = plt.subplots(1, 1)
    ax.set_aspect('equal')
    ax.set_xlim(0, 255)
    ax.set_ylim(0, 255)
    ax.hold(True)
    rw = randomwalk()
    x, y = rw.next()

    plt.show(False)
    plt.draw()

    if doblit:
        # cache the background
        background = fig.canvas.copy_from_bbox(ax.bbox)

    points = ax.plot(x, y, 'o')[0]
    tic = time.time()

    for ii in xrange(niter):

        # update the xy data
        x, y = rw.next()
        points.set_data(x, y)

        if doblit:
            # restore background
            fig.canvas.restore_region(background)

            # redraw just the points
            ax.draw_artist(points)

            # fill in the axes rectangle
            fig.canvas.blit(ax.bbox)

        else:
            # redraw everything
            fig.canvas.draw()

    plt.close(fig)
    print "Blit = %s, average FPS: %.2f" % (
        str(doblit), niter / (time.time() - tic))

if __name__ == '__main__':
    run(doblit=False)
    run(doblit=True)

Producción:

Blit = False, average FPS: 54.37
Blit = True, average FPS: 438.27

  • @bejota La versión original fue diseñada para funcionar dentro de una sesión interactiva de matplotlib. Para que funcione como un script independiente, es necesario 1) seleccionar explícitamente un backend para matplotlib, y 2) forzar la visualización y el dibujo de la figura antes de ingresar al ciclo de animación usando plt.show() y plt.draw(). He agregado estos cambios al código anterior.

    – ali_m

    2 de febrero de 2015 a las 10:41

  • ¿Es la intención/motivación del blit() parece mucho ser “mejorar el trazado en tiempo real”? Si tiene un desarrollador/blog de matplotlib discutiendo el por qué/propósito/intención/motivación, sería genial. (Parece que esta nueva operación de blit convertiría a Matplotlib de un uso exclusivo para datos fuera de línea o que cambian muy lentamente a ahora puede usar Matplotlib con datos de actualización muy rápidos… casi como un osciloscopio).

    – Trevor Boyd Smith

    14/04/2016 a las 13:43

  • Descubrí que este enfoque hace que la ventana de trazado no responda: no puedo interactuar con ella y, al hacerlo, podría fallar.

    – Ninjakannon

    29 de diciembre de 2016 a las 4:44

  • Para aquellos que tienen el problema de “gtk no encontrado”, funciona bien con un back-end diferente (utilicé ‘TKAgg’). Para encontrar un respaldo compatible, utilicé esta solución: stackoverflow.com/questions/3285193/…

    –James Nelson

    26 de abril de 2017 a las 0:15

  • El enlace en esta respuesta ya no parece funcionar. Este podría ser un enlace actualizado: scipy-cookbook.readthedocs.io/items/…

    – awelkie

    21/07/2017 a las 14:00

Avatar de usuario de K.Mulier
K.Mulier

Sé que llego un poco tarde para responder a esta pregunta. Sin embargo, hice un código hace un tiempo para trazar gráficos en vivo, que me gustaría compartir:

Código para PyQt4:

###################################################################
#                                                                 #
#                    PLOT A LIVE GRAPH (PyQt4)                    #
#                  -----------------------------                  #
#            EMBED A MATPLOTLIB ANIMATION INSIDE YOUR             #
#            OWN GUI!                                             #
#                                                                 #
###################################################################


import sys
import os
from PyQt4 import QtGui
from PyQt4 import QtCore
import functools
import numpy as np
import random as rd
import matplotlib
matplotlib.use("Qt4Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import time
import threading


def setCustomSize(x, width, height):
    sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
    sizePolicy.setHorizontalStretch(0)
    sizePolicy.setVerticalStretch(0)
    sizePolicy.setHeightForWidth(x.sizePolicy().hasHeightForWidth())
    x.setSizePolicy(sizePolicy)
    x.setMinimumSize(QtCore.QSize(width, height))
    x.setMaximumSize(QtCore.QSize(width, height))

''''''

class CustomMainWindow(QtGui.QMainWindow):

    def __init__(self):

        super(CustomMainWindow, self).__init__()

        # Define the geometry of the main window
        self.setGeometry(300, 300, 800, 400)
        self.setWindowTitle("my first window")

        # Create FRAME_A
        self.FRAME_A = QtGui.QFrame(self)
        self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QtGui.QColor(210,210,235,255).name())
        self.LAYOUT_A = QtGui.QGridLayout()
        self.FRAME_A.setLayout(self.LAYOUT_A)
        self.setCentralWidget(self.FRAME_A)

        # Place the zoom button
        self.zoomBtn = QtGui.QPushButton(text="zoom")
        setCustomSize(self.zoomBtn, 100, 50)
        self.zoomBtn.clicked.connect(self.zoomBtnAction)
        self.LAYOUT_A.addWidget(self.zoomBtn, *(0,0))

        # Place the matplotlib figure
        self.myFig = CustomFigCanvas()
        self.LAYOUT_A.addWidget(self.myFig, *(0,1))

        # Add the callbackfunc to ..
        myDataLoop = threading.Thread(name="myDataLoop", target = dataSendLoop, daemon = True, args = (self.addData_callbackFunc,))
        myDataLoop.start()

        self.show()

    ''''''


    def zoomBtnAction(self):
        print("zoom in")
        self.myFig.zoomIn(5)

    ''''''

    def addData_callbackFunc(self, value):
        # print("Add data: " + str(value))
        self.myFig.addData(value)



''' End Class '''


class CustomFigCanvas(FigureCanvas, TimedAnimation):

    def __init__(self):

        self.addedData = []
        print(matplotlib.__version__)

        # The data
        self.xlim = 200
        self.n = np.linspace(0, self.xlim - 1, self.xlim)
        a = []
        b = []
        a.append(2.0)
        a.append(4.0)
        a.append(2.0)
        b.append(4.0)
        b.append(3.0)
        b.append(4.0)
        self.y = (self.n * 0.0) + 50

        # The window
        self.fig = Figure(figsize=(5,5), dpi=100)
        self.ax1 = self.fig.add_subplot(111)


        # self.ax1 settings
        self.ax1.set_xlabel('time')
        self.ax1.set_ylabel('raw data')
        self.line1 = Line2D([], [], color="blue")
        self.line1_tail = Line2D([], [], color="red", linewidth=2)
        self.line1_head = Line2D([], [], color="red", marker="o", markeredgecolor="r")
        self.ax1.add_line(self.line1)
        self.ax1.add_line(self.line1_tail)
        self.ax1.add_line(self.line1_head)
        self.ax1.set_xlim(0, self.xlim - 1)
        self.ax1.set_ylim(0, 100)


        FigureCanvas.__init__(self, self.fig)
        TimedAnimation.__init__(self, self.fig, interval = 50, blit = True)

    def new_frame_seq(self):
        return iter(range(self.n.size))

    def _init_draw(self):
        lines = [self.line1, self.line1_tail, self.line1_head]
        for l in lines:
            l.set_data([], [])

    def addData(self, value):
        self.addedData.append(value)

    def zoomIn(self, value):
        bottom = self.ax1.get_ylim()[0]
        top = self.ax1.get_ylim()[1]
        bottom += value
        top -= value
        self.ax1.set_ylim(bottom,top)
        self.draw()


    def _step(self, *args):
        # Extends the _step() method for the TimedAnimation class.
        try:
            TimedAnimation._step(self, *args)
        except Exception as e:
            self.abc += 1
            print(str(self.abc))
            TimedAnimation._stop(self)
            pass

    def _draw_frame(self, framedata):
        margin = 2
        while(len(self.addedData) > 0):
            self.y = np.roll(self.y, -1)
            self.y[-1] = self.addedData[0]
            del(self.addedData[0])


        self.line1.set_data(self.n[ 0 : self.n.size - margin ], self.y[ 0 : self.n.size - margin ])
        self.line1_tail.set_data(np.append(self.n[-10:-1 - margin], self.n[-1 - margin]), np.append(self.y[-10:-1 - margin], self.y[-1 - margin]))
        self.line1_head.set_data(self.n[-1 - margin], self.y[-1 - margin])
        self._drawn_artists = [self.line1, self.line1_tail, self.line1_head]

''' End Class '''

# You need to setup a signal slot mechanism, to 
# send data to your GUI in a thread-safe way.
# Believe me, if you don't do this right, things
# go very very wrong..
class Communicate(QtCore.QObject):
    data_signal = QtCore.pyqtSignal(float)

''' End Class '''


def dataSendLoop(addData_callbackFunc):
    # Setup the signal-slot mechanism.
    mySrc = Communicate()
    mySrc.data_signal.connect(addData_callbackFunc)

    # Simulate some data
    n = np.linspace(0, 499, 500)
    y = 50 + 25*(np.sin(n / 8.3)) + 10*(np.sin(n / 7.5)) - 5*(np.sin(n / 1.5))
    i = 0

    while(True):
        if(i > 499):
            i = 0
        time.sleep(0.1)
        mySrc.data_signal.emit(y[i]) # <- Here you emit a signal!
        i += 1
    ###
###


if __name__== '__main__':
    app = QtGui.QApplication(sys.argv)
    QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique'))
    myGUI = CustomMainWindow()
    sys.exit(app.exec_())

''''''

Recientemente reescribí el código para PyQt5.
Código para PyQt5:

###################################################################
#                                                                 #
#                    PLOT A LIVE GRAPH (PyQt5)                    #
#                  -----------------------------                  #
#            EMBED A MATPLOTLIB ANIMATION INSIDE YOUR             #
#            OWN GUI!                                             #
#                                                                 #
###################################################################

import sys
import os
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import functools
import numpy as np
import random as rd
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import time
import threading

class CustomMainWindow(QMainWindow):
    def __init__(self):
        super(CustomMainWindow, self).__init__()
        # Define the geometry of the main window
        self.setGeometry(300, 300, 800, 400)
        self.setWindowTitle("my first window")
        # Create FRAME_A
        self.FRAME_A = QFrame(self)
        self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QColor(210,210,235,255).name())
        self.LAYOUT_A = QGridLayout()
        self.FRAME_A.setLayout(self.LAYOUT_A)
        self.setCentralWidget(self.FRAME_A)
        # Place the zoom button
        self.zoomBtn = QPushButton(text="zoom")
        self.zoomBtn.setFixedSize(100, 50)
        self.zoomBtn.clicked.connect(self.zoomBtnAction)
        self.LAYOUT_A.addWidget(self.zoomBtn, *(0,0))
        # Place the matplotlib figure
        self.myFig = CustomFigCanvas()
        self.LAYOUT_A.addWidget(self.myFig, *(0,1))
        # Add the callbackfunc to ..
        myDataLoop = threading.Thread(name="myDataLoop", target = dataSendLoop, daemon = True, args = (self.addData_callbackFunc,))
        myDataLoop.start()
        self.show()
        return

    def zoomBtnAction(self):
        print("zoom in")
        self.myFig.zoomIn(5)
        return

    def addData_callbackFunc(self, value):
        # print("Add data: " + str(value))
        self.myFig.addData(value)
        return

''' End Class '''


class CustomFigCanvas(FigureCanvas, TimedAnimation):
    def __init__(self):
        self.addedData = []
        print(matplotlib.__version__)
        # The data
        self.xlim = 200
        self.n = np.linspace(0, self.xlim - 1, self.xlim)
        a = []
        b = []
        a.append(2.0)
        a.append(4.0)
        a.append(2.0)
        b.append(4.0)
        b.append(3.0)
        b.append(4.0)
        self.y = (self.n * 0.0) + 50
        # The window
        self.fig = Figure(figsize=(5,5), dpi=100)
        self.ax1 = self.fig.add_subplot(111)
        # self.ax1 settings
        self.ax1.set_xlabel('time')
        self.ax1.set_ylabel('raw data')
        self.line1 = Line2D([], [], color="blue")
        self.line1_tail = Line2D([], [], color="red", linewidth=2)
        self.line1_head = Line2D([], [], color="red", marker="o", markeredgecolor="r")
        self.ax1.add_line(self.line1)
        self.ax1.add_line(self.line1_tail)
        self.ax1.add_line(self.line1_head)
        self.ax1.set_xlim(0, self.xlim - 1)
        self.ax1.set_ylim(0, 100)
        FigureCanvas.__init__(self, self.fig)
        TimedAnimation.__init__(self, self.fig, interval = 50, blit = True)
        return

    def new_frame_seq(self):
        return iter(range(self.n.size))

    def _init_draw(self):
        lines = [self.line1, self.line1_tail, self.line1_head]
        for l in lines:
            l.set_data([], [])
        return

    def addData(self, value):
        self.addedData.append(value)
        return

    def zoomIn(self, value):
        bottom = self.ax1.get_ylim()[0]
        top = self.ax1.get_ylim()[1]
        bottom += value
        top -= value
        self.ax1.set_ylim(bottom,top)
        self.draw()
        return

    def _step(self, *args):
        # Extends the _step() method for the TimedAnimation class.
        try:
            TimedAnimation._step(self, *args)
        except Exception as e:
            self.abc += 1
            print(str(self.abc))
            TimedAnimation._stop(self)
            pass
        return

    def _draw_frame(self, framedata):
        margin = 2
        while(len(self.addedData) > 0):
            self.y = np.roll(self.y, -1)
            self.y[-1] = self.addedData[0]
            del(self.addedData[0])

        self.line1.set_data(self.n[ 0 : self.n.size - margin ], self.y[ 0 : self.n.size - margin ])
        self.line1_tail.set_data(np.append(self.n[-10:-1 - margin], self.n[-1 - margin]), np.append(self.y[-10:-1 - margin], self.y[-1 - margin]))
        self.line1_head.set_data(self.n[-1 - margin], self.y[-1 - margin])
        self._drawn_artists = [self.line1, self.line1_tail, self.line1_head]
        return

''' End Class '''


# You need to setup a signal slot mechanism, to
# send data to your GUI in a thread-safe way.
# Believe me, if you don't do this right, things
# go very very wrong..
class Communicate(QObject):
    data_signal = pyqtSignal(float)

''' End Class '''



def dataSendLoop(addData_callbackFunc):
    # Setup the signal-slot mechanism.
    mySrc = Communicate()
    mySrc.data_signal.connect(addData_callbackFunc)

    # Simulate some data
    n = np.linspace(0, 499, 500)
    y = 50 + 25*(np.sin(n / 8.3)) + 10*(np.sin(n / 7.5)) - 5*(np.sin(n / 1.5))
    i = 0

    while(True):
        if(i > 499):
            i = 0
        time.sleep(0.1)
        mySrc.data_signal.emit(y[i]) # <- Here you emit a signal!
        i += 1
    ###
###

if __name__== '__main__':
    app = QApplication(sys.argv)
    QApplication.setStyle(QStyleFactory.create('Plastique'))
    myGUI = CustomMainWindow()
    sys.exit(app.exec_())

Solo pruébalo. Copie y pegue este código en un nuevo archivo python y ejecútelo. Deberías obtener un hermoso gráfico que se mueva suavemente:

ingrese la descripción de la imagen aquí

  • Me di cuenta de que el dataSendLoop el hilo seguía ejecutándose en segundo plano cuando cerraba la ventana. Así que agregué el daemon = True palabra clave para resolver ese problema.

    – K.Mulier

    26 de septiembre de 2016 a las 9:21

  • El entorno virtual para esto tomó un poco de trabajo. Finalmente, conda install pyqt=4 Hizo el truco.

    – Cabaña Reb

    29 de junio de 2018 a las 4:20

  • Muchas gracias por el código básico. Me ayudó a crear una interfaz de usuario simple modificando y agregando funciones en función de su código. Me salvó el tiempo =]

    –Isaac Sim

    18 de diciembre de 2018 a las 0:30

  • @DavidCian, no hay mejor alternativa que una publicación con código de trabajo

    – Pablo

    19 de mayo de 2022 a las 1:56

  • @Paul Genial, aquí es, de mi propio caso de uso. Si el código funcional fuera siempre un buen código, la ingeniería de software no existiría ;). Resulta que, de hecho, PyQtGraph es objetivamente mejor, ya que está diseñado para el trazado en línea desde el principio, muy diferente a Matplotlib.

    –David Cian

    19 de mayo de 2022 a las 12:27

Avatar de usuario de Hai Zhang
hai zhang

Las respuestas principales (y muchas otras) se basaron en plt.pause(), pero esa era una forma antigua de animar la trama en matplotlib. No solo es lento, sino que también hace que la atención se centre en cada actualización (me costó mucho detener el proceso de trazado de Python).

TL;RD: es posible que desee utilizar matplotlib.animation (como se menciona en la documentación).

Después de investigar varias respuestas y piezas de código, de hecho, esta resultó ser una forma fluida de dibujar infinitamente los datos entrantes para mí.

Aquí está mi código para un inicio rápido. Traza la hora actual con un número aleatorio en[0100)cada200msinfinitamentealmismotiempoquemanejaelreescaladoautomáticodelavista:[0100)every200msinfinitelywhilealsohandlingautorescalingoftheview:

from datetime import datetime
from matplotlib import pyplot
from matplotlib.animation import FuncAnimation
from random import randrange

x_data, y_data = [], []

figure = pyplot.figure()
line, = pyplot.plot_date(x_data, y_data, '-')

def update(frame):
    x_data.append(datetime.now())
    y_data.append(randrange(0, 100))
    line.set_data(x_data, y_data)
    figure.gca().relim()
    figure.gca().autoscale_view()
    return line,

animation = FuncAnimation(figure, update, interval=200)

pyplot.show()

También puedes explorar blit para un rendimiento aún mejor como en la documentación de FuncAnimation.

Un ejemplo de la blit documentación:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')

def init():
    ax.set_xlim(0, 2*np.pi)
    ax.set_ylim(-1, 1)
    return ln,

def update(frame):
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    return ln,

ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
                    init_func=init, blit=True)
plt.show()

Avatar de usuario de Oren
Orén

Ninguno de los métodos funcionó para mí. Pero descubrí que este diagrama de matplotlib en tiempo real no funciona mientras aún está en un bucle

Todo lo que necesitas es agregar

plt.pause(0.0001)

y luego se podían ver las nuevas tramas.

Entonces su código debería verse así, y funcionará

import matplotlib.pyplot as plt
import numpy as np
plt.ion() ## Note this correction
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()
    plt.pause(0.0001) #Note this correction

  • Esto abre una nueva ventana de figura/trama cada vez para mí. ¿Hay alguna forma de actualizar la figura existente? tal vez es porque estoy usando imshow?

    –Francisco Vargas

    26 de enero de 2016 a las 2:27

  • @FranciscoVargas si está usando imshow, necesita usar set_data, mire aquí: stackoverflow.com/questions/17835302/…

    – Oren

    11 de diciembre de 2016 a las 7:14

Avatar de usuario de BrenBarn
BrenBarn

show probablemente no sea la mejor opción para esto. yo lo que haria es usar pyplot.draw() en cambio. También es posible que desee incluir un pequeño retraso de tiempo (por ejemplo, time.sleep(0.05)) en el ciclo para que pueda ver las tramas que suceden. Si hago estos cambios en su ejemplo, me funciona y veo que cada punto aparece uno a la vez.

  • Esto abre una nueva ventana de figura/trama cada vez para mí. ¿Hay alguna forma de actualizar la figura existente? tal vez es porque estoy usando imshow?

    –Francisco Vargas

    26 de enero de 2016 a las 2:27

  • @FranciscoVargas si está usando imshow, necesita usar set_data, mire aquí: stackoverflow.com/questions/17835302/…

    – Oren

    11 de diciembre de 2016 a las 7:14

Sé que esta pregunta es antigua, pero ahora hay un paquete disponible llamado dibujado ahora en GitHub como “python-drawingow”. Esto proporciona una interfaz similar a Drawow de MATLAB: puede fácilmente actualizar una figura.

Un ejemplo para su caso de uso:

import matplotlib.pyplot as plt
from drawnow import drawnow

def make_fig():
    plt.scatter(x, y)  # I think you meant this

plt.ion()  # enable interactivity
fig = plt.figure()  # make a figure

x = list()
y = list()

for i in range(1000):
    temp_y = np.random.random()
    x.append(i)
    y.append(temp_y)  # or any arbitrary update to your figure's data
    i += 1
    drawnow(make_fig)

python-drarawow es un envoltorio delgado alrededor plt.draw pero proporciona la capacidad de confirmar (o depurar) después de la visualización de la figura.

  • Esto hace que tk cuelgue en alguna parte

    – chwi

    17 de noviembre de 2015 a las 10:49

  • Si es así, presente un problema con más contexto github.com/scottsievert/python-drawedow/issues

    – Scott

    18 de noviembre de 2015 a las 15:49


  • +1 Esto funcionó para mí para trazar datos en vivo por cuadro de captura de video de opencv, mientras que matplotlib se congeló.

    – jj080808

    20 de febrero de 2017 a las 1:58

  • Intenté esto y parecía más lento que otros métodos.

    – Dave C.

    03/12/2018 a las 23:50

  • no usar, mi servidor se reinicia, matplotlib congelado

    – grande-vl

    4 abr 2020 a las 20:52

¿Ha sido útil esta solución?