Quick fix

Print what you pass to imshow(): print(type(img), getattr(img, "shape", None)). If it is None, the image failed to load (check the path; cv2.imread does not raise errors) or you assigned the result of an in-place method such as thumbnail(). If it is a string, open the file first.

Cause 1: cv2.imread returned None

cv2.imread() never raises an exception for a missing or unreadable file; it returns None, and the error surfaces later in imshow(). We ran this with matplotlib 3.11:

show.py
import matplotlib
matplotlib.use("Agg")
import cv2
import matplotlib.pyplot as plt

img = cv2.imread("photos/IMG_0001.jpg")     # wrong path: cv2.imread returns None, no error
plt.imshow(img)
Tested on ✓ Linux ✓ Windows ✓ macOS
Traceback
TypeError: Image data of dtype object cannot be converted to float

Older matplotlib versions word it as TypeError: Image data can not convert to float; it is the same problem.

Cause 2: passing a path instead of an image

show.py
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

plt.imshow("photo.jpg")                       # a path, not an image
Tested on ✓ Linux ✓ Windows ✓ macOS
Traceback
TypeError: Image data of dtype <U9 cannot be converted to float

Here the dtype in the message is <U9, a 9-character string: the file name.

Cause 3: assigning the result of an in-place method

thumbnail(), paste() and ImageDraw methods modify the image and return None:

show.py
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from PIL import Image

img = Image.open("photo.jpg")
img = img.thumbnail((400, 400))               # thumbnail() returns None
plt.imshow(img)
Tested on ✓ Linux ✓ Windows ✓ macOS
Traceback
TypeError: Image data of dtype object cannot be converted to float

Fixes

Fail early, with a clear message, when an image did not load:

show.py
import matplotlib
matplotlib.use("Agg")
from pathlib import Path
import cv2
import matplotlib.pyplot as plt

path = Path("photos/img_1.jpg")
img = cv2.imread(str(path))
if img is None:
    raise FileNotFoundError(f"could not read {path.resolve()}")
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))   # also convert BGR -> RGB for correct colours
plt.savefig("ok.png")
print("shown", img.shape)
Tested on ✓ Linux ✓ Windows ✓ macOS
Output
shown (1067, 1600, 3)

And keep in-place calls on their own line:

show.py
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from PIL import Image

img = Image.open("photo.jpg")
img.thumbnail((400, 400))                     # in place, no assignment
plt.imshow(img)
plt.savefig("ok.png")
print("shown", img.size)
Tested on ✓ Linux ✓ Windows ✓ macOS
Output
shown (400, 267)

Cause 4: an array of arrays with different shapes

Stacking images of different sizes into one NumPy array gives an object array, which imshow() also rejects. Show the images one at a time, or resize them to the same shape first:

ragged.py
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

frames = [np.array(Image.open("photo.jpg").resize((40, 27))), np.array(Image.open("portrait.jpg").resize((27, 40)))]
batch = np.empty(len(frames), dtype=object)    # what you get from frames of different sizes
batch[:] = frames
print(batch.dtype, batch.shape)
plt.imshow(batch)
Tested on ✓ Linux ✓ Windows ✓ macOS
Output
object (2,)
Traceback (most recent call last):
  ...
TypeError: Image data of dtype object cannot be converted to float

For everything about displaying images (Jupyter, Tkinter, greyscale colour maps), see displaying a PIL image.

The outputs and images on this page are the real results of running every example with Pillow 12.3.0 on Python 3.13 (Linux) on 2026-10-15. Every example is also re-run automatically on macOS (Darwin 25.6.0, Pillow 12.3.0), Linux (Linux 6.17.0-1022-azure, Pillow 12.3.0), Windows (Windows 2025Server, Pillow 12.3.0); the line under each example shows the result per operating system. The DejaVu Sans font files sit next to each script so font examples behave the same everywhere. Sample photos: NASA/Sam Lott, public domain. Spotted something wrong? Tell us.