Python 如何更新matplotlib';是否以交互方式打开imshow()窗口?

Python 如何更新matplotlib';是否以交互方式打开imshow()窗口?,python,numpy,matplotlib,spyder,Python,Numpy,Matplotlib,Spyder,我正在研究一些计算机视觉算法,我想展示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 xrang

我正在研究一些计算机视觉算法,我想展示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()
开关,但在这里它似乎不起作用

问题1。连续显示numpy阵列(实际上是uint8灰度图像)更新的最佳方式是什么


问题2。是否可以使用动画功能(如中的)执行此操作?我想在循环中调用函数,因此我不知道如何使用动画函数实现这一点。

您不需要一直调用
imshow
。使用对象的
set\u 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)

我实现了一个方便的脚本,它正好适合您的需要。试试看

显示自定义目录中图像的示例如下:

导入操作系统
导入glob
从scipy.misc导入imread
img_dir='YOUR-IMAGE-DIRECTORY'
img_files=glob.glob(os.path.join(video_dir,'.*.jpg'))
def重绘_fn(f,轴):
img_文件=img_文件[f]
img=imread(img\u文件)
如果未重新绘制\u fn.initialized:
重绘_fn.im=axes.imshow(img,动画=True)
重新绘制\u fn.initialized=True
其他:
重绘\u fn.im.set\u数组(img)
重新绘制\u fn.initialized=False
videofig(len(img\u文件)、重画fn、播放fps=30)

如果您使用的是Jupyter,可能您会对这个答案感兴趣。 我在书中读到,
clear\u output
的emmbed函数可以实现以下功能:

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

这个方法确实很慢,但可以用于测试目的。

我很难让它工作,因为很多帖子都在谈论这个问题,但似乎没有人关心提供一个工作示例。然而,在这种情况下,原因不同:

  • 我不能使用蒂亚戈或比利的答案,因为它们不在列表中 与问题相同的范例。在问题中,刷新是 使用Functor动画时,由算法本身调度 videofig,我们处于事件驱动的范例中。事件驱动 编程对于现代用户界面编程来说是不可避免的,但是 当您从一个复杂的算法开始时,可能很难 将其转换为事件驱动方案——我希望能够做到这一点 这也是经典的程序范式
  • Bub Espinja的回答还遇到了另一个问题:我没有尝试过 jupyter笔记本的上下文,但重复imshow是错误的,因为它 每次都会重新创建新的数据结构,这会导致 内存泄漏并减慢整个显示过程
Tiago还提到调用
draw()
,但没有指定从何处获取,顺便说一下,您不需要它。您真正需要调用的函数是
flush\u event()
。有时,它在没有的情况下工作,但这是因为它是从其他地方触发的。你不能指望它。真正棘手的一点是,您不能在空表上调用
imshow()
,否则它将无法初始化其颜色映射,并且set\u数据也将失败

以下是一个可行的解决方案:

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

这可能取决于您使用的后端,但在开始循环之前,请尝试调用至少一个
show()
draw()
,看看这个。这对我来说很有效,但不幸的是,它不起作用,同样的情况也会发生。也许我应该使用动画功能,如在动态图像示例中:但我不知道如何将其转换为基于循环的代码。@zsero:如果简单的版本不起作用,我想知道更复杂的动画是否起作用。我刚刚添加了一个适用于我的示例(matplotlib 1.2),看看它是否适用于您。我刚刚尝试修改您的示例,我认为
im=imshow(data,…)
应该是
im=plt.imshow(data,…)
。另外,为了运行动画,您需要
plt.show()
。Cheers@Chrigi你是对的。我通常有
--pylab
,所以我没有发现问题。只是更新了答案。他不是在问关于更新绘图的问题,而是一个2D图像。提供的脚本是通用的。可以使用它更新matplotlib绘制的任何美工人员。更新示例以显示如何更新二维图像。我已经用了3年了,它从未让我失望。希望它能帮助别人@ProfHuster这比任何其他解决方案都值得更多的投票。这是一个独立的工作解决方案。多亏了这一点,将像素设置为99是一个奇怪但必要的技巧,我的色阶也没有初始化!我在回复中提到了它,但重复imshow是错误的,因为它每次都会重新创建新的数据结构,这会导致重要的内存泄漏,并减慢整个显示过程。