PaddlePaddle/PaddleOCR · error · ValueError

Make sure that the channel dimension of the pixel values mat

Error message

Make sure that the channel dimension of the pixel values match with the one set in the configuration.

What it means

DonutSwinPatchEmbeddings.forward unpacks the input as (N, C, H, W) and requires C == self.num_channels (3 for the pretrained Swin tokenizer used by Donut/DOC-VQA rec models). Unlike the top-level model, this embeddings module does not repeat-interleave grayscale input, so a mismatch raises ValueError immediately.

Source

Thrown at ppocr/modeling/backbones/rec_donut_swin.py:368

        )

    def maybe_pad(self, pixel_values, height, width):
        if width % self.patch_size[1] != 0:
            pad_values = (0, self.patch_size[1] - width % self.patch_size[1])
            if self.is_export:
                pad_values = paddle.to_tensor(pad_values, dtype="int32")
            pixel_values = nn.functional.pad(pixel_values, pad_values)
        if height % self.patch_size[0] != 0:
            pad_values = (0, 0, 0, self.patch_size[0] - height % self.patch_size[0])
            if self.is_export:
                pad_values = paddle.to_tensor(pad_values, dtype="int32")
            pixel_values = nn.functional.pad(pixel_values, pad_values)
        return pixel_values

    def forward(self, pixel_values) -> Tuple[paddle.Tensor, Tuple[int]]:
        _, num_channels, height, width = pixel_values.shape
        if num_channels != self.num_channels:
            raise ValueError(
                "Make sure that the channel dimension of the pixel values match with the one set in the configuration."
            )
        pixel_values = self.maybe_pad(pixel_values, height, width)
        embeddings = self.projection(pixel_values)

        _, _, height, width = embeddings.shape
        output_dimensions = (height, width)
        embeddings = embeddings.flatten(2).transpose([0, 2, 1])

        return embeddings, output_dimensions


# Copied from transformers.models.swin.modeling_swin.SwinPatchMerging
class DonutSwinPatchMerging(nn.Layer):
    """
    Patch Merging Layer.

    Args:

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Convert images to 3-channel RGB before batching: img = img.convert('RGB') in the preprocessing
  2. If you call DonutSwinModel.forward (not the embeddings directly), pass a non-None pixel_values tensor — it repeats 1-channel input to 3 automatically
  3. Align the config's num_channels with the actual input channels (default and pretrained weights expect 3)

Example fix

# before
img = Image.open(path)              # may be L or RGBA
x = to_tensor(img).unsqueeze(0)      # C=1 -> ValueError

# after
img = Image.open(path).convert('RGB')
x = to_tensor(img).unsqueeze(0)      # C=3
Defensive patterns

Strategy: type-guard

Validate before calling

assert pixel_values.ndim == 4 and pixel_values.shape[1] == 3, \
    f'expected (N, 3, H, W) input, got {tuple(pixel_values.shape)}'

Type guard

def is_rgb_batch(t) -> bool:
    return t.ndim == 4 and t.shape[1] == 3

Prevention

When it happens

Trigger: Calling DonutSwinEmbeddings/patch embedding forward with a 1-channel tensor, or with 4-channel input (e.g. alpha kept, or RGBA PIL image converted with .tensor() without convert('RGB')); or building the backbone with a non-default num_channels and feeding normal images.

Common situations: Preprocessing pipeline that skips img.convert('RGB') for grayscale source scans (very common with document OCR), or a config where num_channels was changed to 1 without routing through DonutSwinModel.forward (which does repeat channel 1 to 3).

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/84812b8f04aa7aeb. Report an issue: GitHub.