Imshow:范围和方面

Posted

技术标签:

【中文标题】Imshow:范围和方面【英文标题】:Imshow: extent and aspect 【发布时间】:2012-11-03 07:02:18 【问题描述】:

我正在编写一个通过 3D 数据集可视化切片和投影的软件系统。我正在使用matplotlib 尤其是imshow 来可视化我从分析代码中返回的图像缓冲区。

因为我想用绘图轴注释图像,所以我使用imshow 提供的extent 关键字将图像缓冲区像素坐标映射到数据空间坐标系。

不幸的是,matplotlib 不知道单位。假设(举一个人为的例子)我想绘制一个尺寸为1000 m X 1 km 的图像。在这种情况下,范围将类似于[0, 1000, 0, 1]。即使图像数组是正方形的,由于 extent 关键字隐含的纵横比是 1000,因此生成的绘图轴也具有 1000 的纵横比。

是否可以强制绘图的纵横比,同时仍保留使用 extent 关键字获得的自动生成的主要刻度线和标签?

【问题讨论】:

【参考方案1】:

plt.imshow()官方指南,我们知道aspect控制轴的纵横比。用我的话来说,方面就是 x unit 和 y unit 的比率。大多数情况下,我们希望将其保持为 1,因为我们不想无意中扭曲数字。但是,确实有一些情况需要我们指定纵横比而不是 1。提问者提供了一个很好的例子,即 x 和 y 轴可能有不同的物理单位。假设x以km为单位,y以m为单位。因此,对于 10x10 数据,范围应为 [0,10km,0,10m] = [0, 10000m, 0, 10m]。在这种情况下,如果我们继续使用默认的 aspect=1,那么图形的质量真的很差。因此,我们可以指定 aspect = 1000 来优化我们的图形。下面的代码说明了这种方法。

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
rng=np.random.RandomState(0)
data=rng.randn(10,10)
plt.imshow(data, origin = 'lower',  extent = [0, 10000, 0, 10], aspect = 1000)

不过,我认为有一个替代方案可以满足提问者的需求。我们可以将范围设置为 [0,10,0,10] 并添加额外的 xy 轴标签来表示单位。代码如下。

plt.imshow(data, origin = 'lower',  extent = [0, 10, 0, 10])
plt.xlabel('km')
plt.ylabel('m')

要制作一个正确的数字,我们应该始终牢记x_max-x_min = x_res * data.shape[1]y_max - y_min = y_res * data.shape[0],其中extent = [x_min, x_max, y_min, y_max]。默认为aspect = 1,表示单位像素为正方形。此默认行为也适用于具有不同值的 x_res 和 y_res。扩展前面的示例,假设 x_res 为 1.5,而 y_res 为 1。因此范围应等于 [0,15,0,10]。使用默认方面,我们可以有矩形颜色像素,而单位像素仍然是正方形!

plt.imshow(data, origin = 'lower',  extent = [0, 15, 0, 10])
# Or we have similar x_max and y_max but different data.shape, leading to different color pixel res.
data=rng.randn(10,5)
plt.imshow(data, origin = 'lower',  extent = [0, 5, 0, 5])

彩色像素的方面是x_res / y_res。将其方面设置为单位像素的方面(即aspect = x_res / y_res = ((x_max - x_min) / data.shape[1]) / ((y_max - y_min) / data.shape[0]))将始终给出方形颜色像素。我们可以将 aspect = 1.5 更改为 x 轴单位是 y 轴单位的 1.5 倍,从而得到一个正方形的颜色像素和正方形的整个图形,而不是矩形的像素单元。显然,它通常不被接受。

data=rng.randn(10,10)
plt.imshow(data, origin = 'lower',  extent = [0, 15, 0, 10], aspect = 1.5)

最不希望的情况是设置纵横比为任意值,如 1.2,这将导致既不会导致正方形单位像素也不会导致正方形颜色像素。

plt.imshow(data, origin = 'lower',  extent = [0, 15, 0, 10], aspect = 1.2)

长话短说,设置正确的范围并让 matplotlib 为我们做剩下的事情总是足够的(即使 x_res!=y_res)!仅在必要时才更改外观。

【讨论】:

【参考方案2】:

您可以通过手动设置图像的纵横比(或让它自动缩放以填充图形的范围)来做到这一点。

默认情况下,imshow 将绘图的纵横比设置为 1,因为这通常是人们想要的图像数据。

在您的情况下,您可以执行以下操作:

import matplotlib.pyplot as plt
import numpy as np

grid = np.random.random((10,10))

fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, figsize=(6,10))

ax1.imshow(grid, extent=[0,100,0,1])
ax1.set_title('Default')

ax2.imshow(grid, extent=[0,100,0,1], aspect='auto')
ax2.set_title('Auto-scaled Aspect')

ax3.imshow(grid, extent=[0,100,0,1], aspect=100)
ax3.set_title('Manually Set Aspect')

plt.tight_layout()
plt.show()

【讨论】:

谢谢。有趣的是,文档对scalar 选项只字未提。它似乎按给定的标量缩放y-axis @JoeKington 是否可以获得单个像素的大小。此大小取决于数据集的大小,并且可以像您的情况一样将拼凑的图块拼凑成连续的图。 正是我正在寻找的 aspect = "auto"。谢谢 @Joe Kington,第二个和第三个情节是怎么出来的。使用上面的脚本,我得到了带有网格的图!谢谢

以上是关于Imshow:范围和方面的主要内容,如果未能解决你的问题,请参考以下文章

不能将自定义非线性颜色图与 imshow 结合使用

使用 RGB 数据将输入数据剪切到 imshow 的有效范围(浮点数为 [0..1] 或整数为 [0..255])

matlab imshow()函数显示白色图像问题

您好。我用gray2ind函数转换为伪彩色图像然后用imshow显示,为啥图像全白或全黑呢?

imshow & 图像深度

MATLAB中imshow()和image()