lllyasviel/ControlNet · error · Exception
Image must have H x W x 3, H x W x 1 or H x W dimensions.
Error message
Image must have H x W x 3, H x W x 1 or H x W dimensions.
What it means
Raised by write_pfm when the numpy array's shape is not 2D (H x W grayscale), 3D with 3 channels (H x W x 3 color), or 3D with 1 channel (H x W x 1). The PFM writer cannot serialize arrays with other channel counts or dimensions, such as batched 4D tensors or multi-channel non-RGB data.
Source
Thrown at ldm/modules/midas/utils.py:82
scale (int, optional): Scale. Defaults to 1.
"""
with open(path, "wb") as file:
color = None
if image.dtype.name != "float32":
raise Exception("Image dtype must be float32.")
image = np.flipud(image)
if len(image.shape) == 3 and image.shape[2] == 3: # color image
color = True
elif (
len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1
): # greyscale
color = False
else:
raise Exception("Image must have H x W x 3, H x W x 1 or H x W dimensions.")
file.write("PF\n" if color else "Pf\n".encode())
file.write("%d %d\n".encode() % (image.shape[1], image.shape[0]))
endian = image.dtype.byteorder
if endian == "<" or endian == "=" and sys.byteorder == "little":
scale = -scale
file.write("%f\n".encode() % scale)
image.tofile(file)
def read_image(path):
"""Read image and output RGB image (0-1).
Args:View on GitHub (pinned to ed85cd1e25)
Solutions
- Remove batch/channel dimensions: image = image.squeeze() or image = image[0] as appropriate
- If writing a single channel from a multi-channel map, select it first: image = feat[:, :, 0]
- Assert the shape before saving: assert image.ndim == 2 or (image.ndim == 3 and image.shape[2] in (1, 3))
- For non-visual N-channel tensors, save with np.save instead of PFM
Example fix
# before write_depth(path, prediction) # prediction.shape == (1, 384, 384) # after write_depth(path, prediction.squeeze()) # or prediction[0] if batch dim
Defensive patterns
Strategy: validation
Validate before calling
def valid_pfm_shape(img) -> bool:
import numpy as np
return img.ndim == 2 or (img.ndim == 3 and img.shape[2] in (1, 3)) Type guard
from typing import Protocol
import numpy as np
def pfm_image_ok(img: np.ndarray) -> bool:
return valid_pfm_shape(img) and img.dtype == np.float32 Prevention
- squeeze() batch dims right after model forward
- Assert shape before save: assert depth.ndim == 2
- Save non-RGB/1-channel tensors with np.save, not PFM
When it happens
Trigger: Calling write_pfm(path, image) with image.shape of length 4 (e.g. (1, H, W, 1) batched depth), length 3 with shape[2] not in (1, 3) (e.g. H x W x 2 or H x W x 38 MiDaS raw channels), or a 1D/0D array.
Common situations: Passing a raw MiDaS model output with an extra batch dimension, forgetting to squeeze a (H, W, 1) prediction, or writing attention/feature maps with arbitrary channel counts.
Related errors
- Image dtype must be float32.
- Image dtype must be float32.
- Image must have H x W x 3, H x W x 1 or H x W dimensions.
- Malformed PFM header.
- Not a PFM file:
AI-assisted analysis of lllyasviel/ControlNet@ed85cd1e25 (2026-08-27).
Data as JSON: /api/errors/849aeacb7e5130bf.
Report an issue: GitHub.