{"record":{"id":"27f1948cebf4522b","repo":"huggingface/transformers","slug":"image-must-be-a-numpy-array","errorCode":null,"errorMessage":"image must be a numpy array","messagePattern":"image must be a numpy array","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/transformers/image_transforms.py","lineNumber":409,"sourceCode":"    \"\"\"\n    Normalizes `image` using the mean and standard deviation specified by `mean` and `std`.\n\n    image = (image - mean) / std\n\n    Args:\n        image (`np.ndarray`):\n            The image to normalize.\n        mean (`float` or `Collection[float]`):\n            The mean to use for normalization.\n        std (`float` or `Collection[float]`):\n            The standard deviation to use for normalization.\n        data_format (`ChannelDimension`, *optional*):\n            The channel dimension format of the output image. If unset, will use the inferred format from the input.\n        input_data_format (`ChannelDimension`, *optional*):\n            The channel dimension format of the input image. If unset, will use the inferred format from the input.\n    \"\"\"\n    if not isinstance(image, np.ndarray):\n        raise TypeError(\"image must be a numpy array\")\n\n    if input_data_format is None:\n        input_data_format = infer_channel_dimension_format(image)\n\n    channel_axis = get_channel_dimension_axis(image, input_data_format=input_data_format)\n    num_channels = image.shape[channel_axis]\n\n    # We cast to float32 to avoid errors that can occur when subtracting uint8 values.\n    # We preserve the original dtype if it is a float type to prevent upcasting float16.\n    if not np.issubdtype(image.dtype, np.floating):\n        image = image.astype(np.float32)\n\n    if isinstance(mean, Collection):\n        if len(mean) != num_channels:\n            raise ValueError(f\"mean must have {num_channels} elements if it is an iterable, got {len(mean)}\")\n    else:\n        mean = [mean] * num_channels\n    mean = np.array(mean, dtype=image.dtype)","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/huggingface/transformers/blob/a597f974857b3d92939971296bc0deb93d33d780/src/transformers/image_transforms.py#L391-L427","documentation":"normalize (per-channel mean/std standardization) is numpy-only and raises TypeError for non-ndarray images. The subsequent axis inference and broadcasting math assume numpy arrays.","triggerScenarios":"normalize(pil_image, mean, std) or normalize(torch_tensor, mean, std); commonly hit in custom pipelines that forget conversion, or when a processor receives tensor images with do_normalize and non-numpy internal paths in user code.","commonSituations":"Reimplementing processor steps manually, mixing torchvision transforms (which want tensors) with transformers utils (which want numpy), or batching code that produces lists.","solutions":["Convert to numpy: np.array(pil_image) or tensor.numpy().","Or use torchvision.transforms.Normalize for tensor pipelines.","Best: rely on the image processor's __call__ to manage types end-to-end."],"exampleFix":"# before\nimg = normalize(pil_img, mean=IMAGENET_MEAN, std=IMAGENET_STD)  # TypeError\n\n# after\nimg = normalize(np.array(pil_img), mean=IMAGENET_MEAN, std=IMAGENET_STD)","handlingStrategy":"type-guard","validationCode":"import numpy as np\nimage = np.asarray(image) if not isinstance(image, np.ndarray) else image","typeGuard":"def ensure_ndarray(image):\n    return image if isinstance(image, np.ndarray) else np.asarray(image)","tryCatchPattern":null,"preventionTips":["Route tensor images to torchvision.transforms.Normalize instead.","Convert representations once at pipeline entry, not per-step."],"tags":["image-processing","numpy","normalization","typeerror"],"backgroundTag":null,"analyzedSha":"a597f974857b3d92939971296bc0deb93d33d780","analyzedAt":"2026-08-14T18:24:08.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}