Nodes/comfyui_my_img_util/OpenCV Denoise (Luma/Chroma)
ComfyUI Node

OpenCV Denoise (Luma/Chroma)

Kill high-ISO noise without burning a diffusion pass

By sugarkwork·Created about a year ago·Updated 7 months ago· 2
OpenCV Denoise (Luma/Chroma)
  • image
  • IMAGE
h_luminance3.0
h_color3.0
search_window5
template_window3

The instinct when an image looks noisy is to reach for img2img at low denoise and hope. That's a heavy hammer: it can rewrite details, re-roll the seed lottery, and costs you a full sampling pass. For plain sensor-style noise - the grainy speckle and the red/green color blotches you get from high ISO or a low-light render - there's a deterministic option that's been sitting in OpenCV for years: non-local means denoising. OpenCV Denoise (Luma/Chroma) wraps it as a node, with separate strength controls for the brightness noise and the color noise.

How it works

It's a thin wrapper over cv2.fastNlMeansDenoisingColored. The idea behind non-local means: instead of blurring nearby pixels (which smears edges), it searches the image for similar patches and averages them together, weighted by how similar they are. Similar patches reinforce each other; noise, which doesn't repeat, averages out. That's what lets it preserve edges far better than a Gaussian.

The node converts each input frame to BGR, calls the function with your four parameters, converts back to RGB, and stacks the batch. It handles multi-frame batches, so it works frame-by-frame on a video if you're patient - it's a legitimately cheap frame denoiser. It does not carry alpha: RGB in, RGB out, so don't feed it an RGBA image expecting transparency to survive.

The inputs and outputs that matter

  • image - the IMAGE to denoise.
  • h_luminance - strength for luma (brightness) noise. Higher = smoother but more detail lost. The author's README suggests ~1.5–2.5; the default is 3.
  • h_color - strength for chroma (color) noise. Color blotches are lower-frequency and can usually take more; the README suggests setting this a bit higher than h_luminance.
  • search_window - how far the node hunts for similar patches (an odd square side length, 5–50). Bigger = better quality, slower.
  • template_window - the patch size used for similarity comparison (odd, 3–20). Keep this small; big patches blur.

Output: image, the denoised IMAGE.

Installing it

It's in the comfyui_my_img_util pack with four other image utilities. ComfyUI Manager → search "comfyui_my_img_util", or:

cd ComfyUI/custom_nodes
git clone https://github.com/sugarkwork/comfyui_my_img_util
cd comfyui_my_img_util
pip install -r requirements.txt

Restart, and it's under "Image/Post-Processing". This is the one node in the pack that actually needs opencv-python - and because the pack imports cv2 at module level, a missing OpenCV install takes down every node in the pack, this one included. pip install -r requirements.txt handles it. No models, nothing to download, runs on CPU.

Common issues

  • "It didn't do anything." Look at the search window. The default search_window of 5 is tiny - OpenCV's own default is 21. At 5, the node only compares patches in a tiny neighborhood, so it's very gentle. Crank it to 15–21 when you actually have noise to kill.
  • "It turned everything to plastic." That's h_luminance too high, or the template window creeping up. Luma strength removes noise and fine detail together - there's no free lunch in NLM. Start luma at 1.5–2.5, keep the template at 3–5, and only then touch the search window.
  • Slow on big images or video. Non-local means is inherently expensive - it's comparing patches, not convolving. A 4K frame at a large search window takes a while; that's the price of the quality.
  • It's global. It doesn't know your subject is a face and the noise is the background - it smooths everything to the same degree. For selective work, like skin smoothing, you want an edge-aware bilateral filter in a pack like bvhari/ComfyUI_ImageProcessing instead (the post-processing doc has the full bilateral-vs-Gaussian breakdown).

Where you'd actually use it

This is the post-processing doc's favorite move: a deterministic pixel operation where a diffusion pass is overkill. Denoise a high-ISO photo before upscaling, so an ESRGAN pass isn't amplifying the noise it's fed. Clean up low-light renders. Tame video frames where temporal denoising isn't available. And if you're dealing with a mix of real noise and banding, this plus a gamma or sigmoid curve from the other post-processing packs will get you further than any single slider.

CategoryImage/Post-Processing

Inputs (5)

NameTypeDefaultDescription
imageIMAGE
h_luminanceFLOAT3.00–100
h_colorFLOAT3.00–100
search_windowINT55–50
template_windowINT33–20

Outputs (1)

NameTypeDescription
IMAGEIMAGE