设置纵横比时 Pyplot imshow 不显示方形像素

Pyplot imshow not showing square pixels when setting aspect ratio

我在使用 Pyplot imshow 从名为 data 的 numpy ndarray 绘制图像时遇到一些问题,同时保持其纵横比和 square-shaped 像素。 ndarray 的形状是 (112, 2182)。这是我使用的代码:

import matplotlib as mpl
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

mpl.use('Agg')

import matplotlib.pyplot as plt

data = np.random.random_sample((112, 2182))
plt.figure(figsize=(25, 3.5))
plt.subplots_adjust(left=0.1, right=0.9)

ax = plt.subplot(111)
plt.axis('off')
plt.title('Title', fontweight='bold', y=1.15)

im = ax.imshow(data)

# Add same-width colorbar to the bottom of the image
divider = make_axes_locatable(ax)
cax = divider.append_axes("bottom", size="25%", pad=0.3)
cbar = plt.colorbar(im, orientation="horizontal", cax=cax)

# Save image
plt.savefig('image.pdf', dpi=1000, format=pdf)

我认为通过使用 ndarray 的形状设置纵横比,图像会显示方形像素。然而,图像似乎保持纵横比但像素不是正方形,正如您在缩放图像中看到的那样(我仍然不能 post 图像,抱歉):

zoomed plot
whole plot

这些输出与我在没有 aspect 参数的情况下使用 im = ax.imshow(data) 时得到的相同。我手动统计了整幅图y-axis中的像素,有112个,所以不是像素分组的问题。关于如何解决这个问题的任何想法?

编辑:我绘制的图像也将有一个颜色条和一个标题。此外,我需要能够将其保存为 pdf 文件。我上传的放大图是在 pdf 查看器中放大的图的屏幕截图。

文档说 aspect 参数可能是浮点数或

'equal': Ensures an aspect ratio of 1. Pixels will be square (unless pixel sizes are explicitly made non-square in data coordinates using extent).

'auto': The axes is kept fixed and the aspect is adjusted so that the data fit in the axes. In general, this will result in non-square pixels.

因此,1.0 的纵横比正是您要寻找的。鉴于您根据数组的形状计算出的值,预计您不会获得上面显示的输出。 正如@ImportanceOfBeingErnest 指出 aspect='equal' 是默认值,所以它就像

一样简单
im = ax.imshow(data)

如果您使用 ax.imshow(data),您将自动获得方形像素。相反,如果您将纵横比设置为 1/"equal" 以外的值,那么您将不会获得正方形像素。然而,这与问题中观察到的效果无关。

"zoomed image" 中的问题是数据像素的大小与实际屏幕像素的数量级相当。因此,图像像素的大小可能会随着屏幕像素的变化而变化。解决这个问题的方法是保存一个图形,使一个图像像素恰好是一个屏幕像素,或者它的任意倍数。

在这种情况下,这就像

一样简单
data = np.random.random_sample((2182, 112))
plt.imsave("filename.png", data)

您需要使用 imshow 选项重新缩放像素:形状和范围:

import numpy as np
import matplotlib.pyplot as plt

shape = (112, 2182)
extent = [0, 112, 0, 2182]

data = np.random.random_sample(shape)

plt.figure(figsize=(5, 3.5))

ax = plt.subplot(111)
plt.axis('off')

dx = (extent[1] - extent[0]) / shape[1]
dy = (extent[3] - extent[2]) / shape[0]
dx_dy = dx/dy

im = ax.imshow(data, extent=extent, aspect=dx_dy)
plt.show()