it-swarm.com.de

Wie kann man das imshow () - Fenster von matplotlib interaktiv aktualisieren?

Ich arbeite an einem Computer-Vision-Algorithmus und möchte zeigen, wie sich ein numpy-Array in jedem Schritt ändert.

Was jetzt funktioniert, ist, dass wenn ich am Ende meines Codes eine einfache imshow( array ) habe, das Fenster das endgültige Bild anzeigt und anzeigt.

Ich möchte jedoch das imshow-Fenster aktualisieren und anzeigen, wenn sich das Bild in jeder Iteration ändert. 

Zum Beispiel würde ich gerne tun:

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)

Das Problem ist, dass auf diese Weise das Matplotlib-Fenster nur dann aktiviert wird, wenn die gesamte Berechnung abgeschlossen ist.

Ich habe sowohl native Matplotlib als auch Pyplot ausprobiert, aber die Ergebnisse sind die gleichen. Für das Zeichnen von Befehlen habe ich einen .ion()-Schalter gefunden, aber hier scheint er nicht zu funktionieren.

Q1. Was ist der beste Weg, um fortlaufend Aktualisierungen eines numpy-Arrays anzuzeigen (eigentlich ein uint8-Graustufenbild)?

Q2. Kann man dies mit einer Animationsfunktion machen, wie im dynamischen Bildbeispiel ? Ich möchte eine Funktion innerhalb einer Schleife aufrufen, daher weiß ich nicht, wie Sie dies mit einer Animationsfunktion erreichen können.

28
hyperknot

Sie müssen nicht ständig imshow aufrufen. Es ist viel schneller, die set_data-Methode des Objekts zu verwenden:

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

Die draw() sollte sicherstellen, dass das Backend das Image aktualisiert.

UPDATE: Ihre Frage wurde wesentlich geändert. In solchen Fällen ist es besser, eine andere Frage zu stellen. Hier ist eine Möglichkeit, Ihre zweite Frage zu beantworten:

Die Animation von Matplotlib behandelt nur eine wachsende Dimension (Zeit), sodass Ihre Doppelschleife nicht funktioniert. Sie müssen Ihre Indizes in einen einzelnen Index konvertieren. Hier ist ein Beispiel:

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)
30
tiago

Ich habe ein praktisches Skript implementiert, das genau zu Ihnen passt. Probieren Sie es aus hier

Ein Beispiel, das eine dynamische Sinuswelle zeichnet:

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
Bily