π§Ή Advanced Image Denoiser
The denoiser that measures your noise before it touches it
- image
- image
- noise_report
Run almost any denoiser on an AI image and you get the same sad result: the noise is gone, but so is every bit of micro-texture, and the output looks like it was smeared with vaseline. The π§Ή Advanced Image Denoiser is built to avoid exactly that. It first measures how noisy your image actually is (wavelet-based sigma estimation), then in smart_auto mode applies just enough denoising to remove it - no more - and finally runs an edge-aware detail recovery pass that puts the original fine detail back only along edges. Flat areas stay clean, grain disappears, and fabric/foliage/hair keep their texture.
Why you'd actually reach for it
This is a post-processing node, not a generation node. The classic uses: cleaning up grainy real photos before they go into an img2img or inpainting pass, de-noising a scan or a heavily compressed source before upscaling (upscalers love to amplify noise), or scrubbing the ISO-style grain that some photorealism LoRAs bake in when you don't want it. The KB's upscaling notes are the right mental model: real restoration of genuinely noisy, compressed sources is SUPIR's job; for "my image has grain and I want it gone without losing detail," this is a much cheaper, fully local stop. No model files, no GPU, no API key - pure OpenCV/numpy running on your CPU.
How it works
Every frame goes through estimate_noise_sigma, which uses scikit-image's wavelet-based noise estimator (with an Immerkaer Laplacian fallback if skimage is missing) to get a per-image noise level in 0β255 sigma units. smart_auto then feeds that measured sigma into a Non-Local Means pass - strength 0.5 means "apply exactly the measured level." The edge-aware detail recovery is the clever bit: it computes an edge map from the denoised image (so noise spikes don't count as edges), then soft-thresholds it against the measured noise floor and adds the original's high-frequency detail back only where that threshold is exceeded. That's why raising detail_recovery is safe - flat areas never get their noise re-injected.
There are eight methods under the hood, and the honest summary is: smart_auto for almost everything, non_local_means when you want separate luminance/chroma control over photo grain, bilateral for portraits, guided_filter for a fast pure-numpy smooth, wavelet (BayesShrink) and total_variation (Chambolle) for synthetic or AI-generated flat areas, bm3d for maximum quality when you've installed the optional dependency, and median for salt-and-pepper impulse artifacts only. The built-in UI panel gives each method its own contextual sliders, so you won't drown in irrelevant knobs.
The inputs that actually matter
- image - an IMAGE tensor, batched frames fine. It denoises each frame.
- method -
smart_autois the default and the one you should start on. - strength - keep it LOW, 0.05β0.25. The default 0.15 is a good starting point; 0.5 in smart_auto applies exactly the measured noise, and higher over-smooths fast.
- detail_recovery - default 0.35, safe to raise to 0.5β0.6 to bring texture back.
The optional ones worth knowing: luminance_strength/chroma_strength (manual methods only - luminance smoothing causes visible blur, so keep it low; chroma can go 2β3Γ higher since eyes barely notice chroma blur), blend_original (0.1β0.2 for a natural look), and sharpen_mode (luminance_only avoids color fringing on a post-sharpen). The outputs are image and a noise_report STRING that tells you the measured sigma per image - wire that to any text-display node and you'll finally know how noisy your input actually was. Handy for deciding whether denoising is even worth it.
Install
ComfyUI Manager works - search "comfyui-advanced-denoiser" and install. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/MONKEYFOREVER2/comfyui-advanced-denoiser
cd comfyui-advanced-denoiser
pip install -r requirements.txt # opencv-python, scikit-image, numpy
# optional, enables the bm3d method:
pip install bm3d
Then restart ComfyUI and look under image β denoising. It's CPU-only, so it runs anywhere, and the node ships its own smoke test (python test_node.py) if you want to verify your install.
Gotchas
The one real trap: the bm3d method is a silent fallback. If you pick it without pip install bm3d, it doesn't error - it just runs adaptive NLM instead and prints a note to your console. Fine output, but not what you asked for. Also, a quirk worth knowing: the author deliberately made the node accept out-of-range widget values from workflows saved with older versions of the node, clamping them internally instead of rejecting the prompt - so a stale workflow won't brick, but your sliders may read one thing while the math does another. If output looks unexpectedly smooth, check noise_report first; it's the quickest way to see what the node thinks it was cleaning up.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | β | |
| method | COMBO | smart_auto | smart_auto measures the noise level and applies just enough denoising. bm3d is the highest quality (needs `pip install bm3d`). |
| strength | FLOAT | 0.150β1 | Keep this LOW (0.05β0.25). In smart_auto, 0.5 applies exactly the measured noise level; higher over-smooths. |
| detail_recovery | FLOAT | 0.350β1 | Edge-aware: restores fine texture from the original along edges only, so flat areas stay clean. Safe to raise. |
| luminance_strengthopt | FLOAT | 0.100β1 | Manual methods only. Brightness-channel denoising β keep low, this is what causes blur if overdone. |
| chroma_strengthopt | FLOAT | 0.300β1 | Color-noise removal. Eyes are less sensitive to chroma blur, so this can be 2β3Γ higher than luminance. |
| patch_sizeopt | INT | 73β15 | NLM comparison patch (odd). 7 is standard. |
| search_windowopt | INT | 217β35 | NLM search area (odd). Bigger = better but slower. |
| wavelet_levelopt | INT | 31β6 | Wavelet decomposition depth. |
| blend_originalopt | FLOAT | 0.000β1 | Mix the untouched original back in for a natural look (0.1β0.2 is plenty). |
| sharpen_modeopt | COMBO | off | Optional post-sharpen. luminance_only avoids color fringing. |
| sharpen_amountopt | FLOAT | 0.200β1 | Sharpening intensity. |
| sharpen_radiusopt | FLOAT | 0.300.05β1 | Detail scale: low = fine micro-detail. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | β |
| noise_report | STRING | β |