{"record":{"id":"bcf577f56a1f994e","repo":"opendatalab/MinerU","slug":"unsupported-image-shape-for-unimerswinimageprocess","errorCode":null,"errorMessage":"Unsupported image shape for UnimerSwinImageProcessor: {image.shape}","messagePattern":"Unsupported image shape for UnimerSwinImageProcessor: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/image_processing_unimer_swin.py","lineNumber":33,"sourceCode":"        ):\n        self.input_size = [int(_) for _ in image_size]\n        assert len(self.input_size) == 2\n\n    def __call__(self, item):\n        image = self.prepare_input(item)\n        return self.to_normalized_gray_tensor(image)\n\n    @staticmethod\n    def to_normalized_gray_tensor(image: np.ndarray) -> torch.Tensor:\n        \"\"\"将图像确定性转灰度、按 UniMERNet 参数归一化，并转为单通道 tensor。\"\"\"\n        if image.ndim == 2:\n            gray = image\n        elif image.ndim == 3 and image.shape[2] == 1:\n            gray = image[:, :, 0]\n        elif image.ndim == 3 and image.shape[2] == 3:\n            gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)\n        else:\n            raise ValueError(f\"Unsupported image shape for UnimerSwinImageProcessor: {image.shape}\")\n\n        normalized = (gray.astype(np.float32) - 0.7931 * 255.0) / (0.1738 * 255.0)\n        return torch.from_numpy(normalized[None, :, :])\n\n    @staticmethod\n    def crop_margin(img: Image.Image) -> Image.Image:\n        data = np.array(img.convert(\"L\"))\n        data = data.astype(np.uint8)\n        max_val = data.max()\n        min_val = data.min()\n        if max_val == min_val:\n            return img\n        data = (data - min_val) / (max_val - min_val) * 255\n        gray = 255 * (data < 200).astype(np.uint8)\n\n        coords = cv2.findNonZero(gray)  # Find all non-zero points (text)\n        a, b, w, h = cv2.boundingRect(coords)  # Find minimum spanning bounding box\n        return img.crop((a, b, w + a, h + b))","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/opendatalab/MinerU/blob/4fe4bde114a23ee5dd637eae99b767f4669bf58c/mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/image_processing_unimer_swin.py#L15-L51","documentation":"UnimerSwinImageProcessor.to_normalized_gray_tensor converts arbitrary input arrays to single-channel grayscale before normalization. It accepts 2-D arrays, 3-D with 1 channel, and 3-D with 3 channels; anything else (4-channel RGBA, 2-channel, ndim 1 or 4) is rejected because no defined grayscale conversion exists.","triggerScenarios":"Passing an RGBA crop (shape (H, W, 4)) straight from PIL's .convert('RGBA') or a PNG with alpha into the processor; passing a (H, W, 2) LA-mode array; passing a flattened or batched array with ndim != 2/3.","commonSituations":"Cropping formula regions from PDF page renders that keep an alpha channel, mixing BGR/RGBA pipelines from OpenCV-based upstream stages, or feeding batched tensors (N, H, W) instead of a single image.","solutions":["Convert to RGB before calling: img = img.convert('RGB') for PIL or cv2.cvtColor(img, cv2.COLOR_RGBA2BGR) then back, dropping alpha.","If you have a PIL Image, pass modes 'L' or 'RGB' only.","For batched arrays, iterate and pass one (H, W[, C]) image at a time.","Composite RGBA onto a white background if alpha carries meaning."],"exampleFix":"# before\ncrop = pil_page.crop(box)  # RGBA page render\nfeat = processor(crop)\n\n# after\ncrop = pil_page.crop(box).convert('RGB')\nfeat = processor(crop)","handlingStrategy":"type-guard","validationCode":"def normalize_shape(img: np.ndarray) -> np.ndarray:\n    if img.ndim == 3 and img.shape[2] not in (1, 3):\n        img = img[:, :, :3]\n    return img","typeGuard":"def is_supported_gray_input(img: np.ndarray) -> bool:\n    return img.ndim == 2 or (img.ndim == 3 and img.shape[2] in (1, 3))","tryCatchPattern":"try:\n    feat = processor(crop)\nexcept ValueError as e:\n    if 'Unsupported image shape' in str(e):\n        feat = processor(np.asarray(Image.fromarray(crop).convert('RGB')))\n    else:\n        raise","preventionTips":["Convert every crop to 'L' or 'RGB' PIL mode right after cropping.","Composite RGBA onto white before feeding formula models.","Log crop .shape in debug builds to catch pipeline format drift early."],"tags":["image-processing","validation","formula-recognition"],"backgroundTag":null,"analyzedSha":"4fe4bde114a23ee5dd637eae99b767f4669bf58c","analyzedAt":"2026-08-14T21:29:18.456Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}