注意
跳转至页面底部下载完整示例代码。
放置图像,保持相对大小#
默认情况下,Matplotlib 会对使用 imshow 创建的图像进行重采样,以使其适应父 Axes。这意味着原始尺寸差异很大的图像最终可能看起来大小相似。
本示例展示了如何保持图像的相对大小,或如何使图像保留与原始数据完全相同的像素。
保持相对大小#
默认情况下,尽管其中一张图像的宽度是另一张的 1.5 倍,但两张图像被调整为相似的大小。
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches
# make the data:
N = 450
x = np.arange(N) / N
y = np.arange(N) / N
X, Y = np.meshgrid(x, y)
R = np.sqrt(X**2 + Y**2)
f0 = 5
k = 100
a = np.sin(np.pi * 2 * (f0 * R + k * R**2 / 2))
A = a[:100, :300]
B = A[:40, :200]
# default layout: both axes have the same size
fig, axs = plt.subplots(1, 2, facecolor='aliceblue')
axs[0].imshow(A, vmin=-1, vmax=1)
axs[1].imshow(B, vmin=-1, vmax=1)
def annotate_rect(ax):
# add a rectangle that is the size of the B matrix
rect = mpatches.Rectangle((0, 0), 200, 40, linewidth=1,
edgecolor='r', facecolor='none')
ax.add_patch(rect)
return rect
annotate_rect(axs[0])

请注意,两张图像的长宽比均为 1(即像素为正方形),但由于图像被缩放到相同的宽度,它们的像素大小有所不同。
如果图像尺寸适宜,我们可以通过使用子图的 width_ratio(宽度比)或 height_ratio(高度比)来保持两张图像的相对大小。具体使用哪一个取决于图像的形状和图形的尺寸。如果图像的宽度大于高度且并排显示(如本例所示),我们可以通过 width_ratios 参数来控制相对大小。
在进行更改的同时,让我们使用 figsize 使图形的长宽比更接近坐标轴的长宽比,从而减少图形中多余的空白空间。请注意,保存图形时,您也可以通过向 savefig 传递 bbox_inches="tight" 来修剪多余的空白空间。

考虑到数据子样本位于较大图像的左上角,如果较小 Axes 的顶部与较大 Axes 的顶部对齐,可能会更合理。这可以通过使用 set_anchor 并设置 "NW"(西北,即左上)来手动实现。

显式放置#
上述调整 figsize 和 width_ratios 的方法通用性不强,因为它需要手动调整参数,甚至可能需要根据图像的比例和布局将代码改为使用 height_ratios 而非 width_ratios。
我们可以选择显式计算位置,并使用 add_axes 将 Axes 放置在绝对坐标处。这采用 [左 底 宽 高] 格式的位置参数,并使用 图形坐标。在下文中,我们确定了图形尺寸和 Axes 位置,以便一个图像数据点正好渲染为一个图形像素。
dpi = 100 # 100 pixels is one inch
# All variables from here are in pixels:
buffer = 0.35 * dpi # pixels
# Get the position of A axes
left = buffer
bottom = buffer
ny, nx = np.shape(A)
posA = [left, bottom, nx, ny]
# we know this is tallest, so we can already get the fig height (in pixels)
fig_height = bottom + ny + buffer
# place the B axes to the right of the A axes
left = left + nx + buffer
ny, nx = np.shape(B)
# align the bottom so that the top lines up with the top of the A axes:
bottom = fig_height - buffer - ny
posB = [left, bottom, nx, ny]
# now we can get the fig width (in pixels)
fig_width = left + nx + buffer
# figsize must be in inches:
fig = plt.figure(figsize=(fig_width / dpi, fig_height / dpi), facecolor='aliceblue')
# the position posA must be normalized by the figure width and height:
ax = fig.add_axes((posA[0] / fig_width, posA[1] / fig_height,
posA[2] / fig_width, posA[3] / fig_height))
ax.imshow(A, vmin=-1, vmax=1)
annotate_rect(ax)
ax = fig.add_axes((posB[0] / fig_width, posB[1] / fig_height,
posB[2] / fig_width, posB[3] / fig_height))
ax.imshow(B, vmin=-1, vmax=1)
plt.show()

检查该图像会发现它正好是 3* 35 + 300 + 200 = 605 像素宽,170 像素高(如果浏览器使用了 2 倍版本,则为该值的两倍)。图像应以每个数据点正好 1 个像素(如果为 2 倍,则为 4 个)的比例进行渲染。
脚本总运行时间:(0 分 1.013 秒)