roboflow/supervision · error · ValueError
BGR2GRAY conversion requires a three-channel image
Error message
BGR2GRAY conversion requires a three-channel image
What it means
BGR2GRAY computes a weighted sum of exactly three channels (BT.601 weights 0.114/0.587/0.299, with a fixed-point fast path for uint8). The fallback at src/supervision/_cv2/_color.py:35 requires a 3-channel 3-D image; RGBA (4-channel), grayscale (2-D), or batched input raises.
Source
Thrown at src/supervision/_cv2/_color.py:35
_COLOR_RGB2BGR,
)
def _cvt_color(image: npt.NDArray[Any], code: int) -> npt.NDArray[Any]:
"""Convert the BGR, RGB, grayscale, and 8-bit HSV formats used by Supervision."""
if code in (_COLOR_BGR2RGB, _COLOR_RGB2BGR):
if image.ndim != 3 or image.shape[2] != 3:
raise ValueError("BGR/RGB conversion requires a three-channel image")
return np.ascontiguousarray(image[..., ::-1])
if code == _COLOR_GRAY2BGR:
if image.ndim != 2:
raise ValueError("GRAY2BGR conversion requires a two-dimensional image")
return np.repeat(image[..., np.newaxis], 3, axis=2)
if code == _COLOR_BGR2GRAY:
if image.ndim != 3 or image.shape[2] != 3:
raise ValueError("BGR2GRAY conversion requires a three-channel image")
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:View on GitHub (pinned to 7f254d9784)
Solutions
- Drop the alpha channel first: `frame = frame[..., :3]`
- Skip the conversion if input is already 2-D grayscale
- Index batched arrays per-image: `frames[i]`
Example fix
// before gray = cv2.cvtColor(bgra_frame, cv2.COLOR_BGR2GRAY) // after gray = cv2.cvtColor(bgra_frame[..., :3], cv2.COLOR_BGR2GRAY)
Defensive patterns
Strategy: type-guard
Validate before calling
import numpy as np
def as_bgr_three_channel(image):
"""Return a (H, W, 3) BGR array for BGR2GRAY."""
arr = np.asarray(image)
if arr.ndim == 2:
return arr # already grayscale; caller can skip the conversion
if arr.ndim == 3 and arr.shape[2] > 3:
arr = arr[..., :3]
if arr.ndim != 3 or arr.shape[2] != 3:
raise ValueError(f"expected (H, W, 3), got {arr.shape}")
return arr Type guard
def is_bgr_frame(image) -> bool:
"""BGR2GRAY requires exactly (H, W, 3)."""
arr = np.asarray(image)
return arr.ndim == 3 and arr.shape[2] == 3 Prevention
- Drop alpha channels immediately after loading BGRA/RGBA sources
- Skip BGR2GRAY when input is already 2-D
When it happens
Trigger: `cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)` on an RGBA frame, a mask already grayscale, or a (N, H, W, 3) batched array.
Common situations: Images loaded with IMREAD_UNCHANGED keeping alpha; video sources yielding BGRA; downstream code assuming 3-channel frames receiving 4.
Related errors
- BGR/RGB conversion requires a three-channel image
- GRAY2BGR conversion requires a two-dimensional image
- Unsupported color conversion code: {code}
- At least one channel is required
- HSV2BGR conversion requires a three-channel image
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/01cf494c13ac8d23.
Report an issue: GitHub.