{"record":{"id":"84812b8f04aa7aeb","repo":"PaddlePaddle/PaddleOCR","slug":"make-sure-that-the-channel-dimension-of-the-pixel","errorCode":null,"errorMessage":"Make sure that the channel dimension of the pixel values match with the one set in the configuration.","messagePattern":"Make sure that the channel dimension of the pixel values match with the one set in the configuration\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"ppocr/modeling/backbones/rec_donut_swin.py","lineNumber":368,"sourceCode":"        )\n\n    def maybe_pad(self, pixel_values, height, width):\n        if width % self.patch_size[1] != 0:\n            pad_values = (0, self.patch_size[1] - width % self.patch_size[1])\n            if self.is_export:\n                pad_values = paddle.to_tensor(pad_values, dtype=\"int32\")\n            pixel_values = nn.functional.pad(pixel_values, pad_values)\n        if height % self.patch_size[0] != 0:\n            pad_values = (0, 0, 0, self.patch_size[0] - height % self.patch_size[0])\n            if self.is_export:\n                pad_values = paddle.to_tensor(pad_values, dtype=\"int32\")\n            pixel_values = nn.functional.pad(pixel_values, pad_values)\n        return pixel_values\n\n    def forward(self, pixel_values) -> Tuple[paddle.Tensor, Tuple[int]]:\n        _, num_channels, height, width = pixel_values.shape\n        if num_channels != self.num_channels:\n            raise ValueError(\n                \"Make sure that the channel dimension of the pixel values match with the one set in the configuration.\"\n            )\n        pixel_values = self.maybe_pad(pixel_values, height, width)\n        embeddings = self.projection(pixel_values)\n\n        _, _, height, width = embeddings.shape\n        output_dimensions = (height, width)\n        embeddings = embeddings.flatten(2).transpose([0, 2, 1])\n\n        return embeddings, output_dimensions\n\n\n# Copied from transformers.models.swin.modeling_swin.SwinPatchMerging\nclass DonutSwinPatchMerging(nn.Layer):\n    \"\"\"\n    Patch Merging Layer.\n\n    Args:","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/ppocr/modeling/backbones/rec_donut_swin.py#L350-L386","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Convert images to 3-channel RGB before batching: img = img.convert('RGB') in the preprocessing","If you call DonutSwinModel.forward (not the embeddings directly), pass a non-None pixel_values tensor — it repeats 1-channel input to 3 automatically","Align the config's num_channels with the actual input channels (default and pretrained weights expect 3)"],"exampleFix":"# before\nimg = Image.open(path)              # may be L or RGBA\nx = to_tensor(img).unsqueeze(0)      # C=1 -> ValueError\n\n# after\nimg = Image.open(path).convert('RGB')\nx = to_tensor(img).unsqueeze(0)      # C=3","handlingStrategy":"type-guard","validationCode":"assert pixel_values.ndim == 4 and pixel_values.shape[1] == 3, \\\n    f'expected (N, 3, H, W) input, got {tuple(pixel_values.shape)}'","typeGuard":"def is_rgb_batch(t) -> bool:\n    return t.ndim == 4 and t.shape[1] == 3","tryCatchPattern":null,"preventionTips":["Always convert('RGB') in the image preprocessing for Donut/DOC-VQA models","Call DonutSwinModel.forward (auto-repeats 1-channel) instead of embeddings directly when feeding grayscale","Assert channel dim right after batch collation, before the forward pass"],"tags":["input-validation","preprocessing","donut-swin","channels"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}