展示:范围和方面


85

我正在编写一个通过3D数据集可视化切片和投影的软件系统。我正在使用matplotlib并且专门imshow用于可视化从分析代码中获得的图像缓冲区。

由于我想用绘图轴注释图像,因此我使用了imshow用来将图像缓冲区像素坐标映射到数据空间坐标系的range关键字。

不幸的是,matplotlib不知道单位。说(以人工示例为例),我想绘制尺寸为的图像1000 m X 1 km。在这种情况下,范围将类似于[0, 1000, 0, 1]。即使图像阵列是方形的,但由于extent关键字所隐含的纵横比为1000,因此所得绘图轴的纵横比也为1000。

是否可以在保持我通过使用range关键字获得的自动生成的主要刻度线和标签的同时,保持绘图的纵横比?

Answers:


141

您可以通过手动设置图像的外观(或使其自动缩放以填满图形的范围)来实现。

默认情况下,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按给定的标量缩放。
orodbhen

@JoeKington可以获取单个像素的大小。该大小取决于数据集的大小,并且可以像您的情况一样,由拼凑而成的瓷砖拼成连续的图。
Alexander Cska

4

根据plt.imshow()官方指南,我们知道纵横比可以控制轴的纵横比。用我的话来说,方面恰好是x单位与y单位的比率。大多数时候,我们希望将其保持为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)!仅在必须时更改外观。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.