pythonimagematplotlibsubplot

How can I prevent Matplotlib from autoscaling images to the same size in subplots?


I’m trying to display three images of different sizes side-by-side using Matplotlib. I want each subplot to maintain the original size of the images without auto scaling them to be the same size.


img_512 = down_sample(1024, 512, img)

img_512_upsample = up_sample(512, 1024, img_512)

fig, ax = plt.subplots(1,3, figsize=(15,10))

ax[0].imshow(img, cmap='gray', aspect='equal', extent=[0, img.shape[1], img.shape[0], 0])
ax[0].set_title(f"Original Image")
ax[0].axis('on')

ax[1].imshow(img_512, cmap='gray', aspect='equal', extent=[0, img_512.shape[1], img_512.shape[0], 0])
ax[1].set_title(f"Down Sample to 512x512")
ax[1].axis('on')


ax[2].imshow(img_512_upsample, cmap='gray', aspect='equal', extent=[0, img_512_upsample.shape[1], img_512_upsample.shape[0], 0])
ax[2].set_title(f"Up Sample to 1024x1024")
ax[2].axis('on')

plt.autoscale(False)
plt.tight_layout()
plt.show()

Image of my result

I tried turning off auto scaling, setting aspect to equal and tried setting the extent to the sizes of the images.


Solution

  • If you want the subplots the same size, use sharex/sharey in the call to subplots:

    import matplotlib.pyplot as plt
    import numpy as np
    
    img = np.zeros((1024, 1024))
    img_512 = np.zeros((512, 512))
    img_512_upsample = np.zeros((1024, 1024))
    
    fig, ax_arr = plt.subplots(1,3, figsize=(15,10), sharex=True, sharey=True)
    
    ax_arr[0].imshow(img, cmap='gray', aspect='equal', extent=[0, img.shape[1], img.shape[0], 0])
    ax_arr[0].set_title(f"Original Image")
    
    ax_arr[1].imshow(img_512, cmap='gray', aspect='equal', extent=[0, img_512.shape[1], img_512.shape[0], 0])
    ax_arr[1].set_title(f"Down Sample to 512x512")
    
    ax_arr[2].imshow(img_512_upsample, cmap='gray', aspect='equal', extent=[0, img_512_upsample.shape[1], img_512_upsample.shape[0], 0])
    ax_arr[2].set_title(f"Up Sample to 1024x1024")
    
    plt.show()
    

    Subplots are all the same size and shape.  The "downsampled" image is in the top left of the middle subplot.

    If instead you want the middle subplot half the height and width, use width_ratios in the call to subplots:

    fig, ax_arr = plt.subplots(1,3, figsize=(15,10), width_ratios=[2, 1, 2])
    

    The middle subplot is half the height and width of the out subplots. The three subplots are aligned by their centres.

    You can align the subplots by their top or bottom edge using the anchor property - "N" for north or "S" for south:

    for ax in ax_arr:
        ax.set_anchor("N")
    

    The same as the second image but the subplots are aligned by their tops.