lllyasviel/ControlNet · error · Exception

Image dtype must be float32.

Error message

Image dtype must be float32.

What it means

write_pfm serializes a numpy array to PFM, which only supports float32 pixel data. Any other dtype (float64, uint8, float16) is rejected before writing, because the PFM endianness/byte layout assumes 4-byte floats.

Source

Thrown at annotator/midas/utils.py:71

        data = np.flipud(data)

        return data, scale


def write_pfm(path, image, scale=1):
    """Write pfm file.

    Args:
        path (str): pathto file
        image (array): data
        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":

View on GitHub (pinned to ed85cd1e25)

Solutions

  1. Cast before writing: image = image.astype(np.float32)
  2. If using write_depth, ensure the depth array you pass is float32
  3. Add an assertion in your pipeline right after depth inference to catch dtype drift early

Example fix

# before
write_pfm('/tmp/d.pfm', depth)  # depth is float64
# after
write_pfm('/tmp/d.pfm', depth.astype(np.float32))
Defensive patterns

Strategy: validation

Validate before calling

assert image.dtype == np.float32, f'need float32, got {image.dtype}'
image = image.astype(np.float32, copy=False)

Type guard

def is_float32(img) -> bool:
    return getattr(img, 'dtype', None) == np.float32

Try / catch

try:
    write_pfm(path, image)
except Exception as e:
    if 'dtype must be float32' in str(e):
        write_pfm(path, image.astype(np.float32))
    else:
        raise

Prevention

When it happens

Trigger: Calling write_pfm (directly or via write_depth) with a numpy image whose dtype is not np.float32, e.g. a float64 depth array from computation or a uint8 image.

Common situations: Depth predictions in float64 after arithmetic; normalizing with astype('float16') to save memory; feeding model outputs without an explicit dtype cast.

Related errors


AI-assisted analysis of lllyasviel/ControlNet@ed85cd1e25 (2026-08-27). Data as JSON: /api/errors/ee72bf16d4750c83. Report an issue: GitHub.