{"record":{"id":"44fa25b29e97dbe0","repo":"keras-team/keras","slug":"expected-the-input-image-to-be-rank-3-or-4-receiv","errorCode":null,"errorMessage":"Expected the input image to be rank 3 or 4. Received inputs.shape={images_shape}","messagePattern":"Expected the input image to be rank 3 or 4\\. Received inputs\\.shape=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/layers/preprocessing/image_preprocessing/random_brightness.py","lineNumber":104,"sourceCode":"                + f\"Received: value_range={value_range}\"\n            )\n        self.value_range = sorted(value_range)\n\n    def get_random_transformation(self, data, training=True, seed=None):\n        if isinstance(data, dict):\n            images = data[\"images\"]\n        else:\n            images = data\n        images_shape = self.backend.shape(images)\n        rank = len(images_shape)\n        if rank == 3:\n            rgb_delta_shape = (1, 1, 1)\n        elif rank == 4:\n            # Keep only the batch dim. This will ensure to have same adjustment\n            # with in one image, but different across the images.\n            rgb_delta_shape = [images_shape[0], 1, 1, 1]\n        else:\n            raise ValueError(\n                \"Expected the input image to be rank 3 or 4. Received \"\n                f\"inputs.shape={images_shape}\"\n            )\n        if not training:\n            return {\"rgb_delta\": self.backend.numpy.zeros(rgb_delta_shape)}\n\n        if seed is None:\n            seed = self._get_seed_generator(self.backend._backend)\n        rgb_delta = self.backend.random.uniform(\n            minval=self.factor[0],\n            maxval=self.factor[1],\n            shape=rgb_delta_shape,\n            seed=seed,\n        )\n        rgb_delta = rgb_delta * (self.value_range[1] - self.value_range[0])\n        return {\"rgb_delta\": rgb_delta}\n\n    def transform_images(self, images, transformation, training=True):","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/layers/preprocessing/image_preprocessing/random_brightness.py#L86-L122","documentation":"RandomBrightness.get_random_transformation computes a brightness delta shaped by input rank: rank 3 (single image) or rank 4 (batched). Images of any other rank (e.g. rank 2 grayscale without channels, or rank 5) raise this ValueError.","triggerScenarios":"Calling the layer on a (224, 224) grayscale array with no channel axis, or a rank-5 tensor from an extra batch dim.","commonSituations":"Grayscale images loaded without keepdims, e.g. PIL Image.convert('L') then np.array giving (H, W); stacking an already-batched tensor.","solutions":["Add a channel axis: images[..., None] for grayscale rank-2 inputs","Remove stray leading dims: images = np.squeeze(images, axis=0)","Feed (H, W, C) or (batch, H, W, C) consistently"],"exampleFix":"# before\nimages = np.array(img.convert('L'))  # (H, W) rank 2\nout = layer(images)\n# after\nimages = np.array(img.convert('L'))[..., None]  # (H, W, 1)\nout = layer(images)","handlingStrategy":"validation","validationCode":"if len(images.shape) == 2:\n    images = images[..., None]\nassert len(images.shape) in (3, 4), images.shape","typeGuard":"def is_rank3or4(x):\n    return len(getattr(x, 'shape', ())) in (3, 4)","tryCatchPattern":null,"preventionTips":["Always load images with a channel axis (np.array(img) on RGB, add [..., None] for grayscale)","Assert rank at dataset map time, before layers run"],"tags":["keras","random-brightness","tensor-rank","image-preprocessing"],"backgroundTag":"input-shape-validation-failed","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}