How to update matplotlib's imshow() window interactively?

hyperknot picture hyperknot · Jul 24, 2013 · Viewed 65.8k times · Source

I'm working on some computer vision algorithm and I'd like to show how a numpy array changes in each step.

What works now is that if I have a simple imshow( array ) at the end of my code, the window displays and shows the final image.

However what I'd like to do is to update and display the imshow window as the image changes in each iteration.

So for example I'd like to do:

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)

The problem is that this way, the Matplotlib window doesn't get activated, only once the whole computation is finished.

I've tried both native matplotlib and pyplot, but the results are the same. For plotting commands I found an .ion() switch, but here it doesn't seem to work.

Q1. What is the best way to continuously display updates to a numpy array (actually a uint8 greyscale image)?

Q2. Is it possible to do this with an animation function, like in the dynamic image example? I'd like to call a function inside a loop, thus I don't know how to achieve this with an animation function.

Answer

tiago picture tiago · Jul 24, 2013

You don't need to call imshow all the time. It is much faster to use the object's set_data method:

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

The draw() should make sure that the backend updates the image.

UPDATE: your question was significantly modified. In such cases it is better to ask another question. Here is a way to deal with your second question:

Matplotlib's animation only deals with one increasing dimension (time), so your double loop won't do. You need to convert your indices to a single index. Here is an example:

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)