opendatalab/MinerU · error · ValueError

Invalid image mode. Please provide 'rgb' or 'bgr'.

Error message

Invalid image mode. Please provide 'rgb' or 'bgr'.

What it means

Raised by MineRU's image contrast helper (calculate_contrast in span_pre_proc) when img_mode is neither 'rgb' nor 'bgr'. The function converts the input numpy image to grayscale via OpenCV and must know the channel order to pick COLOR_RGB2GRAY vs COLOR_BGR2GRAY; any other string (or a defaulted None) cannot be mapped. The mode is a caller-supplied convention flag, not derived from the array itself.

Source

Thrown at mineru/utils/span_pre_proc.py:666

    del span['chars']


def calculate_contrast(img, img_mode) -> float:
    """
    计算给定图像的对比度。
    :param img: 图像,类型为numpy.ndarray
    :Param img_mode = 图像的色彩通道,'rgb' 或 'bgr'
    :return: 图像的对比度值
    """
    if img_mode == 'rgb':
        # 将RGB图像转换为灰度图
        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    elif img_mode == 'bgr':
        # 将BGR图像转换为灰度图
        gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    else:
        raise ValueError("Invalid image mode. Please provide 'rgb' or 'bgr'.")

    # 计算均值和标准差
    mean_value = np.mean(gray_img)
    std_dev = np.std(gray_img)
    # 对比度定义为标准差除以平均值(加上小常数避免除零错误)
    contrast = std_dev / (mean_value + 1e-6)
    # logger.debug(f"contrast: {contrast}")
    return round(contrast, 2)

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. Pass exactly 'rgb' or 'bgr' (lowercase) matching how the array was actually produced: 'bgr' for cv2.imread, 'rgb' for PIL.Image → numpy.
  2. Normalize external inputs: img_mode = img_mode.strip().lower() and validate against {'rgb','bgr'} before calling.
  3. If your images are grayscale (2-D arrays), convert appropriately upstream — this helper only accepts 3-channel orders.

Example fix

# before
img = np.array(Image.open(p))          # RGB channels
contrast = calculate_contrast(img, img_mode='RGB')  # ValueError

# after
img = np.array(Image.open(p))
contrast = calculate_contrast(img, img_mode='rgb')
Defensive patterns

Strategy: type-guard

Validate before calling

IMG_MODES = {'rgb', 'bgr'}
img_mode = 'rgb' if loaded_with_pil else 'bgr'
assert img_mode in IMG_MODES

Type guard

from typing import Literal, TypeGuard
ImgMode = Literal['rgb', 'bgr']

def is_img_mode(v: object) -> TypeGuard[ImgMode]:
    return isinstance(v, str) and v in ('rgb', 'bgr')

Try / catch

try:
    contrast = calculate_contrast(img, img_mode=img_mode)
except ValueError as e:
    if 'Invalid image mode' in str(e):
        raise TypeError(f'img_mode must be rgb|bgr, got {img_mode!r}') from e
    raise

Prevention

When it happens

Trigger: Calling calculate_contrast(img, img_mode=...) with values like 'RGB' (case matters), 'gray', None, or omitting an explicit value in wrapper code whose default is not one of the two literals. Common with images loaded by PIL (RGB world) passed with a BGR habit from OpenCV code, or vice versa — though swapped-but-valid modes silently skew results rather than raise.

Common situations: Wrapper code copies an OpenCV BGR default while feeding PIL-loaded images; an uppercase or abbreviated mode string ('RGB', 'R') is passed; a config-driven pipeline forwards an arbitrary colorspace name ('gray', 'yuv') into a function that only understands the two grayscale-conversion orders.

Related errors


AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14). Data as JSON: /api/errors/ee03aa933fef37a7. Report an issue: GitHub.