理解subplots, ax.imshow, FuncAnimation
python
文章目录
subplot和subplots的区别
看到subplots会联想到subplot,两者的区别是什么?查一下subplot的英文含义vocabulary subplot,subplot常用作故事里的子情节。
- 看stackoverflow回答,举了两者的例子说明。
- 看subplots的例子what-is-a-subplots-in-matplotlib可知,subplots相当于直接创建一组子图。一次调用可以得到n个子图,然后在子图上绘制即可。
- 而看subplot的csdn例子可知,你需要调用多次subplot来绘制子图,有n个待生成的子图就要调用n次subplot函数。
subplots与ax.imshow例子
所以,subplots可以直接创建画板的格局,如下例子,subplots创建了一个2行1列排版的画布,然后用ax.imshow在排版上绘制图像。
而ax.imshow的行为是能在区域ax绘制图像,其可以接受list或者numpy.ndarray类型输入的像素点,并绘制图片。
下述代码首先定义了红、绿、蓝三种像素点,再做了三种排列row1、row2、row3。然后分别赋值到list和numpy.ndarray。并用imshow展示像素图。
import matplotlib.pyplot as plt
import numpy as np
# 使用ax.imshow绘制两幅图
fig, axs = plt.subplots(2, 1)
red = [255,0,0]
green = [0,255,0]
yellow = [0,0,255]
row1 = [red,green,yellow]
row2 = [green,yellow,red]
row3 = [yellow,red,green]
#plot 1: 用list绘制一副彩色图片, 维度是[M,N,3]
axs[0].imshow([row1, row2, row3])
#plot 2: 用numpy.ndarray绘制一副彩色图片,维度是[M,N,3]
image2 = np.ndarray((3,3,3))
image2[:] = [row2, row3, row1]
print("image2 is instance of numpy array: ", isinstance(image2, np.ndarray)) # True
axs[1].imshow(image2)
plt.show()
输出如下,是两张图画,各有3*3=9个像素点,每个像素点都是彩色,所以维度[H, W, 3]=[3, 3, 3]。
这里的像素点很大,但确实符合3*3的格式。如果像素点数量变多,像素点应该会变小,图像会更像一幅图。
这里没有删除坐标轴,如果不想看到坐标轴和数字,可以代码设置
axs[0].axis("off")
。axs[0].axis("off") axs[0].imshow([row1, row2, row3])
可以看到,第一幅子图的坐标轴消除了,第二幅子图的坐标轴没消除。
如果在使用subplots的情况下,想取消所有图的坐标轴,根据turn-off-axes-in-subplots ,不应该调用plot.axis("off")
,而仍然应该对每个ax调用axis("off")
subplots参数探究
figsize
subplots的figsize参数主要用于设置整个画幅的大小,其中(4,4)代表400px*400px。其它单位使用参考官方文档figure_size_units。
下面看下两种排版下的画幅大小。
import matplotlib.pyplot as plt
def show_blank(nrow, ncol):
fig, axs = plt.subplots(nrow, ncol, sharex=True, sharey=True, figsize=(4, 4))
for ax in axs:
ax.text(0.5, 0.5, "xxxx")
plt.show()
show_blank(2,1)
show_blank(10,1)
运行分别得到:
以及
显而易见,排版虽然是21和101(纵坐标轴因画幅太小而挤压),但整个窗口大小在两次运行中是一样的。所figsize参数指定了画幅的整体大小。
sharex sharey
这两个参数指定了是否共享纵轴和横轴,尽管sharex和sharey接受字符串类型的参数,本文之探究bool类型的运行情况。
下面代码让窗口两次显示2*2排版的画幅,并对比share参数在两种bool输入下的表现。
import matplotlib.pyplot as plt
def show_blank(nrow, ncol, sharex, sharey):
fig, axs = plt.subplots(nrow, ncol, sharex=sharex, sharey=sharey, figsize=(8, 8))
for ax_row in axs:
for ax in ax_row:
ax.text(0.5, 0.5, "test text")
plt.show()
show_blank(2, 2, True, True)
show_blank(2, 2, False, False)
其图片输出分别如下:
可见:
- sharex会让同一列内的图片都共享横坐标轴
- sharey会让同一行内的图片都共享纵坐标轴
具体可以自己调试一下。
imshow参数与返回值
需要探究的参数有cmap、vmin、vmax。根据官方文档。如果要显示灰色画幅,设置参数为cmap='gray', vmin=0, vmax=255
。
- cmap代表图画是灰色还是彩色。如果是RGB图画,可以忽略该参数。
- 在没有设置norm的情况下,vmin和vmax代表色域的最小值和最大值。
个人觉得只需记住灰色、彩色图的参数即可,灰色图就设置一下cmap为gray,彩色图就直接输入[H,W,3]的数据即可。对于一些奇特的用法,不必过多纠缠。
FuncAnimation
- python学习之matplotlib绘制动图FuncAnimation参数 文章对动画的各种参数作了讲解
- FuncAnimation官方文档
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
nrow, ncol = 2, 2
fig, axs = plt.subplots(nrow, ncol, sharex=True, sharey=True, figsize=(8, 8))
texts = ["aaaa", "bbbb", "cccc", "dddd"]
def animate_diff(i):
# 刷新本帧
for row in range(nrow):
for col in range(ncol):
axs[row, col].clear()
# 像素属于第row * ncol + col个,偏移量为i,对len(texts)取余
idx = (i + row * ncol + col) % len(texts)
axs[row, col].text(0.5, 0.5, f"({row},{col}) {texts[idx]}")
# 设置动画
ani = FuncAnimation(fig, animate_diff, interval=1500, blit=False, repeat=True,
frames=100)
plt.show()
动态图如下,从左上到右下的四个子图,坐标分别是(0,0), (0,1), (1,0), (1,1)。各个参数的作用如下:
- fig参数代表动画绘制在fig对象上。
- 帧更新函数为animate_diff,每一帧会调用一次,在函数里可以利用axs对象更新画幅。animate_diff的参数i代表当前是第几帧
- repeat参数代表是否重复播放。
- interval=1500代表帧间隔为1500ms,frames=100代表一轮播放有100帧。
运行以后,可以看到画幅重复以下情形
5. 第一个frame,四个子图分别显示a b c d
6. 第二个frame,四个子图分别显示b c d a
7. 第三个frame,四个子图分别显示c d a b
8. 第四个frame,四个子图分别显示d a b c
留意到,并不需要为animate_diff设置返回值,也可以正常生成动画图。但有的例子中会不止更新画幅,而且设置返回值,这里留个疑问。
更多推荐
所有评论(0)