Image Normalize
The node everybody skips, then blames when their embeddings are garbage
- image
- IMAGE
Image Normalize is the boring node that quietly decides whether everything after it works. The Timm Backbone Image Encode node does not touch your pixels before running the model - it expects an already-preprocessed image, and this is the node that does that preprocessing. Skip it and feed raw ComfyUI pixels straight into a backbone, and you'll get feature vectors that look like they were drawn from a random number generator. The model isn't broken; you just fed it pixels in a range it was never trained on.
The mechanism is unglamorous but worth understanding. ComfyUI hands you an IMAGE tensor in float32, with pixel values in [0, 1]. Vision backbones in timm were trained with a specific normalization: subtract a per-channel mean, divide by a per-channel std. This node does exactly that via torchvision's normalize, on each of the three channels, then hands back an IMAGE in the same [b, h, w, c] layout it received. Nothing else happens. There's no resizing here, no channel flipping - just the math.
The two inputs that matter
- mean and std - both strings, comma-separated, one value per channel. The default is
0.5, 0.5, 0.5, which maps[0,1]pixels to roughly[-1, 1]. That's a generic default, and here's the trap: it's usually wrong. What you set depends on which backbone you loaded:- Classic ImageNet-trained timm models (ResNets, EfficientNets, vanilla ViTs) want the ImageNet stats:
mean 0.485, 0.456, 0.406/std 0.229, 0.224, 0.225. - CLIP-family backbones - like the loader's default
timm/vit_huge_patch14_clip_224.laion2b- want the OpenCLIP stats instead:mean 0.48145, 0.45783, 0.40821/std 0.26863, 0.26130, 0.27578.
- Classic ImageNet-trained timm models (ResNets, EfficientNets, vanilla ViTs) want the ImageNet stats:
The model card on Hugging Face for whichever checkpoint you chose will state its normalization. Copy those numbers in.
Where people get burned
- Feeding the output into a normal img2img or VAE path. This node outputs normalized values, and the name "Image Normalize" is easy to misread as a generic preprocessor. If you plug it into anything that isn't a timm encode, the
[-1,1]-ish values will look washed out or broken. This node's output belongs on the input of Timm Backbone Image Encode and pretty much nowhere else. - Not resizing first. Normalizing doesn't fix resolution. Whatever you feed must be the backbone's training size (the
224in...clip_224), so put a resize node upstream before this one. - Typo'd the mean/std strings. They're parsed by splitting on commas, so
0.485,0.456,0.406works but a stray space-in-a-value or an extra comma will throw an error or silently produce garbage. Keep it simple:0.485, 0.456, 0.406.
Install is the same as the rest of the pack - ComfyUI Manager search timm backbone, or clone https://github.com/p1atdev/comfyui-timm-backbone into custom_nodes and pip install -r requirements.txt (just timm). Then put it between your resize and the encode node, set the numbers your model card actually lists, and stop blaming the backbone.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mean | STRING | 0.5, 0.5, 0.5 | — |
| std | STRING | 0.5, 0.5, 0.5 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |