{"record":{"id":"0a9fd1b84f4fd691","repo":"keras-team/keras","slug":"invalid-image2-rank-expected-rank-3-single-image","errorCode":null,"errorMessage":"Invalid image2 rank: expected rank 3 (single image) or rank 4 (batch of images). Received input with shape: image2.shape={image2.shape}","messagePattern":"Invalid image2 rank: expected rank 3 \\(single image\\) or rank 4 \\(batch of images\\)\\. Received input with shape: image2\\.shape=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/ops/image.py","lineNumber":2727,"sourceCode":"            image1,\n            image2,\n            max_val=self.max_val,\n            filter_size=self.filter_size,\n            filter_sigma=self.filter_sigma,\n            k1=self.k1,\n            k2=self.k2,\n            data_format=self.data_format,\n        )\n\n    def compute_output_spec(self, image1, image2):\n        if len(image1.shape) not in (3, 4):\n            raise ValueError(\n                \"Invalid image1 rank: expected rank 3 (single image) \"\n                \"or rank 4 (batch of images). Received input with shape: \"\n                f\"image1.shape={image1.shape}\"\n            )\n        if len(image2.shape) not in (3, 4):\n            raise ValueError(\n                \"Invalid image2 rank: expected rank 3 (single image) \"\n                \"or rank 4 (batch of images). Received input with shape: \"\n                f\"image2.shape={image2.shape}\"\n            )\n        # Output is a scalar per image in the batch\n        if len(image1.shape) == 3:\n            output_shape = ()\n        else:\n            output_shape = (image1.shape[0],)\n        return KerasTensor(shape=output_shape, dtype=image1.dtype)\n\n\n@keras_export(\"keras.ops.image.ssim\")\ndef ssim(\n    image1,\n    image2,\n    max_val=1.0,\n    filter_size=11,","sourceCodeStart":2709,"sourceCodeEnd":2745,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/ops/image.py#L2709-L2745","documentation":"The SSIM op's shape validation for image2: it must be rank 3 or rank 4, mirroring the image1 check. It fires when the second (target/reference) image has the wrong rank.","triggerScenarios":"ssim(image1 (N,H,W,C), image2 (H,W,C)) with unbatched ground truth; image2 stored as a rank-2 grayscale array.","commonSituations":"Comparing a model's batched predictions against a single reference image; dataset ground-truth stored channel-less.","solutions":["Batch the reference: image2[None, ...] to match rank 4.","Add a channel axis to grayscale ground truth.","Verify image1.shape == image2.shape before calling ssim."],"exampleFix":"# before\nssim(preds, ref_img, 1.0)  # preds (N,H,W,C), ref (H,W,C)\n\n# after\nssim(preds, np.stack([ref_img] * len(preds)), 1.0)","handlingStrategy":"validation","validationCode":"import numpy as np\na, b = np.asarray(image1), np.asarray(image2)\nif b.ndim == a.ndim - 1: b = np.stack([b] * a.shape[0])\nassert a.shape == b.shape, (a.shape, b.shape)","typeGuard":"def same_image_shapes(a, b):\n    return np.asarray(a).shape == np.asarray(b).shape and np.asarray(a).ndim in (3, 4)","tryCatchPattern":null,"preventionTips":["Store ground truth in the same layout as predictions.","Tile single reference images explicitly."],"tags":["keras","image","ssim","shape-validation"],"backgroundTag":"tensor-rank-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}