Python之使用Matplotlib绘图小记——使用迭代器形式的子图对象

Python之使用Matplotlib绘图小记——使用迭代器形式的子图对象,第1张

Python之使用Matplotlib绘图小记——使用迭代器形式的子图对象 Python之使用Matplotlib绘图小记——使用迭代器形式的子图对象 前言

在使用 opencv 构建计算机视觉程序的时候,常会使用 matplotlib 来可视化中间的结果。因为直接为每一个中间结果进行一次单独的输出并不现实,因为如果窗口积累多了,关起来非常麻烦,最好的还是使用子图的形式,每个输出作为一个子图。

创建子图 子图索引的坑

实际 *** 作中,这里会涉及到对于子图的索引。matplotlib 本身对子图的索引是按照行列来区分的。当然,这里有个坑,那就是如果使用一行或者一列,那就应该使用一维索引就行,而若涉及到多行多列,那就是二维索引了。

fig, axes = plt.subplots(nrows=1, ncols=1)
print(type(axes), axes)
fig, axes = plt.subplots(nrows=2, ncols=1)
print(type(axes), axes.shape)
fig, axes = plt.subplots(nrows=1, ncols=2)
print(type(axes), axes.shape)
fig, axes = plt.subplots(nrows=2, ncols=2)
print(type(axes), axes.shape)

"""
 AxesSubplot(0.125,0.11;0.775x0.77)
 (2,)
 (2,)
 (2, 2)
"""
更方便的形式——迭代器

如果代码流程本身是确定的,那么直接使用固定递增的序号来索引子图自然是最直接和直观的,但是如果代码前后顺序随时可能会调整或者中间可能会插入额外的 *** 作和可视化的时候,就不太方便了。这个时候,其实最适合使用迭代器来处理。每次按照顺序“d出”一个对象,并不需要指定索引。

考虑到 fig, axes = plt.subplots(...) 返回的 axes 是一个 ndarray 对象,我们直接将其展平成一维后使用内建方法 iter() 构建迭代器就可以很好的应对这个问题。直接对构建的迭代器对象使用 next() 函数就可以获得一个新的 axis 对象,且同时可以保证前后的 axis 对象对应的子图序号是按照行主序与整体子图一一对应的。由此可以得到以下代码:

axis = next(axes)
axis.set_title(title)
axis.imshow(image, cmap="gray", vmin=0, vmax=255)

这里要注意 cmap 的设定,因为 matplotlib 默认的 cmap 并不是灰度图的形式所以为了正常展示灰度图,我们需要重新设定其为 gray。

更简洁的形式——包装成独立函数

甚至我们可以进一步简化调用的方式,将其包装成一个函数。由于其中需要用到一个共享的 axes,这里可以使用全局变量或者参数的形式进行传递。

python 中仅支持共享传参(指函数的各个形式参数获得实参中各个引用的副本,也就是说,函数内部的形参是实参的别名)。对于这里传入的迭代器,每次 next 都是在修改同一个对象的内部状态,也可以将迭代器看作是一个可变对象:

def imshow_on_axis(image, title, axes):
    axis = next(axes)
    axis.set_title(title)
    axis.imshow(image, cmap="gray", vmin=0, vmax=255)
其他参考

关于 python 的可变对象与不可变对象可以简单看看下面这篇文章。虽然细节可能有所欠缺,但是胜在介绍的比较丰富:

python 可变对象与不可变对象 - Dwzb 的文章 - 知乎 https://zhuanlan.zhihu.com/p/34395671

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/zaji/5701506.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存