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?
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.
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
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