HOWTO · Matplotlib
How to Display Multiple Images in One Figure Correctly in Matplotlib
Display multiple images in one Matplotlib figure with a grid of axes, then customize individual panels.
On this page
To display several images in one figure, create one Matplotlib figure with an axis for each image, then call imshow() on the corresponding axis. fig.add_subplot() lets you build the grid in a loop; plt.subplots() is convenient when you want the axes as an array.
Use Matplotlib add_subplot() in for Loop
Pass the number of rows, the number of columns, and a one-based panel index to fig.add_subplot(rows, columns, index). The loop below fills a 2-by-2 grid with four distinct arrays and gives each panel a title. The examples are unexecuted here; the explanations describe the code and API usage shown.
Run this example:
import numpy as np
import matplotlib.pyplot as plt
rows, cols = 2, 2
images = [np.full((8, 8), value) for value in (1, 2, 3, 4)]
fig = plt.figure(figsize=(6, 5))
for index, image in enumerate(images, start=1):
ax = fig.add_subplot(rows, cols, index)
ax.imshow(image, cmap="viridis")
ax.set_title(f"Image {index}")
fig.tight_layout()
plt.show()
Each iteration creates one axis and displays that iteration’s image on it. Keep the returned axes when you want to customize individual panels later. For a regular grid, plt.subplots() returns the axes in row-and-column form; flatten them for iteration, and use two indices to select a particular panel.
import numpy as np
import matplotlib.pyplot as plt
rows, cols = 2, 2
images = [np.full((8, 8), value) for value in (1, 2, 3, 4)]
x = np.linspace(0, 7, 8)
fig, axes = plt.subplots(rows, cols, figsize=(6, 5))
for index, (ax, image) in enumerate(zip(axes.flat, images), start=1):
ax.imshow(image, cmap="viridis", alpha=0.75)
ax.set_title(f"Image {index}")
axes[0, 1].plot(x, x, color="white")
axes[1, 1].plot(x, 7 - x, color="red")
fig.tight_layout()
plt.show()
Here axes.flat provides a simple way to visit each panel, while axes[row, column] addresses a specific panel. The extra lines are drawn on top of those panels’ images. Make sure the grid has enough axes for every image; zip() stops when either input runs out, so unmatched images or axes are not displayed by that loop.
Define a Function Based on the Subplots in Matplotlib
For repeated use, wrap the grid setup in a function. This version converts the axes to a flat array so it also handles a 1-by-1 grid, checks that the grid has room for every image, titles each panel, and hides the axes for an image-focused figure.
import numpy as np
import matplotlib.pyplot as plt
def display_multiple_img(images, rows=1, cols=1):
images = list(images.items())
figure, axes = plt.subplots(nrows=rows, ncols=cols)
axes = np.atleast_1d(axes).ravel()
if len(images) > len(axes):
raise ValueError("The grid must have at least one axis per image.")
for ax, (title, image) in zip(axes, images):
ax.imshow(image, cmap="viridis")
ax.set_title(title)
ax.set_axis_off()
for ax in axes[len(images):]:
ax.set_axis_off()
figure.tight_layout()
plt.show()
images = {
"Image 1": np.full((8, 8), 1),
"Image 2": np.full((8, 8), 2),
"Image 3": np.full((8, 8), 3),
"Image 4": np.full((8, 8), 4),
}
display_multiple_img(images, rows=2, cols=2)
Pass an insertion-ordered mapping from titles to image arrays, along with the desired grid dimensions. The function turns the axes into a flat sequence before iteration, so a single panel works as well as a multi-panel grid. If there are more images than available axes, it raises ValueError; increase rows or cols to display them all.