PIL
IPython
Jupyter Notebook
Image Display
Python

How to show PIL Image in ipython notebook

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Displaying a PIL image in an IPython or Jupyter notebook can be done in several ways, and the right method depends on whether you need quick preview, rich formatting, or plotting controls. Most issues come from mixing Matplotlib display rules with PIL objects. A clear display pattern keeps notebooks reliable and easy to share.

Quick Display With IPython Display

The simplest approach is to load image with Pillow and pass it to display.

python
1from PIL import Image
2from IPython.display import display
3
4img = Image.open("sample.jpg")
5display(img)

This works well for ad hoc inspection and preserves notebook output inline.

Display With Matplotlib for Control

If you need axes control, titles, or side by side comparison, use Matplotlib.

python
1from PIL import Image
2import matplotlib.pyplot as plt
3
4img = Image.open("sample.jpg")
5
6plt.figure(figsize=(6, 4))
7plt.imshow(img)
8plt.axis("off")
9plt.title("Input image")
10plt.show()

Matplotlib is useful when combining image output with charts or model diagnostics in one figure.

Handle Color Modes Correctly

PIL images can be in modes like RGB, RGBA, or L. Some downstream code expects a specific mode. Convert explicitly when needed.

python
1img = Image.open("sample.png")
2if img.mode != "RGB":
3    img = img.convert("RGB")
4
5display(img)

Explicit conversion prevents subtle display differences across environments.

Show Processed Images in Notebook Pipelines

Notebook workflows often apply transforms before display. Keep transformations in pure functions for repeatability.

python
1from PIL import ImageOps
2
3def preprocess(image: Image.Image) -> Image.Image:
4    image = image.convert("L")
5    image = ImageOps.autocontrast(image)
6    return image
7
8processed = preprocess(Image.open("sample.jpg"))
9display(processed)

This pattern helps when comparing raw and processed inputs for machine learning experiments.

Save and Reopen for Reproducibility Checks

If notebook output looks different from exported files, verify by saving and reopening.

python
processed.save("processed_output.png")
check = Image.open("processed_output.png")
display(check)

This catches issues around compression settings, color profiles, and accidental mode conversion.

Compare Multiple Images in One Output Cell

Model development often needs before and after comparisons. Use subplots to render original, transformed, and prediction overlays together.

python
1from PIL import Image, ImageFilter
2import matplotlib.pyplot as plt
3
4img = Image.open("sample.jpg").convert("RGB")
5blurred = img.filter(ImageFilter.GaussianBlur(radius=2))
6edge = img.filter(ImageFilter.FIND_EDGES)
7
8fig, axes = plt.subplots(1, 3, figsize=(12, 4))
9axes[0].imshow(img)
10axes[0].set_title("Original")
11axes[1].imshow(blurred)
12axes[1].set_title("Blurred")
13axes[2].imshow(edge)
14axes[2].set_title("Edges")
15
16for ax in axes:
17    ax.axis("off")
18
19plt.tight_layout()
20plt.show()

This workflow is clearer than printing each image in separate cells and makes review easier during experiments.

Convert Between PIL and NumPy Safely

Some libraries return NumPy arrays while others expect PIL images. Convert explicitly to avoid dtype surprises.

python
1import numpy as np
2
3arr = np.array(img)
4print(arr.shape, arr.dtype)
5
6img_back = Image.fromarray(arr.astype("uint8"), mode="RGB")
7display(img_back)

Explicit conversion keeps notebook pipelines predictable across OpenCV, Pillow, and TensorFlow utilities.

Common Pitfalls

  • Forgetting plt.show when using Matplotlib in certain notebook configurations.
  • Passing closed file handles to Image.open workflow.
  • Ignoring image mode conversions before display or model input.
  • Displaying very large images without resizing, causing sluggish notebooks.
  • Mixing OpenCV BGR arrays with PIL RGB images without conversion.

Summary

  • Use IPython.display.display for the quickest inline PIL rendering.
  • Use Matplotlib when you need layout and annotation control.
  • Convert image mode explicitly for consistent notebook behavior.
  • Keep transform functions deterministic for reproducible experiments.
  • Save and reopen outputs when debugging visual discrepancies.
  • Standardize notebook display helpers to keep visualization behavior consistent across team experiments and shared tutorials.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.