python matplotlib 的 gridspec 无法减少子图之间的差距

python matplotlib's gridspec unable to reduce gap between subplots

我正在使用 GridSpec 在子图中绘制子图以显示图像。

在下面的示例代码中,我创建了一个 1x2 子图,其中每个子图轴包含 3x3 子图(第一个子图中的子图)。

3x3 子图基本上是将图像切割成 9 个方块,排列成 3x3 的形式。我不希望图像片段之间有任何间距,所以我将 wspacehspace 都设置为 0。奇怪的是,生成的输出子图显示行之间的垂直间隙。

我尝试将 hspace 设置为负值以减少行之间的垂直间距,但它会导致行重叠。有没有更方便的方法来实现?

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from PIL import Image
from sklearn.datasets import load_sample_image

flower = load_sample_image('flower.jpg')
img = Image.fromarray(flower)
img = img.crop((100, 100, 325, 325))

# Create tiles - cuts image to 3x3 square tiles
n_tiles = 9
tile_size = float(img.size[0]) / 3 # assumes square tile
tiles = [None] * n_tiles
for n in range(n_tiles):
    row = n // 3 
    col = n % 3

    # compute tile coordinates in term of the image (0,0) is top left corner of the image
    left = col * tile_size
    upper = row * tile_size
    right = left + tile_size
    lower = upper + tile_size
    tile_coord = (int(left), int(upper), int(right), int(lower))
    tile = img.crop(tile_coord)
    tiles[n] = tile
    
# plot subplot of subplot using gridspec
fig = plt.figure(figsize=(7, 3))
outer = gridspec.GridSpec(1, 3, wspace=1)

# image shown as 3x3 grid of image tiles
inner = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=outer[0], wspace=0, hspace=0)
for j in range(len(tiles_tensor)):
    ax1 = plt.Subplot(fig, inner[j], xticks=[], yticks=[])
    ax1.imshow(tiles[j])
    fig.add_subplot(ax1)

# image shown as 3x3 grid of image tiles
inner = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=outer[1], wspace=0, hspace=0)
for j in range(len(data)):
    ax2 = plt.Subplot(fig, inner[j], xticks=[], yticks=[])
    ax2.imshow(tiles[j])
    fig.add_subplot(ax2)

主要问题是 imshow 默认为 aspect='equal'。这迫使小瓷砖成为方形。但是次要地块不是正方形的,所以 9 个正方形瓷砖拼在一起并不能很好地填满次要地块。

一个简单的解决方案是通过 imshow(..., aspect='auto') 关闭方形纵横比。为了让子图更方正,可以调整 topbottomleftright 设置。

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from PIL import Image
from sklearn.datasets import load_sample_image

flower = load_sample_image('flower.jpg')
img = Image.fromarray(flower)
img = img.crop((100, 100, 325, 325))

# Create tiles - cuts image to 3x3 square tiles
n_tiles = 9
tile_size = float(img.size[0]) / 3  # assumes square tile
tiles = [None] * n_tiles
for n in range(n_tiles):
    row = n // 3
    col = n % 3

    # compute tile coordinates in term of the image (0,0) is top left corner of the image
    left = col * tile_size
    upper = row * tile_size
    right = left + tile_size
    lower = upper + tile_size
    tile_coord = (int(left), int(upper), int(right), int(lower))
    tile = img.crop(tile_coord)
    tiles[n] = tile

# plot subplot of subplot using gridspec
fig = plt.figure(figsize=(7, 3))
outer = gridspec.GridSpec(1, 2, wspace=1, left=0.1, right=0.9, top=0.9, bottom=0.1)

titles = [f'Subplot {j+1}' for j in range(outer.nrows * outer.ncols) ]
for j in range(len(titles)):
    ax = plt.Subplot(fig, outer[j], xticks=[], yticks=[])
    ax.axis('off')
    ax.set_title(titles[j])
    fig.add_subplot(ax)


# image shown as 3x3 grid of image tiles
inner = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=outer[0], wspace=0, hspace=0)
for j in range(len(tiles)):
    ax1 = plt.Subplot(fig, inner[j], xticks=[], yticks=[])
    ax1.imshow(tiles[j], aspect='auto')
    fig.add_subplot(ax1)

# image shown as 3x3 grid of image tiles
inner = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=outer[1], wspace=0, hspace=0)
for j in range(len(tiles)):
    ax2 = plt.Subplot(fig, inner[j], xticks=[], yticks=[])
    ax2.imshow(tiles[j], aspect='auto')
    fig.add_subplot(ax2)

fig.suptitle('Overall title')

plt.show()