keras-team/keras · error · ValueError
Input arrays must be multi-channel 2D images.
Error message
Input arrays must be multi-channel 2D images.
What it means
apply_affine_transform works only on 3D arrays (a 2D image plus a channel dimension). If x.ndim != 3 it raises this ValueError right after the axis checks. Grayscale images stored as 2D arrays and batched 4D tensors are both rejected.
Source
Thrown at keras/src/legacy/preprocessing/image.py:1808
"""
# Input sanity checks:
# 1. x must 2D image with one or more channels (i.e., a 3D tensor)
# 2. channels must be either first or last dimension
if np.unique([row_axis, col_axis, channel_axis]).size != 3:
raise ValueError(
"'row_axis', 'col_axis', and 'channel_axis' must be distinct"
)
# shall we support negative indices?
valid_indices = set([0, 1, 2])
actual_indices = set([row_axis, col_axis, channel_axis])
if actual_indices != valid_indices:
raise ValueError(
f"Invalid axis' indices: {actual_indices - valid_indices}"
)
if x.ndim != 3:
raise ValueError("Input arrays must be multi-channel 2D images.")
if channel_axis not in [0, 2]:
raise ValueError(
"Channels are allowed and the first and last dimensions."
)
transform_matrix = None
if theta != 0:
theta = np.deg2rad(theta)
rotation_matrix = np.array(
[
[np.cos(theta), -np.sin(theta), 0],
[np.sin(theta), np.cos(theta), 0],
[0, 0, 1],
]
)
transform_matrix = rotation_matrix
if tx != 0 or ty != 0:View on GitHub (pinned to 7a34a03db6)
Solutions
- Expand grayscale images to (H, W, 1) with np.expand_dims(img, -1)
- For batches, loop: out[i] = apply_affine_transform(x[i], ...)
- Prefer tf.keras.layers.RandomRotation and other preprocessing layers for batched data
Example fix
# before random_rotation(gray_img, 20) # shape (H, W) # after random_rotation(np.expand_dims(gray_img, -1), 20) # (H, W, 1)
Defensive patterns
Strategy: validation
Validate before calling
assert img.ndim == 3, f'expected 3D image, got {img.ndim}D'
if img.ndim == 2:
img = img[..., None] Type guard
def is_single_image(x):
return getattr(x, 'ndim', None) == 3 Prevention
- Normalize grayscale images to (H, W, 1) at load time
- Loop over the batch dimension instead of passing batches
When it happens
Trigger: Passing a 2D grayscale image (H, W) with no channel axis; passing a 4D batch (N, H, W, C) directly to apply_affine_transform or random_rotation/random_shift/random_shear/random_zoom.
Common situations: Loading grayscale images with PIL/imageio that yield shape (H, W); forgetting to slice a batch tensor before augmenting one image at a time.
Related errors
- Expected the input image to be rank 3 or 4. Received inputs.
- 'row_axis', 'col_axis', and 'channel_axis' must be distinct
- Invalid axis' indices: {actual_indices - valid_indices}
- Channels are allowed and the first and last dimensions.
- `adapt()` can only be called on a tf.data.Dataset or a dict
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/46d67839ec761ade.
Report an issue: GitHub.