I have some numpy image arrays, all of the same shape (say (64, 64, 3)). I want to plot them in a grid using pyplot.subplot()
, but when I do, I get unwanted spacing between images, even when I use pyplot.subplots_adjust(hspace=0, wspace=0)
. Below is an example piece of code.
from matplotlib import pyplot
import numpy
def create_dummy_images():
"""
Creates images, each of shape (64, 64, 3) and of dtype 8-bit unsigned integer.
:return: 4 images in a list.
"""
saturated_channel = numpy.ones((64, 64), dtype=numpy.uint8) * 255
zero_channel = numpy.zeros((64, 64), dtype=numpy.uint8)
red = numpy.array([saturated_channel, zero_channel, zero_channel]).transpose(1, 2, 0)
green = numpy.array([zero_channel, saturated_channel, zero_channel]).transpose(1, 2, 0)
blue = numpy.array([zero_channel, zero_channel, saturated_channel]).transpose(1, 2, 0)
random = numpy.random.randint(0, 256, (64, 64, 3))
return [red, green, blue, random]
if __name__ == "__main__":
images = create_dummy_images()
for i, image in enumerate(images):
pyplot.subplot(2, 2, i + 1)
pyplot.axis("off")
pyplot.imshow(image)
pyplot.subplots_adjust(hspace=0, wspace=0)
pyplot.show()
Below is the output.
As you can see, there is unwanted vertical space between those images. One way of circumventing this problem is to carefully hand-pick the right size for the figure, for example I use matplotlib.rcParams['figure.figsize'] = (_, _)
in Jupyter Notebook. However, the number of images I usually want to plot varies between each time I plot them, and hand-picking the right figure size each time is extremely inconvenient (especially because I can't work out exactly what the size means in Matplotlib). So, is there a way that Matplotlib can automatically work out what size the figure should be, given my requirement that all my (64 x 64) images need to be flush next to each other? (Or, for that matter, a specified distance next to each other?)
We can use the plt. subplots_adjust() method to change the space between Matplotlib subplots. The parameters wspace and hspace specify the space reserved between Matplotlib subplots. They are the fractions of axis width and height, respectively.
Use with GridSpectight_layout method (the pyplot api pyplot. tight_layout also works). You may provide an optional rect parameter, which specifies the bounding box that the subplots will be fit inside. The coordinates must be in normalized figure coordinates and the default is (0, 0, 1, 1).
The easiest way to display multiple images in one figure is use figure(), add_subplot(), and imshow() methods of Matplotlib. The approach which is used to follow is first initiating fig object by calling fig=plt. figure() and then add an axes object to the fig by calling add_subplot() method.
Per the help(plt.imshow) docstring: cmap : ~matplotlib.colors.Colormap , optional, default: None. If None, default to rc image.cmap value. cmap is ignored when X has RGB(A) information. However, if img were an array of shape (M,N) , then the cmap controls the colormap used to display the values.
NOTE: correct answer is reported in the update below the original answer.
Create your subplots first, then plot in them. I did it on one line here for simplicity sake
images = create_dummy_images()
fig, axs = pyplot.subplots(nrows=1, ncols=4, gridspec_kw={'wspace':0, 'hspace':0},
squeeze=True)
for i, image in enumerate(images):
axs[i].axis("off")
axs[i].imshow(image)
UPDATE:
Nevermind, the problem was not with your subplot definition, but with imshow()
which distorts your axes after you've set them up correctly.
The solution is to use aspect='auto'
in the call to imshow()
so that the pictures fills the axes without changing them. If you want to have square axes, you need to create a picture with the appropriate width/height ratio:
pyplot.figure(figsize=(5,5))
images = create_dummy_images()
for i, image in enumerate(images):
pyplot.subplot(2, 2, i + 1)
pyplot.axis("off")
pyplot.imshow(image, aspect='auto')
pyplot.subplots_adjust(hspace=0, wspace=0)
pyplot.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With