如何使用matplotlib实现多图像序列子图的动画正常更新
问题原因
你当前代码无法更新子图内容有两个核心问题:
ArtistAnimation要求每帧对应的列表存储的是该帧需要渲染的所有艺术家对象(也就是imshow返回的图像对象),你直接把整张画布fig加入帧列表,动画渲染时无法识别需要更新的元素- 循环中反复在同一个子图上调用
imshow会叠加多个图像图层,不会自动替换旧图层
解决方案1:基于现有ArtistAnimation写法调整
import matplotlib.pyplot as plt from matplotlib import animation from IPython.display import HTML fig, (ax0, ax1, ax2) = plt.subplots(nrows=1, ncols=3, figsize=(12, 6)) # 标题仅需设置一次,无需放在循环中重复执行 ax0.set_title('Raw image') ax1.set_title('Manually cropped image') ax2.set_title('Cropped image after re-centering') fis = [] for i in range(0, len(filename_list), 4): # 保存当前帧的三个图像艺术家对象 im0 = ax0.imshow(plt.imread(filename_list[i]), animated=True) im1 = ax1.imshow(plt.imread(filename_list[i].parent / 'cropped' / filename_list[i].name), animated=True) im2 = ax2.imshow(plt.imread(filename_list[i].parent / 'cropped_corr' / filename_list[i].name), animated=True) # 将当前帧所有需要渲染的对象加入帧列表 fis.append([im0, im1, im2]) ani = animation.ArtistAnimation(fig, fis, interval=500, blit=False, repeat_delay=1000) plt.close() HTML(ani.to_jshtml())
解决方案2:使用更易维护的FuncAnimation实现
该写法后续调整帧逻辑更灵活,性能也更优:
import matplotlib.pyplot as plt from matplotlib import animation from IPython.display import HTML fig, (ax0, ax1, ax2) = plt.subplots(nrows=1, ncols=3, figsize=(12, 6)) ax0.set_title('Raw image') ax1.set_title('Manually cropped image') ax2.set_title('Cropped image after re-centering') # 初始化三个图像对象 im0 = ax0.imshow(plt.imread(filename_list[0])) im1 = ax1.imshow(plt.imread(filename_list[0].parent / 'cropped' / filename_list[0].name)) im2 = ax2.imshow(plt.imread(filename_list[0].parent / 'cropped_corr' / filename_list[0].name)) # 定义单帧更新函数 def update(frame_idx): i = frame_idx * 4 # 对应你每隔4张取1张的采样逻辑 im0.set_data(plt.imread(filename_list[i])) im1.set_data(plt.imread(filename_list[i].parent / 'cropped' / filename_list[i].name)) im2.set_data(plt.imread(filename_list[i].parent / 'cropped_corr' / filename_list[i].name)) return [im0, im1, im2] # 生成动画 total_frames = len(range(0, len(filename_list), 4)) ani = animation.FuncAnimation(fig, update, frames=total_frames, interval=500, blit=True, repeat_delay=1000) plt.close() HTML(ani.to_jshtml())
注:如果不同帧的图像像素取值范围差异较大,可以在update函数中新增
im0.set_clim()、im1.set_clim()、im2.set_clim()语句手动设置对比度范围,避免显示异常。
内容的提问来源于stack exchange,提问作者Pettey
相关产品推荐
相关产品推荐

