Python 如何以交互方式更新 matplotlib 的 imshow() 窗口?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17835302/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to update matplotlib's imshow() window interactively?
提问by hyperknot
I'm working on some computer vision algorithm and I'd like to show how a numpy array changes in each step.
我正在研究一些计算机视觉算法,我想展示一个 numpy 数组在每个步骤中是如何变化的。
What works now is that if I have a simple imshow( array )
at the end of my code, the window displays and shows the final image.
现在有效的是,如果imshow( array )
我的代码末尾有一个简单的,窗口会显示并显示最终图像。
However what I'd like to do is to update and display the imshow window as the image changes in each iteration.
但是,我想做的是随着图像在每次迭代中的变化而更新和显示 imshow 窗口。
So for example I'd like to do:
所以例如我想做:
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)
The problem is that this way, the Matplotlib window doesn't get activated, only once the whole computation is finished.
问题是这样,Matplotlib 窗口不会被激活,只有在整个计算完成后。
I've tried both native matplotlib and pyplot, but the results are the same. For plotting commands I found an .ion()
switch, but here it doesn't seem to work.
我已经尝试过原生 matplotlib 和 pyplot,但结果是一样的。对于绘图命令,我找到了一个.ion()
开关,但在这里它似乎不起作用。
Q1. What is the best way to continuously display updates to a numpy array (actually a uint8 greyscale image)?
一季度。连续显示 numpy 数组(实际上是 uint8 灰度图像)更新的最佳方法是什么?
Q2. Is it possible to do this with an animation function, like in the dynamic image example? I'd like to call a function inside a loop, thus I don't know how to achieve this with an animation function.
Q2。是否可以使用动画功能来做到这一点,就像在动态图像示例中一样?我想在循环内调用一个函数,因此我不知道如何使用动画函数来实现这一点。
采纳答案by tiago
You don't need to call imshow
all the time. It is much faster to use the object's set_data
method:
你不需要一直打电话imshow
。使用对象的set_data
方法要快得多:
myobj = imshow(first_image)
for pixel in pixels:
addpixel(pixel)
myobj.set_data(segmentedimg)
draw()
The draw()
should make sure that the backend updates the image.
本draw()
应确保后端更新图像。
UPDATE:your question was significantly modified. In such cases it is better to ask another question. Here is a way to deal with your second question:
更新:您的问题已显着修改。在这种情况下,最好再问一个问题。这是处理您的第二个问题的一种方法:
Matplotlib's animation only deals with one increasing dimension (time), so your double loop won't do. You need to convert your indices to a single index. Here is an example:
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)
回答by Bily
I implemented a handy script that just suits your needs. Try it out here
我实现了一个适合您需求的方便脚本。在这里试试
An example that shows images in a custom directory is like this:
在自定义目录中显示图像的示例如下所示:
import os
import glob
from scipy.misc import imread
img_dir = 'YOUR-IMAGE-DIRECTORY'
img_files = glob.glob(os.path.join(video_dir, '*.jpg'))
def redraw_fn(f, axes):
img_file = img_files[f]
img = imread(img_file)
if not redraw_fn.initialized:
redraw_fn.im = axes.imshow(img, animated=True)
redraw_fn.initialized = True
else:
redraw_fn.im.set_array(img)
redraw_fn.initialized = False
videofig(len(img_files), redraw_fn, play_fps=30)
回答by Bub Espinja
If you are using Jupyter, maybe this answer interests you.
I read in this sitethat the emmbebed function of clear_output
can make the trick:
如果您使用的是 Jupyter,也许这个答案会让您感兴趣。我在这个网站上读到的 emmbebed 功能clear_output
可以解决这个问题:
%matplotlib inline
from matplotlib import pyplot as plt
from IPython.display import clear_output
plt.figure()
for i in range(len(list_of_frames)):
plt.imshow(list_of_frames[i])
plt.title('Frame %d' % i)
plt.show()
clear_output(wait=True)
It is true that this method is quite slow, but it can be used for testing purposes.
这种方法确实很慢,但它可以用于测试目的。