Более быстрая частота обновления с помощью plt.imshow

Я хотел бы отобразить некоторые изображения во время numpy вычисление:

import numpy as np
import matplotlib.pyplot as plt
plt.ion()  # Turn the interactive mode on.
for i in range(100):
    A = np.random.randn(10,10)
    plt.imshow(A)
    plt.pause(0.001)
    # do some other numpy computations here (they take < 1 ms)

Вместо того, чтобы отображать изображения быстро, это довольно медленно.

Я не запрашиваю 100 кадров в секунду, но я думал, что 30 кадров в секунду будут возможны, но это не так: после нескольких итераций, я близок к 2 кадрам в секунду на моем стандартном ноутбуке i5 (Windows 7 x64).

Как быстрее imshow Частота обновления?

Заметки:

  • Я уже попробовал основной ответ из Fast Live Plotting в Matplotlib / PyPlot, но здесь это кажется сложным методом (с использованием blit параметр) для такой простой задачи, а также я не получаю 28 кадров в секунду, а только 15 кадров в секунду.

  • Я только хочу отобразить матрицу в виде изображения: без рамки, без осей, без подзаговора и т. Д. Я полагаю, что это можно сделать быстрее, чем решение Fast Live Plotting в Matplotlib / PyPlot, может быть, не с matplotlib, а с другой библиотекой?

2 ответа

Решение

Это потому, что вы создаете новое изображение в каждой итерации, что в итоге приводит к 100 изображениям на вашей фигуре.

Рекомендованный способ создания анимации - использовать FuncAnimation и только изменять данные изображения, вместо того, чтобы постоянно изображать новое изображение.

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

im = plt.imshow(np.random.randn(10,10))

def update(i):
    A = np.random.randn(10,10)
    im.set_array(A)
    return im, text

ani = FuncAnimation(plt.gcf(), update, frames=range(100), interval=5, blit=False)

plt.show()

Хотя interval установлен на 5 мс, приведенный выше код работает на моем компьютере с частотой 50 кадров в секунду. Это не пойдет быстрее, чем может. Теперь вы можете использовать блиттинг, т.е. blit=Trueв этом случае я вижу 100 кадров в секунду. Это предел того, чего может достичь matplotlib, но он, конечно, будет зависеть от мощности компьютера.

Обратите внимание, что человеческий мозг не способен разрешать 100 кадров в секунду. Один говорит, что 25 - это обычная частота кадров, так что большинство фильмов также используют такую ​​частоту кадров. Таким образом, здесь даже не нужно использовать блиттинг, так как 50 кадров в секунду больше, чем вы можете воспринимать.

Если по какой-либо причине вы хотите работать с анимацией быстрее, вам нужно использовать другие библиотеки, кроме matplotlib.

См. Например


Одно предложение в отредактированном вопросе говорит, что не должно быть никакой границы. Это достигается путем настройки размера фигуры в соответствии с аспектом изображения (квадратное изображение -> квадратная фигура) и установки всех полей на ноль

plt.figure(figsize=(5,5))
plt.subplots_adjust(0,0,1,1)

Комментарий под ответом настаивает на использовании цикла for. Это будет выглядеть

im = plt.imshow(np.random.randn(10,10))

plt.ion()
for i in range(100):

    A = np.random.randn(10,10)
    im.set_array(A)
    plt.pause(0.005)

plt.ioff()
plt.show()

Это будет немного медленнее, чем при использовании FuncAnimation, потому что анимация происходит вне GUI EventLop. Также обратите внимание, что реализация блитинга для такого случая - намного больше работы, как видно из Fast Live Plotting в Matplotlib / PyPlot

Я нашел гораздо более быстрое решение благодаря OpenCV. Следующий код выполняется на моем компьютере в течение 2 секунд, то есть способен отображать со скоростью 500 кадров в секунду (я знаю, что человеческий глаз не способен увидеть это, но приятно знать, что этот метод очень быстрый).

import numpy as np
import cv2

cv2.namedWindow('img', cv2.WINDOW_NORMAL)

for i in range(1000):
    A = np.random.randn(10,10)
    cv2.imshow("img", A)
    cv2.waitKey(1)  # it's needed, but no problem, it won't pause/wait
Другие вопросы по тегам