A faster refresh rate with plt.imshow

南楼画角 提交于 2019-12-01 07:14:04

问题


I'd like to display some images while doing a numpy computation:

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)

Instead of displaying the images quickly, it is rather slow.

I'm not asking for 100 frames per second, but I thought 30 fps would be possible, but it's not: after a few iterations, I'm close to 2 fps on my standard i5 laptop (Windows 7 x64).

How to have a faster imshow refresh rate?

Notes:

  • I've already tried the main answer from Fast Live Plotting in Matplotlib / PyPlot, but here it seems a complex method (using blit parameter) for such a simple task and also I don't get 28 fps but only 15 fps.

  • I only want to display the matrix as image: no border, no axes, no subplot, etc., I imagine this could be done faster than the solution Fast Live Plotting in Matplotlib / PyPlot, maybe not with matplotlib but another library?


回答1:


This is because you create a new image in each iteration, eventually leading to 100 images in your figure.

The recommended way to create an animation would be to use FuncAnimation and to only change the image's data, instead of plotting a new image all the time.

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()

Even though the interval is set to 5 ms, the above code runs with 50 fps on my computer. It will not go faster than it can. You may now use blitting, i.e. blit=True, in which case I see 100 fps. This is the limit of what matplotlib can achieve, but it will of course vary depending on the computer power.

Note however, that the human brain is not capable of resolving 100 fps. One says, 25 is the usual framerate, such that most movies use such framerate as well. So there shouldn't even be the need to use blitting here, as 50 fps is larger than what you are able to perceive.

If for any reason you want to go faster with your animation, you need to use other libraries than matplotlib.

See e.g.

  • Matplotlib, refresh image with imshow faster
  • Matplotlib equivalent of pygame flip

One sententence in the edited question says that there should be no border. This is accomplished by making the figure size obey the aspect of the image (square image -> square figure) and setting all margins to zero

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

A comment below the answer insists on using a for-loop. That would look like

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()

It's will be a bit slower than using FuncAnimation, because the animation happens outside the GUI eventloop. Also note that implementing blitting for such case is much more work as seen in Fast Live Plotting in Matplotlib / PyPlot




回答2:


I found a much faster solution thanks to OpenCV. The following code runs in 2 seconds on my computer, i.e. able to render at 500 fps (I know the human eye isn't able to see this, but good to know that this method is super fast).

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


来源:https://stackoverflow.com/questions/53324068/a-faster-refresh-rate-with-plt-imshow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!