我正在研究一些计算机视觉算法,我想展示一个numpy数组如何在每一步中发生变化。
现在有效的是,如果我的代码末尾有一个简单的imshow( array )
,则窗口会显示并显示最终图像。
然而,我想要做的是更新并显示imshow窗口,因为图像在每次迭代中都会发生变化。
例如,我想这样做:
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)
问题是这样,Matplotlib窗口只有在整个计算完成后才会被激活。
我尝试了原生matplotlib和pyplot,但结果是一样的。为了绘制命令,我找到了一个.ion()
开关,但在这里它似乎不起作用。
Q1。连续显示numpy数组更新的最佳方法是什么(实际上是uint8灰度图像)?
Q2。是否可以使用动画功能执行此操作,例如dynamic image example?我想在循环中调用一个函数,因此我不知道如何使用动画函数来实现它。
答案 0 :(得分:33)
您无需一直致电imshow
。使用对象的set_data
方法要快得多:
myobj = imshow(first_image)
for pixel in pixels:
addpixel(pixel)
myobj.set_data(segmentedimg)
draw()
draw()
应确保后端更新图像。
更新:您的问题已被大幅修改。在这种情况下,最好再问一个问题。这是处理第二个问题的方法:
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)
答案 1 :(得分:5)
如果您使用的是Jupyter,也许这个答案会让您感兴趣。
我在this site中读到,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)
这种方法的确很慢,但是可以用于测试。
答案 2 :(得分:1)
我实现了一个适合您需求的方便脚本。试一试here
绘制动态正弦波的示例:
import numpy as np
def redraw_fn(f, axes):
amp = float(f) / 3000
f0 = 3
t = np.arange(0.0, 1.0, 0.001)
s = amp * np.sin(2 * np.pi * f0 * t)
if not redraw_fn.initialized:
redraw_fn.l, = axes.plot(t, s, lw=2, color='red')
redraw_fn.initialized = True
else:
redraw_fn.l.set_ydata(s)
redraw_fn.initialized = False
videofig(100, redraw_fn)
答案 3 :(得分:0)
我努力使它起作用,因为许多帖子都谈到了这个问题,但是似乎没人在乎提供一个可行的例子。但是,在这种情况下,原因有所不同:
Tiago还提到了调用draw()
,但是没有指定从何处获取它-顺便说一句,您不需要它。您真正需要调用的函数是flush_event()
。有时它可以不运行,但这是因为它是从其他地方触发的。你不能指望它。真正重要的一点是,您不能在空表上调用imshow()
,否则它将无法初始化其颜色映射,并且set_data也将失败。
这是一个可行的解决方案:
IMAGE_SIZE = 500
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
# this example doesn't work because array only contains zeroes
array = np.zeros(shape=(IMAGE_SIZE, IMAGE_SIZE), dtype=np.uint8)
axim1 = ax1.imshow(array)
array[0, 0] = 99 # this value allow imshow to initialise it's color scale
axim2 = ax2.imshow(array)
del array
for _ in range(50):
print(".", end="")
matrix = np.random.randint(0, 100, size=(IMAGE_SIZE, IMAGE_SIZE), dtype=np.uint8)
axim1.set_data(matrix)
fig1.canvas.flush_events()
axim2.set_data(matrix)
fig1.canvas.flush_events()
print()