cv2.getGaussianKernel
The blur kernel you only need when GaussianBlur isn't enough
- nparray
This node hands you a Gaussian kernel - a column vector of weights - and nothing else. It does not blur anything. If what you actually want is a blurred image, you're in the wrong place: cv2.GaussianBlur, or a pack's blur node, builds this kernel internally from sigmaX/sigmaY and applies it in one shot. Reach for cv2.getGaussianKernel when you need the weights themselves - to feed filter2D, to build a separable pass, or to reuse one kernel in two places.
What comes out, and why it's a column
The output is nparray, a raw OpenCV ndarray on the pack's NPARRAY socket: a N×1 matrix, N being ksize. That shape is not a quirk, it's the contract. A separable blur is a row kernel and a column kernel applied in sequence, and OpenCV's sepFilter2D wants exactly that - the row in kx, the column in ky. One call gives you the column; transpose it (cv2.transpose, also in this pack) if you need the row as its own array, or run the same kernel in both slots for an isotropic blur.
The kernels are normalized - they sum to 1 - so using one with filter2D is a weighted average, not a sharpen. That's also why you can't get a "Gaussian unsharp mask" out of this by cranking ksize: bigger kernel, same total weight, softer result.
The two inputs that decide the shape of the curve
ksize is the aperture - the pack's own tooltip says it should be odd and positive, and it means it: an even size can't be symmetric about one centre pixel, which is the whole point of a kernel you're going to convolve with.
sigma is the standard deviation, and here's the trap. The field defaults to 0, and a non-positive sigma doesn't mean "no smoothing" - it means derive it from the size, via the formula in the tooltip: sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8. So ksize=3 quietly gives you sigma=0.8, ksize=5 gives 1.1, and so on. If you want a specific softness, type it; if you leave it at 0 you're letting the size decide, which is fine but rarely what people think they're doing.
ktype is optional, defaults to CV_64F, and renders as a dropdown built from the pack's shared depth enum - so you'll see CV_8U, CV_16S, CV_32S and friends in the list. Ignore all but two of them. OpenCV accepts CV_32F or CV_64F here; anything else earns you an error, and CV_32F is the sensible pick only if you're hand-feeding a float32 pipeline and want to skip a conversion.
Reading it back
An N×1 array of small floats is not an image, so don't be surprised when Preview CV Array renders a thin grey strip. Inspect CV Data is the right tool - it prints shape, dtype, min, max and mean for any value, and you wire its summary output into the core Preview as Text node to actually see it. That's also the general debugging habit for this whole pack: raw wrappers return data, not pictures, and Inspect CV Data is how you check your assumption. The same habit applies at a bigger scale: this whole family of deterministic pixel operations exists so you can reach for a millisecond of arithmetic instead of burning a diffusion pass on a job a lookup table does perfectly.
Install
Requires Python ≥ 3.12 and a recent ComfyUI (the pack is built on the V3 node API). The only real dependency is the contrib OpenCV wheel:
pip install "opencv-contrib-python-headless~=5.0.0.93"
Then either search ComfyUI CV in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
and restart. Everything here is generated at import time from the pack's own registry of cv2 functions, so a node simply won't exist if your installed OpenCV doesn't expose that function.
Where people get burned
- Non-contrib wheels.
opencv-pythonandopencv-contrib-pythonshare onesite-packages/cv2, so installing a non-contrib wheel over a contrib one silently empties the contrib submodules and their nodes vanish from the menu. The pack shipstools/repair_opencv_contrib.pyfor this ---checkdiagnoses,--applyfixes. - Even
ksize. It still runs, which is worse than failing: you get a kernel that isn't centred, and a subtly shifted result. - The pack's own honesty note. The README states plainly that this codebase was written with heavy LLM assistance and that the auto-generated wrappers are uncurated - you handle conversions and edge cases yourself. For a four-line pure function like this one that's harmless; keep it in mind as you go deeper into the raw
cv2.*lane.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| ksize | INT | 0-2147483648–2147483647 | Aperture size. It should be odd ( $\texttt{ksize} \mod 2 = 1$ ) and positive. |
| sigma | FLOAT | 0.0000-1e+38–1e+38 | Gaussian standard deviation. If it is non-positive, it is computed from ksize as `sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8`. |
| ktypeopt | COMBO | CV_64F | Type of filter coefficients. It can be CV_32F or CV_64F . |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |