Nodes/opencv-comfyui/OpenCV fastNlMeansDenoising_0
ComfyUI Node

OpenCV fastNlMeansDenoising_0

FastNlMeansDenoising_0

By geroldmeisinger·Created about a year ago·Updated about a year ago· 35
OpenCV fastNlMeansDenoising_0
  • src
  • dst
  • nparray
h
templateWindowSize
searchWindowSize

You generated something and it came out noisy - sensor-looking grain, JPEG blocks, the faint shimmer you get from a too-aggressive upscale. Your first instinct might be to stick it back through the model. Don't. A plain blur will smooth the noise but turn every edge to mush, and a diffusion re-pass is a lottery. This is the middle path: non-local means denoising, one of the genuinely clever deterministic filters OpenCV has had for years.

fastNlMeansDenoising_0 wraps cv2.fastNlMeansDenoising, and the idea behind it is what makes it worth knowing. A normal blur averages each pixel with its neighbors - that's why edges smear. Non-local means instead averages each pixel with pixels that look like it, anywhere in the image. A patch of skin in the corner is denoised by averaging with similar skin patches elsewhere, not by dragging in the edge that's right next to it. Edges survive, noise doesn't. It's slower than a blur - it's searching the image - but it's the right tool when "denoise" needs to mean "keep the structure."

The inputs that matter

  • src (NPARRAY) - the image. Grayscale only. This overload works on a single-channel 8-bit array; feed it a BGR image and you'll get the classic img.type() == CV_8UC1 assertion error the README warns about. Convert first with cvtColor using code 6 (BGR2GRAY).
  • h (FLOAT) - filter strength. Higher = smoother, blobbier. OpenCV's rule of thumb is ~3 for grayscale.
  • templateWindowSize (INT) - the patch size being compared, an odd number like 3–7. Bigger patches = softer result, more compute.
  • searchWindowSize (INT) - how far the algorithm looks for similar patches, default 21. This is the cost knob; bumping it up is where the minutes go.
  • dst (NPARRAY, optional) - an out-parameter. Leave it unplugged; the README tells you to avoid optional dst inputs on principle.

Output is a single nparray - the denoised image, same size and type as the input. Wire it into Nparrays2Image to get back a Comfy IMAGE.

Installing it

One of ~600 nodes in geroldmeisinger/opencv-comfyui - install the pack once. In ComfyUI Manager search opencv-comfyui, or:

cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui

then restart. Requirements are opencv-contrib-python, numpy, torch. If ComfyUI fails to start with Cannot import name 'guidedFilter' from 'cv2.ximgproc', conflicting OpenCV installs are fighting - one consistent opencv-contrib-python fixes it.

Two gotchas before you wire it up. Everything in this pack runs on nparrays in BGR, 0–255 - bring your image in via Image2Nparray, take the result out via Nparrays2Image. And batch size must be 1; if you get the "batch_size==1" error, put ImageFromBatch (length 1) in front.

When to reach for it

Grayscale inputs are a real constraint for photo work, so for color images you'll more often want fastNlMeansDenoisingColored_0 instead. But if your pipeline is already grayscale - depth maps, masks, line art, upscaled alpha - this is the cleanest edge-preserving denoise in the pack, and it's deterministic and free, the exact kind of cheap primitive the post-processing layer exists to push. Don't pay a diffusion pass for work a filter does in milliseconds.

Categoryimage/OpenCV

Inputs (5)

NameTypeDefaultDescription
srcNPARRAY
hFLOAT
templateWindowSizeINT
searchWindowSizeINT
dstoptNPARRAY

Outputs (1)

NameTypeDescription
nparrayNPARRAY