it-swarm.com.ru

Как обновить окно imshow () matplotlib в интерактивном режиме?

Я работаю над алгоритмом компьютерного зрения, и я хотел бы показать, как на каждом шаге меняется массивный массив.

Что работает сейчас, так это то, что, если у меня есть простая imshow( array ) в конце моего кода, окно отображает и показывает окончательное изображение.

Однако я хотел бы обновить и отобразить окно imshow по мере изменения изображения в каждой итерации. 

Так, например, я хотел бы сделать:

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)

Проблема в том, что таким образом окно Matplotlib не активируется, только когда все вычисления завершены.

Я пробовал и нативный matplotlib и pyplot, но результаты одинаковы. Для построения команд я нашел переключатель .ion(), но здесь он, похоже, не работает.

Q1. Каков наилучший способ непрерывного отображения обновлений в массиве numpy (на самом деле изображение в оттенках серого uint8)?

Q2. Можно ли сделать это с помощью функции анимации, как в примере dynamic image ? Я хотел бы вызвать функцию внутри цикла, поэтому я не знаю, как этого добиться с помощью функции анимации.

28
hyperknot

Вам не нужно постоянно звонить imshow. Гораздо быстрее использовать метод объекта set_data:

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

Функция draw() должна убедиться, что сервер обновляет образ.

ОБНОВЛЕНИЕ: Ваш вопрос был значительно изменен. В таких случаях лучше задать еще один вопрос. Вот способ решения вашего второго вопроса:

Анимация Matplotlib имеет дело только с одним увеличивающимся измерением (временем), поэтому ваш двойной цикл не сработает. Вам нужно конвертировать ваши индексы в один индекс. Вот пример:

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

Я реализовал удобный скрипт, который просто соответствует вашим потребностям. Попробуйте это здесь

Пример, который рисует динамическую синусоидальную волну:

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