Skip to content

numpy_to_pil removes singleton spatial dimensions from grayscale images #14901

Description

@Afloat16

Problem

The grayscale path uses image.squeeze() before passing an image to Pillow. This removes height and width when either equals one, instead of removing only the channel dimension.

Reproduction

import numpy as np
from diffusers.utils.pil_utils import numpy_to_pil
x = np.zeros((1, 7, 1), dtype=np.float32)
y = numpy_to_pil(x)[0]
print(y.size)  # expected (7, 1), not (1, 7)
# A (1, 1, 1) image also loses both spatial dimensions.

Proposed scope

Use image.squeeze(-1) for the HWC grayscale branch. The same Image.fromarray(image.squeeze(), mode="L") pattern occurs once in src/diffusers/utils/pil_utils.py and twice in src/diffusers/image_processor.py; a fix should cover all three paths with common singleton-height/width regressions. Two DreamBooth examples, train_dreambooth_lora_flux2_img2img.py and train_dreambooth_lora_flux2_klein_img2img.py, also use unrestricted squeeze for CHW grayscale tensors; those need a channel-axis-specific review rather than blindly applying axis -1.

Validation and limits

Current pil_utils blob: 72d4704fa945f0cc4edfa8e6a15955cd75fd18f1. Current image_processor blob: 4f6f4bd52b9c2c6efd4a35fa50706a8642bc6c75. The isolated pil_utils helper harness ran 9 cases: 4 failed/5 passed before, 9 passed after. It checks dimensions and pixel values for singleton spatial axes, batches, and ordinary grayscale/RGB/RGBA. Python 3.12.14, NumPy 2.3.5, Pillow 12.3.0. This is not a full pipeline or repository suite; the repeated image_processor paths and examples have been inspected but not integration-tested.

Opening an issue first for maintainer agreement on scope. I checked related grayscale work, including #488; that added grayscale support, whereas this concerns preserving singleton spatial axes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions