roboflow/supervision · error · TypeError

Unsupported image type: {type(scene)}

Error message

Unsupported image type: {type(scene)}

What it means

Raised by the ensure_cv2_image_for_class_method decorator's wrapper in supervision.utils.conversion when the `scene` argument passed to an annotator's annotate() method is neither a np.ndarray nor a PIL.Image.Image. The decorator transparently converts PIL scenes to BGR NumPy arrays, runs the annotator, and pastes the result back; any other type cannot be handled.

Source

Thrown at src/supervision/utils/conversion.py:41

    Assumes the annotators modify the scene in-place.

    Raises:
        TypeError: If `scene` is not a `numpy.ndarray` or `PIL.Image.Image`.
    """

    @functools.wraps(annotate_func)
    def wrapper(self: Any, scene: ImageType, *args: Any, **kwargs: Any) -> Any:
        if isinstance(scene, np.ndarray):
            return annotate_func(self, scene, *args, **kwargs)

        if isinstance(scene, Image.Image):
            scene_np = pillow_to_cv2(scene)
            annotated_np = annotate_func(self, scene_np, *args, **kwargs)
            scene.paste(cv2_to_pillow(annotated_np))
            return scene

        raise TypeError(f"Unsupported image type: {type(scene)}")

    return cast(F, wrapper)


@deprecated(  # type: ignore[untyped-decorator]
    target=ensure_cv2_image_for_class_method,
    deprecated_in="0.27.0",
    remove_in="0.31.0",
)
def ensure_cv2_image_for_annotation(
    annotate_func: F,
) -> F:
    return cast(F, void(annotate_func))


def ensure_cv2_image_for_standalone_function(
    image_processing_fun: F,
) -> F:

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Convert tensors to NumPy: scene = tensor.cpu().numpy() before annotate().
  2. If you have a path, load it first: scene = cv2.imread(path).
  3. Convert other image objects to a PIL Image or np.ndarray (e.g. np.asarray(qimage)).
  4. Check for None — a failed upstream load (cv2.imread returning None) flows into annotate().

Example fix

// before
frame = model.predict_source(...)  # torch.Tensor
annotated = annotator.annotate(frame, detections)  # TypeError

// after
frame = frame.cpu().numpy()
annotated = annotator.annotate(frame, detections)
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(scene, (np.ndarray, Image.Image)):
    if hasattr(scene, 'cpu') and hasattr(scene, 'numpy'):
        scene = scene.cpu().numpy()
    else:
        scene = np.asarray(scene)
assert isinstance(scene, (np.ndarray, Image.Image))

Type guard

ImageType = Union[np.ndarray, Image.Image]

def is_annotatable(scene: object) -> TypeGuard[ImageType]:
    return isinstance(scene, (np.ndarray, Image.Image))

Try / catch

try:
    annotator.annotate(scene, detections)
except TypeError as e:
    if 'Unsupported image type' in str(e):
        raise TypeError(f'Convert {type(scene)} to np.ndarray first') from e
    raise

Prevention

When it happens

Trigger: Calling an annotator method like box_annotator.annotate(scene, detections) with scene as a torch.Tensor, a cv2.VideoCapture frame object, a file path string, a matplotlib figure, or None.

Common situations: Passing a PyTorch tensor straight from a model without calling .cpu().numpy(); passing an image path instead of a loaded array; passing a QImage or other GUI-framework image type; reusing old code where scene was previously accepted in another format.

Related errors


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