如何将gridspec与plt.subplots()结合起来以消除子图行之间的空间

时间:2017-02-26 23:23:54

标签: python-3.x matplotlib

我试图在子图中绘制多个图像,并消除子图(水平和垂直)之间的空间或控制它。我尝试使用How to Use GridSpec...中的建议。我也在这里试过,但他们没有使用子图():space between subplots 我能够在下面的代码中消除水平空间而不是垂直空间。请不要像我尝试过其他帖子那样重复标记,但他们没有按照我的意愿行事。我的代码如下所示。也许在gridspec_kw字典中还需要另一个关键字参数? 我想使用plt.subplots()而不是plt.subplot()。如果重要,图像不是正方形,而是矩形。我也尝试在plt.show()之前添加f.tight_layout(h_pad=0,w_pad=0),但它没有改变任何东西。

def plot_image_array_with_angles(img_array,correct_angles,predict_angles,
                              fontsize=10,figsize=(8,8)):
'''
Imports:
    import matplotlib.gridspec as gridspec
    import numpy as np
    import matplotlib.pyplot as plt
'''
num_images = len(img_array)
grid = int(np.sqrt(num_images))  # will only show all images if square
#f, axarr = plt.subplots(grid,grid,figsize=figsize)
f, axarr = plt.subplots(grid,grid,figsize=figsize,
                      gridspec_kw={'wspace':0,'hspace':0})
im = 0
for row in range(grid):
    for col in range(grid):
        axarr[row,col].imshow(img_array[im])
        title = 'cor = ' + str(correct_angles[im]) + '  pred = ' + str(predict_angles[im])
        axarr[row,col].set_title(title,fontsize=fontsize)
        axarr[row,col].axis('off')  # turns off all ticks
        #axarr[row,col].set_aspect('equal')
        im += 1
plt.show()
return

1 个答案:

答案 0 :(得分:4)

自动设置imshow绘图的宽高比,使得图像中的像素被平方。此设置比间距的subplots_adjustgridspec设置更强。或者换句话说,如果这些子图的宽高设置为"equal",则无法直接控制子图之间的间距。

第一个明显的解决方案是将图像方面设置为自动ax.set_aspect("auto")。这解决了子图间距的问题,但使图像失真。

另一种选择是调整图形边距和图形大小,以便子图之间的间距符合要求。

假设fighfigw是数字高度和宽度(英寸),s是子图宽度(英寸)。边距为bottomtopleftright(相对于图形尺寸),垂直间距hspace和水平wspace方向(相对于子图大小)。行数表示为n,列数为maspect是子图(图像)高度和宽度(aspect = image height / image width)之间的比率。

然后可以通过

设置尺寸
fig, axes = plt.subplots(nrows=n, ncols=m, figsize=(figwidth, figheight))
plt.subplots_adjust(top=top, bottom=bottom, left=left, right=right, 
                        wspace=wspace, hspace=hspace)

可以根据以下公式计算各个值:

enter image description here

或者,如果边距相同:

enter image description here

一个例子:

import matplotlib.pyplot as plt

image = plt.imread("https://i.stack.imgur.com/9qe6z.png")
aspect = image.shape[0]/float(image.shape[1])
print aspect
n = 2 # number of rows
m = 4 # numberof columns
bottom = 0.1; left=0.05
top=1.-bottom; right = 1.-left
fisasp = (1-bottom-(1-top))/float( 1-left-(1-right) )
#widthspace, relative to subplot size
wspace=0.15  # set to zero for no spacing
hspace=wspace/float(aspect)
#fix the figure height
figheight= 3 # inch
figwidth = (m + (m-1)*wspace)/float((n+(n-1)*hspace)*aspect)*figheight*fisasp

fig, axes = plt.subplots(nrows=n, ncols=m, figsize=(figwidth, figheight))
plt.subplots_adjust(top=top, bottom=bottom, left=left, right=right, 
                    wspace=wspace, hspace=hspace)

for ax in axes.flatten():
    ax.imshow(image)
    ax.set_title("title",fontsize=10)
    ax.axis('off')

plt.show()

enter image description here