roboflow/supervision · error · TypeError

`image` must be a numpy.ndarray or PIL.Image.Image. Received

Error message

`image` must be a numpy.ndarray or PIL.Image.Image. Received type: {type(image)}

What it means

Raised by `sv.get_image_resolution_wh` (and helpers with the same guard) when `image` is neither `numpy.ndarray` nor `PIL.Image.Image`. The function reads `(width, height)` from either type; any other object cannot be measured, so a TypeError is raised naming the actual type received.

Source

Thrown at src/supervision/utils/image.py:650

        >>> sv.get_image_resolution_wh(image)
        (1920, 1080)

        ```
    """
    if isinstance(image, np.ndarray):
        if image.ndim < 2:
            raise ValueError(
                "NumPy image must have at least 2 dimensions (H, W, ...). "
                f"Received shape: {image.shape}"
            )
        height, width = image.shape[:2]
        return int(width), int(height)

    if isinstance(image, Image.Image):
        width, height = image.size
        return int(width), int(height)

    raise TypeError(
        "`image` must be a numpy.ndarray or PIL.Image.Image. "
        f"Received type: {type(image)}"
    )


class ImageSink:
    """
    Save sequential images into a directory through a context manager.

    `ImageSink` creates the target directory on entry and writes each image
    using `save_image`, incrementing the image name pattern after every save.
    """

    def __init__(
        self,
        target_dir_path: str,
        overwrite: bool = False,
        image_name_pattern: str = "image_{:05d}.png",

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Load the image first (`cv2.imread` / `PIL.Image.open`) and pass the array object.
  2. Convert tensors: `tensor.detach().cpu().numpy()`.
  3. Unwrap custom frame containers: `frame.array` or the equivalent attribute holding the ndarray.

Example fix

# before
w, h = sv.get_image_resolution_wh(frame_metadata)  # custom wrapper object
# after
w, h = sv.get_image_resolution_wh(frame_metadata.image)  # the underlying np.ndarray
Defensive patterns

Strategy: type-guard

Validate before calling

assert isinstance(image, (np.ndarray, Image.Image)), f'unsupported image type {type(image)}'

Type guard

from PIL import Image
import numpy as np

def is_image(x: Any) -> bool:
    return isinstance(x, (np.ndarray, Image.Image))

Prevention

When it happens

Trigger: Calling `sv.get_image_resolution_wh(path_string)`, `sv.get_image_resolution_wh(torch_tensor)`, or passing a dataclass/dict that wraps pixel data instead of the array itself.

Common situations: Passing a path where an already-loaded image is expected; handing a framework tensor or a custom `Frame` wrapper object to a supervision utility in a video pipeline; mixing up argument order so another value lands in `image`.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/c7cbd5effa3d2261. Report an issue: GitHub.