使用 plt.imshow 实现更快的刷新率

Posted

技术标签:

【中文标题】使用 plt.imshow 实现更快的刷新率【英文标题】:A faster refresh rate with plt.imshow 【发布时间】:2018-11-15 16:40:10 【问题描述】:

我想在进行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 fps 是可能的,但事实并非如此:经过几次迭代,我在标准 i5 笔记本电脑(Windows 7 x64)上接近 2 fps。

如何拥有更快的imshow刷新率?

注意事项:

我已经尝试了来自 Fast Live Plotting in Matplotlib / PyPlot 的主要答案,但是对于这样一个简单的任务,这里似乎是一个复杂的方法(使用 blit 参数),而且 我没有得到 28 fps但只有 15 fps

我只想将矩阵显示为图像:没有边框、没有轴、没有子图等,我想这可以比解决方案Fast Live Plotting in Matplotlib / PyPlot 更快地完成,也许不是 matplotlib 而是另一个库?

【问题讨论】:

Matplotlib, refresh image with imshow faster的可能重复 @G.Anderson 查看编辑后的问题(见注释)。 Faster plotting of real time audio signal的可能重复 我已经尝试过类似的事情@user2699,但它没有超过 20 fps。查看已编辑的问题以及我发布的答案。 【参考方案1】:

这是因为您在每次迭代中创建了一个新图像,最终导致您的图中有 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 fps 的速度运行。它不会比它可以走得更快。您现在可以使用 blitting,即blit=True,在这种情况下我看到 100 fps。这是 matplotlib 所能达到的极限,但它当然会根据计算机的能力而有所不同。

但请注意,人脑无法解析 100 fps。有人说,25 是通常的帧率,因此大多数电影也使用这样的帧率。所以这里甚至不需要使用 blitting,因为 50 fps 比你能感知的要大。

如果您出于某种原因想要更快地制作动画,则需要使用 matplotlib 以外的其他库。

参见例如

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

编辑问题中的一句话说不应该有边界。这是通过使图形大小服从图像的方面(正方形图像 -> 正方形图形)并将所有边距设置为零来实现的

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 事件循环之外。另请注意,如Fast Live Plotting in Matplotlib / PyPlot 中所见,为这种情况实施 blitting 需要做更多的工作

【讨论】:

谢谢。但我认为您的代码“预先计算”了一个动画并在最后显示它。我想在循环时显示图像,而不是等到结束,然后再显示动画。如何做到这一点? 不,如果你想预先计算动画,你可以使用ArtistAnimation而不是FuncAnimation 哦,对了,我明白了。别的东西:我更愿意像问题中那样“正常”地做一个 for 循环(在我的真实代码中迭代 100k 次),每 100 次迭代显示/绘制 A 的当前状态。必须从 FuncAnimation 对象开始一切都是对我的应用程序有点不方便。有没有办法保持一个简单的 for 循环并从那里调用绘图? 如果你愿意,你可以仍然使用 for 循环。我更新了答案。不过,大多数情况下没有任何理由这样做。为什么不先计算完整数据,然后每 100 步创建一个动画? @ImportanceOfBeingErnest 如何保持FuncAnimation中显示的相同颜色条?【参考方案2】:

感谢 OpenCV,我找到了一个更快的解决方案。以下代码在我的计算机上运行 2 秒,即能够以 500 fps 的速度渲染(我知道人眼无法看到这一点,但很高兴知道这种方法超级快) .

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

【讨论】:

完美运行!

以上是关于使用 plt.imshow 实现更快的刷新率的主要内容,如果未能解决你的问题,请参考以下文章

没有图像弹出或显示plt.imshow()和plt.show()

plt.imshow() 和 plt.show() 没有图像弹出或显示

OpenCV 函数学习04-用 matplotlib 显示图像(plt.imshow)

plt.imshow与cv2.imshow显示颜色问题

opencv imshow plt imshow

将 RGB 图像数组乘以标量后使用 plt.imshow 获取黑色图