Nodes/ComfyUI CV/cv2.GaussianBlur
ComfyUI Node

cv2.GaussianBlur

Gaussian blur with the knobs core ComfyUI hides from you

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.GaussianBlur
  • src
  • ksize
  • result
◄sigmaX0.0000►
◄sigmaY0.0000►
◄borderTypeBORDER_DEFAULT►
◄hintALGO_HINT_DEFAULT►

Core ComfyUI ships ImageBlur, which is a blur with one number on it. This node is the raw cv2.GaussianBlur call, and it's what you want the moment you care how the blur is built: real kernel size, separate X and Y sigma, border handling - and it takes a LATENT, which almost nothing else here does.

Why reach for it

Two jobs dominate. First, unsharp masking, which is the actual recipe behind every "sharpen" slider you've ever used: blur a copy, subtract it to isolate the high-frequency detail, add that detail back scaled. If you want to build that by hand instead of trusting a black box, you need a controllable blur. Second, feathering: run a MASK through it and you get a soft-edged matte for compositing, inpainting or pasting. Sharp masks make seams; blurred masks don't. And it's worth internalising the general rule this node belongs to: deterministic primitives - blur, gamma, colour match - are cheap and instant, and re-rolling a diffusion pass to fix something a filter was always going to fix better is how you burn an afternoon.

Inputs that matter

src is the polymorphic socket: wire an IMAGE, a MASK, an NPARRAY - or a LATENT. An IMAGE arrives as a uint8 BGR array, a MASK as single-channel uint8, an NPARRAY passes through untouched, and a LATENT arrives as a float32 [H,W,C] array with values untouched (latents are unbounded floats; nothing is rescaled to 0–255).

ksize is a two-component value (w, h), and it must be odd - (5, 5), (9, 3), anything like that. It doesn't have to be square. Or leave it (0, 0), in which case cv2 derives the kernel from the sigma instead.

sigmaX is the standard deviation of the Gaussian in pixels. sigmaY (advanced, collapsed until you open the node's advanced inputs) defaults to 0, which means "same as sigmaX". So the one-knob version of this node is: ksize (0, 0), sigmaX 4.

Optional: borderType (how pixels past the edge are invented - BORDER_WRAP isn't supported) and hint, which is the OpenCV AlgorithmHint: ALGO_HINT_DEFAULT, ALGO_HINT_ACCURATE or ALGO_HINT_APPROX. The approximate path is faster and not bit-identical, which is exactly the kind of thing that makes two machines disagree about pixel values.

The output is result, and it echoes the input's format: IMAGE in, IMAGE out; MASK in, MASK out; NPARRAY in, NPARRAY out. That echo is the whole reason this is pleasant to wire.

It batches, which is not true of everything here

Most raw cv2.* wrappers in this pack grab frame 0 of an IMAGE batch and call it a day. GaussianBlur is on the pack's frame-batch list: hand it a 200-frame IMAGE batch and every frame gets blurred and restacked. Same for src wired as a MASK batch. That's the difference between "usable for video" and "paste a loop node in front of it".

The LATENT path is the exception: only frame 0 becomes an array, and what comes back is a single-frame latent. Blur a five-frame video latent and you get one frame back. Latent blur is a tool for still sampling, not for clips.

Latent blur has a scale trap too. SD-family latents are 1/8 the picture size per axis, so sigmaX = 1 in latent space is roughly a 8-pixel blur in the final image. Small numbers mean a lot here.

Install

ComfyUI Manager, search ComfyUI CV, or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"

Restart ComfyUI. The pack needs Python ≥ 3.12 and a recent ComfyUI on the V3 node API. It's a fork of geroldmeisinger's opencv-comfyui - same NPARRAY socket, rewritten.

Where people get burned

  • Even ksize throws. (4, 4) isn't "slightly wrong", cv2 asserts on it, and the message complains about ksize.width without saying "make it odd". Keep them odd, or zero.
  • (0, 0) with sigma 0 throws too. The two knobs are alternatives: either give a size, or give a sigma. Leave both unset and there's nothing to compute from.
  • Huge kernels are slow, not just soft. Cost grows with the kernel area, so (0, 0) + sigma 40 is a real amount of work per frame, times every frame of your batch.
  • A non-contrib OpenCV silently deletes contrib nodes. If half the pack's menu vanished after you installed something else, that's the shared site-packages/cv2 being overwritten by opencv-python. The pack ships tools/repair_opencv_contrib.py --check (then --apply) for exactly that.
Categoryimage/CV/low-level/cv2 G

Inputs (6)

NameTypeDefaultDescription
srcCOMFY_MATCHTYPE_V3input image; the image can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. The image output(s) echo this input's format. A LATENT link is processed in latent space: frame 0 becomes a float32 [H,W,C] array (any channel count), values untouched. Arithmetic ops (add, multiply, etc.) also accept a full LATENT batch ({samples: [B,C,H,W]}) — the whole batch flows through when both inputs have the same batch size. Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
ksizeCV_TUPLE0,0Gaussian kernel size. ksize.width and ksize.height can differ but they both must be positive and odd. Or, they can be zero's and then they are computed from sigma. One value with 2 components (w, h) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place.
sigmaXFLOAT0.0000-1e+38–1e+38Gaussian kernel standard deviation in X direction.
sigmaYoptFLOAT0.0000-1e+38–1e+38Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height, respectively (see #getGaussianKernel for details); to fully control the result regardless of possible future modifications of all this semantics, it is recommended to specify all of ksize, sigmaX, and sigmaY. Preset to the OpenCV default (0.0).
borderTypeoptCOMBOBORDER_DEFAULTpixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not supported.
hintoptCOMBOALGO_HINT_DEFAULTImplementation modification flags. See #AlgorithmHint

Outputs (1)

NameTypeDescription
resultCOMFY_MATCHTYPE_V3Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY.