You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
numpy_to_pil removes singleton spatial dimensions from grayscale images #14901
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
importnumpyasnpfromdiffusers.utils.pil_utilsimportnumpy_to_pilx=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.
Hi @Afloat16, I’d be interested in working on this issue.
I reproduced the singleton spatial-dimension behavior and the proposed squeeze(-1) change makes sense for the HWC grayscale path. I can also add regression coverage for singleton height/width cases, including (1, 7, 1) and (1, 1, 1), while checking that the existing grayscale/RGB/RGBA behavior remains unchanged.
For the two DreamBooth examples, I’ll first verify the tensor/channel layout before making any change rather than applying an unrestricted axis replacement.
If the proposed scope looks good to the maintainers, I’d be happy to submit a PR.
Activity
vinitsonawane45 commentedon Sep 29, 2026
Hi @Afloat16, I’d be interested in working on this issue.
I reproduced the singleton spatial-dimension behavior and the proposed
squeeze(-1)change makes sense for the HWC grayscale path. I can also add regression coverage for singleton height/width cases, including(1, 7, 1)and(1, 1, 1), while checking that the existing grayscale/RGB/RGBA behavior remains unchanged.For the two DreamBooth examples, I’ll first verify the tensor/channel layout before making any change rather than applying an unrestricted axis replacement.
If the proposed scope looks good to the maintainers, I’d be happy to submit a PR.