Nodes/ComfyDL/Image Normalize
ComfyUI Node

Image Normalize

Normalize an image to z-scores — and know it won't come back to [0,1]

By Cynthia-lxx·Created 2 months ago·Updated 2 days ago· 6
Image Normalize
  • image
  • image
mean0.5,0.5,0.5
std0.5,0.5,0.5
denormfalse

CdlImageNormalize applies the standard deep-learning preprocessing recipe - (x - mean) / std per channel - to a ComfyUI image. You know, the transform.Normalize step every textbook model and every pretrained PyTorch classifier was trained with. If you're feeding an image into ComfyDL's LeNet or ResNet nodes, this is the node that makes your input look like what those networks expect to see.

The one thing the README, the docstrings, and anyone who's burned by it will tell you up front: the output is not clipped to [0, 1] - and that's deliberate. The node docstring says it plainly: "the output is NOT clipped to [0, 1] - the normalized output follows the z-score range." Most ComfyDL image nodes clamp their output back to [0,1]; this one deliberately skips that, because the whole point of z-score normalization is that your values live around 0 and can go negative or above 1. If you plug the raw output straight into a preview, it may look black, white, or wildly wrong. That's the math working, not a bug.

How it works

mean and std are comma-separated strings, one value per channel: "0.485,0.462,0.406" for the classic ImageNet means, or a single value like "0.5" which broadcasts to all channels. If you supply the wrong number of values for the channel count, the node raises a clear error rather than silently doing the wrong thing. Flip denorm on and it runs the inverse - x * std + mean - which is how you take a normalized tensor back to displayable image space.

Inputs and output

The inputs that actually matter:

  • image - any IMAGE. For a 3-channel image, mean/std should have 3 values (or 1, which broadcasts).
  • mean, std - comma-separated strings. The defaults are "0.5,0.5,0.5" each, which is the "normalize to roughly [-1, 1]" convention, not ImageNet values.
  • denorm - false normalizes, true un-normalizes. Flip this to invert whatever you did.

The single output is image, same shape, now in z-score space. Pair it with the pack's Image Stats node to actually see the resulting mean and std per channel - that's the honest way to confirm your normalization did what you intended instead of eyeballing a blown-out preview.

Installing ComfyDL

This is part of the ComfyDL pack:

cd ComfyUI/custom_nodes
git clone https://github.com/Cynthia-lxx/ComfyDL
pip install -r ComfyDL/requirements.txt

Restart ComfyUI. The only extra dependency is matplotlib; torch and torchvision come with ComfyUI. ComfyUI Manager users: search "ComfyDL" first, and if it's absent (the pack isn't published to the official registry yet - its pyproject.toml still has a placeholder publisher ID), use Install via Git URL with the repo link.

Where people get burned

Three ways, mostly: forgetting that the output is z-scored and complaining the preview looks broken; feeding the normalized output straight into a VAE or image op that assumes [0,1] range; and mistyping the number of mean/std values and hitting the ValueError. If your downstream node needs a normal image again, chain this node with denorm set to true after your model does its thing, or clamp manually. And remember - the default "0.5,0.5,0.5" is the generic choice, not the ImageNet one. If your pretrained model's docs mention a specific mean/std, type those in.

Categoryimage/color

Inputs (4)

NameTypeDefaultDescription
imageIMAGE
meanSTRING0.5,0.5,0.5
stdSTRING0.5,0.5,0.5
denormBOOLEANfalse

Outputs (1)

NameTypeDescription
imageIMAGE