roboflow/supervision · error · ValueError
Connected-component input must be a two-dimensional image
Error message
Connected-component input must be a two-dimensional image
What it means
Connected-component labeling is inherently a 2D operation; the fallback validates that the input array has exactly two dimensions before converting it to a boolean mask. 3D arrays (video volumes, multi-channel images) or 1D/0D arrays are rejected.
Source
Thrown at src/supervision/_cv2/_components.py:15
"""Private connected-component and mask-topology fallbacks."""
from __future__ import annotations
from typing import Any, cast
import numpy as np
import numpy.typing as npt
def _validate_binary_image(image: npt.NDArray[Any]) -> npt.NDArray[np.bool_]:
"""Validate and normalize a two-dimensional component image."""
values = np.asarray(image)
if values.ndim != 2:
raise ValueError("Connected-component input must be a two-dimensional image")
return cast(npt.NDArray[np.bool_], values != 0)
def _label(
image: npt.NDArray[Any], connectivity: int
) -> tuple[int, npt.NDArray[np.int32]]:
"""Label foreground pixels with the requested four- or eight-way topology."""
if connectivity not in (4, 8):
raise ValueError("Only 4- and 8-connectivity are supported")
from scipy import ndimage
structure = ndimage.generate_binary_structure(2, 1 if connectivity == 4 else 2)
labels, count = ndimage.label(_validate_binary_image(image), structure=structure)
return int(count), np.ascontiguousarray(labels, dtype=np.int32)
def _connected_components(View on GitHub (pinned to 7f254d9784)
Solutions
- Convert color input to grayscale first: gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY).
- Squeeze channel/batch dims: mask = mask.reshape(h, w) or mask.squeeze().
- Loop over frames/batch items and label each 2D slice separately.
Example fix
# before count, labels = cv2.connectedComponents(bgr_image) # (H, W, 3) # after gray = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2GRAY) count, labels = cv2.connectedComponents(gray)
Defensive patterns
Strategy: validation
Validate before calling
img2d = image if image.ndim == 2 else image.reshape(image.shape[:2]) count, labels = cv2.connectedComponents(img2d)
Type guard
def is_labelable(img: np.ndarray) -> bool:
return np.asarray(img).ndim == 2 Prevention
- Convert BGR to grayscale before labeling
- Squeeze (H, W, 1) masks to 2D
- Label video/multi-channel data per 2D slice
When it happens
Trigger: Calling cv2.connectedComponents on a (H, W, 3) BGR image, a (T, H, W) video stack, or a squeezed-to-1D mask.
Common situations: Forgetting cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) before labeling; passing a batch of masks at once; masks with a spurious trailing channel dimension (H, W, 1).
Related errors
- Only 4- and 8-connectivity are supported
- Resize dimensions must be positive
- Unsupported flip code: {flip_code}
- epsilon must be non-negative
- Blur kernel dimensions must be positive
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/afe49b27a6996ebc.
Report an issue: GitHub.