KoO Latent Noise Injector
Controlled Noise Injection, With the Receipts
- latent
- noise
- mask
- latent
- injected_noise
- noise_mask
- report
You know how img2img works: add noise to an image's latent, denoise it back. Denoise strength is a blunt instrument - it decides how much noise got added, at the front, invisibly, inside the sampler. The KoO Latent Noise Injector pulls that step out of the sampler and hands it to you as a node, with a mask, a choice of noise colour, and a printed report of what it actually did.
That's the honest pitch. It isn't a magic quality node. It's a knob the sampler normally hides, and hiding it is sometimes the thing standing between you and the result you want.
The mechanism, precisely
It requires a 4D latent ([B, C, H, W]) and does the following:
- Get noise - either from the optional
noiseinput (so it can chain off the Frequency Noise Mixer or a core noise node), or generate it fromseedusingnoise_type. - Normalize it to unit mean/std if
normalize_noiseis on, then multiply bynoise_scale. - Blend with
blend_mode:add(plainlatent + strength·noise),normalized_add(same path, normalized),lerp(latent·(1−s) + noise·s), orvariance_preserving(latent·√(1−s²) + noise·s- the default, and the one that keeps total energy stable as you dial strength). - Optionally restore the original mean and/or standard deviation (
preserve_mean,preserve_std, both on by default - this is what stops "inject texture" from becoming "brighten the image"). - Composite through the mask if you provided one, then compute the injected noise as the actual difference.
Step 5 is the part I like. The injected_noise output isn't the noise it drew - it's output − input, the real delta including the mask and the stats restoration. Feed that into a preview and you're looking at exactly what changed, not what you hoped changed.
Inputs and outputs
Required: latent, seed, strength (default 0.08, range 0–1, 0.005 steps), noise_type (gaussian, uniform, pink, blue, high_frequency, low_frequency), blend_mode, the preserve/clamp/normalize booleans, noise_scale, mask_blur, invert_mask, and batch_seed_mode.
Optional: noise (NOISE - supply your own instead of generating) and mask (MASK - restrict where injection lands).
Outputs: latent (the perturbed latent, ready for a sampler or an img2img pass), injected_noise (NOISE), noise_mask (MASK, the mask as it was applied), and report (STRING). The report prints blend mode, strength, mask coverage as a percentage, and before/after tensor statistics - min, max, mean, std for latent and injected noise. Keep it wired to a text display while you tune; it's the only way to know whether 0.08 did anything.
The strength range is worth internalising. 0.08 is a deliberate, subtle default: enough to break up a too-clean upscale, not enough to change composition. If you're used to denoise 0.5 in img2img, understand that this is a different scale - 0.5 here is a violent perturbation, and variance_preserving will keep the latent looking statistically normal while the content inside it is well on its way to the bin.
Why you'd want this instead of denoise
Three real uses. First, breaking up the plastic look of a heavy upscale by injecting a little band-limited noise before a low-denoise second pass - pink noise at a small strength is the plausible setting, because it puts energy in the low frequencies where a tiled upscaler's repeats live. Second, masked injection: use a mask to add texture only in the flat region that a detailer left smooth, without touching the rest. Third, A/B science - the report plus the statistics node is genuinely how you find out whether "adding noise" is helping or whether you're just looking at a different seed.
The mask path is a straight borrow from inpainting logic: mask blur is feathering, and the usual 4–12px advice for seams applies unchanged. Overdo mask_blur here and the injection bleeds into regions you meant to protect, which looks exactly like the node ignoring your mask.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/kevintronchin-blip/koo-nodes-pack
Restart ComfyUI. Pure tensor work: no models, no extra packages (all four declared deps - torch, numpy, Pillow, aiohttp - ship with ComfyUI), no frontend component. It lives under KoO/Noise Lab.
Manager/Registry listing at v1.0.3 is pending moderation approval; use the README's ZIP install if search comes up empty, extracting to ComfyUI/custom_nodes/koo-nodes-pack with __init__.py directly inside.
Troubleshooting
"must be a 4D tensor." You fed it a 5D still latent. Run the pack's Krea → 4D adapter first.
Nothing happens at strength 1.0. Check blend_mode. With variance_preserving at 1.0 the latent term goes to zero - you get pure noise, which is the mathematically correct answer and not what most people mean. lerp is the more intuitive extreme.
The image got brighter. preserve_mean or preserve_std is off. Turn them back on before you conclude anything about the texture.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| latent | LATENT | — | |
| seed | INT | 00–18446744073709550000 | — |
| strength | FLOAT | 0.0800–1 | — |
| noise_type | COMBO | gaussian | 6 options: gaussian, uniform, pink, blue, high_frequency, low_frequency |
| blend_mode | COMBO | variance_preserving | 4 options: add, normalized_add, lerp, variance_preserving |
| preserve_mean | BOOLEAN | true | — |
| preserve_std | BOOLEAN | true | — |
| clamp_output | BOOLEAN | false | — |
| normalize_noise | BOOLEAN | true | — |
| noise_scale | FLOAT | 1.000.01–4 | — |
| mask_blur | FLOAT | 0.000–64 | — |
| invert_mask | BOOLEAN | false | — |
| batch_seed_mode | COMBO | fixed | 3 options: fixed, increment, random |
| noiseopt | NOISE | — | |
| maskopt | MASK | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| latent | LATENT | — |
| injected_noise | NOISE | — |
| noise_mask | MASK | — |
| report | STRING | — |