Comment mettre à jour la fenêtre imshow() de matplotlib de manière interactive?

je travaille sur un algorithme de vision par ordinateur et j'aimerais montrer comment un tableau numpy change à chaque étape.

Ce qui fonctionne est que si j'ai un simple imshow( array ) a la fin de mon code, la fenêtre affiche et affiche l'image finale.

cependant, ce que j'aimerais faire, c'est mettre à jour et afficher la fenêtre imshow lorsque l'image change à chaque itération.

Si par exemple je voudrais faire:

import numpy as np
import matplotlib.pyplot as plt
import time

array = np.zeros( (100, 100), np.uint8 )

for i in xrange( 0, 100 ):
    for j in xrange( 0, 50 ):
        array[j, i] = 1

        #_show_updated_window_briefly_
        plt.imshow( array )
        time.sleep(0.1)

Le problème est que de cette façon, le La fenêtre Matplotlib n'est pas activée, seulement une fois le calcul terminé.

j'ai essayé le matplotlib natif et le pyplot, mais les résultats sont les mêmes. Pour tracer les commandes que j'ai trouvé un .ion() switch, mais ici, il ne semble pas fonctionner.

Q1. Quelle est la meilleure façon d'afficher en continu les mises à jour d'un tableau de numpy (en fait une image à l'échelle de gris uint8)?

T2. Est-il possible de le faire avec une fonction d'animation, comme dans dynamique exemple d'image<!--19? J'aimerais appeler une fonction à l'intérieur d'une boucle, donc je ne sais pas comment réaliser cela avec une fonction d'animation.

22
demandé sur hyperknot 2013-07-24 17:21:45

2 réponses

Vous n'avez pas besoin d'appeler imshow tout le temps. Il est beaucoup plus rapide d'utiliser l'objet set_data méthode:

myobj = imshow(first_image)
for pixel in pixels:
    addpixel(pixel)
    myobj.set_data(segmentedimg)
    draw()

draw() doit s'assurer que le backend met à jour l'image.

mise à jour: votre question a été considérablement modifiée. Dans de tels cas, il est préférable de poser une autre question. Voici une façon de répondre à votre deuxième question:

L'animation de Matplotlib ne traite que d'une dimension croissante (temps), donc votre double boucle ne fait pas. Vous devez convertir vos indices en un seul indice. Voici un exemple:

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

nx = 150
ny = 50

fig = plt.figure()
data = np.zeros((nx, ny))
im = plt.imshow(data, cmap='gist_gray_r', vmin=0, vmax=1)

def init():
    im.set_data(np.zeros((nx, ny)))

def animate(i):
    xi = i // ny
    yi = i % ny
    data[xi, yi] = 1
    im.set_data(data)
    return im

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=nx * ny,
                               interval=50)
27
répondu tiago 2014-07-03 14:57:02

j'ai implémenté un script pratique qui répond à vos besoins. L'essayer ici

Un exemple qui dessine une dynamique d'onde sinusoïdale:

import numpy as np

def redraw_fn(f, axes):
  amp = float(f) / 3000
  f0 = 3
  t = np.arange(0.0, 1.0, 0.001)
  s = amp * np.sin(2 * np.pi * f0 * t)
  if not redraw_fn.initialized:
    redraw_fn.l, = axes.plot(t, s, lw=2, color='red')
    redraw_fn.initialized = True
  else:
    redraw_fn.l.set_ydata(s)

redraw_fn.initialized = False

videofig(100, redraw_fn)
1
répondu Bily 2017-05-10 06:44:51