roboflow/supervision · error · ValueError
HSV2BGR conversion requires a three-channel image
Error message
HSV2BGR conversion requires a three-channel image
What it means
HSV2BGR (used for annotator color maps) converts OpenCV's 8-bit HSV representation back to BGR and requires a 3-channel 3-D image. The fallback at src/supervision/_cv2/_color.py:54 raises when the input is not exactly (H, W, 3), since hue/saturation/value channels must all be present.
Source
Thrown at src/supervision/_cv2/_color.py:54
if image.dtype == np.uint8:
values = image.astype(np.uint32)
weighted = (
values[..., 0] * 3735
+ values[..., 1] * 19235
+ values[..., 2] * 9798
+ (1 << 14)
) >> 15
return weighted.astype(np.uint8)
float_values = (
image[..., 0].astype(np.float64) * 0.114
+ image[..., 1].astype(np.float64) * 0.587
+ image[..., 2].astype(np.float64) * 0.299
)
return _cast_array_like_opencv(float_values, image.dtype)
if code == _COLOR_HSV2BGR:
if image.ndim != 3 or image.shape[2] != 3:
raise ValueError("HSV2BGR conversion requires a three-channel image")
return _hsv_to_bgr(image)
raise ValueError(f"Unsupported color conversion code: {code}")
def _hsv_to_bgr(image: npt.NDArray[Any]) -> npt.NDArray[Any]:
"""Convert OpenCV's 8-bit HSV representation to BGR."""
values = image.astype(np.float64)
hue = values[..., 0] / 30.0
saturation = values[..., 1] / 255.0
value = values[..., 2] / 255.0
chroma = value * saturation
sector_index = np.floor(hue).astype(np.int64) % 6
sector = hue - np.floor(hue)
x = chroma * (1 - np.abs(((sector_index + sector) % 2) - 1))
match = value - chroma
zeros = np.zeros_like(chroma)View on GitHub (pinned to 7f254d9784)
Solutions
- Reshape to (H, W, 3): `img = img.reshape(h, w, 3)`
- Slice extra channels: `img[..., :3]`
- Index batched input per-image before conversion
Example fix
// before bgr = cv2.cvtColor(hsv_array, cv2.COLOR_HSV2BGR) # shape (H, W, 4) // after bgr = cv2.cvtColor(hsv_array[..., :3], cv2.COLOR_HSV2BGR)
Defensive patterns
Strategy: type-guard
Validate before calling
import numpy as np
def as_hsv_three_channel(image):
"""Return a (H, W, 3) HSV array for HSV2BGR conversion."""
arr = np.asarray(image)
if arr.ndim != 3 or arr.shape[2] != 3:
raise ValueError(f"HSV input must be (H, W, 3), got {arr.shape}")
return arr Type guard
def is_hsv_frame(image) -> bool:
"""HSV2BGR requires exactly (H, W, 3)."""
arr = np.asarray(image)
return arr.ndim == 3 and arr.shape[2] == 3 Prevention
- Build HSV images with np.zeros((h, w, 3), dtype=np.uint8) so the shape is exact
- Assert the shape after slicing/manipulating HSV arrays in annotator code
When it happens
Trigger: Calling `cv2.cvtColor(img, cv2.COLOR_HSV2BGR)` with a 2-D array, an (H, W, 4) array, or a batched 4-D array on the fallback backend.
Common situations: Annotator/heatmap code that builds HSV images with a stray extra channel or loses a dimension via slicing; feeding arrays straight from a model without reshaping.
Related errors
- BGR/RGB conversion requires a three-channel image
- GRAY2BGR conversion requires a two-dimensional image
- Drawing points must have shape (N, 2) or (N, 1, 2)
- Contour input must be a two-dimensional image
- Unsupported color conversion code: {code}
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/ae9e439ea617f52a.
Report an issue: GitHub.