Nodes/ComfyUI CV/cv2.pyrDown
ComfyUI Node

cv2.pyrDown

The half-size step you build pyramids with, not the resizer you want

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.pyrDown
  • src
  • dstsize
  • result
◄borderTypeBORDER_DEFAULT►

pyrDown blurs, then drops every second row and column. That's a Gaussian pyramid step, and it has exactly two homes: building multi-scale representations (which is what pyramids are for), and cheap "this is half the size, I don't care about the last 5% of quality" downscales.

If your goal is "make this 4K render into a 1080p image", this is not the node. upscaling.md covers the real options - a proper resampler, or one of the neural upscalers. A pyramid step is a half-size step: 1920 → 960, not 1920 → 1080.

What it's actually for

Multi-scale work. The pack's own Laplacian-pyramid blending example, CV Multi-Band Blend (Laplacian pyramid), is a three-level blend along a soft seam - the classic compositing trick where you feed the eye low-frequency content gradually so no seam is visible. You can't build a Laplacian pyramid without a reduce step, and this is it. The other reason to reach for it: a preview or a cheap processing path. Run an expensive analysis on a quarter of the pixels, then push the result back up.

How it works, and the gotchas

The image is convolved with a small Gaussian kernel and then subsampled. Two consequences that matter:

  • The output size is ((w+1)/2, (h+1)/2) - rounded, and odd dimensions can land somewhere you didn't expect (1015 wide becomes 508, not 507). It's intended behaviour, and it's why pyramid code uses it in a loop rather than assuming a factor.
  • dstsize only nudges it. The optional size input is a CV_TUPLE - (width, height), typed in place or wired from CV Tuple - and OpenCV will only accept a value within a pixel or two of the computed half-size. Leave it at (0, 0).
  • borderType is a dropdown for edge extrapolation; BORDER_CONSTANT isn't supported on this one. Default BORDER_DEFAULT is what you want 99% of the time.

Inputs and outputs

src takes an IMAGE, MASK or NPARRAY - a ComfyUI IMAGE is unwrapped to uint8 BGR. Optional dstsize and borderType as above. The output is result, and it echoes the input's format: IMAGE in, IMAGE out; MASK in, MASK out. No adapter node needed. It's also in the per-frame batch set, so a clip goes through frame by frame and comes back as a clip.

Wiring it downstream: the natural partner is cv2.pyrUp (the other half of the pyramid), or any of the pack's multi-scale curated nodes. To compare against a proper resampler, put it side by side with cv2.resize's INTER_AREA - the pyramid step is slightly softer because of the pre-blur, which is precisely why it's correct for pyramid building and slightly wasteful for a one-off downscale.

Install

One of ~470 generated wrappers in ComfyUI CV by bmad4ever. 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. Python ≥ 3.12 and a modern V3-API ComfyUI, no models.

Common issues

"The size is off by a pixel." See above - ((w+1)/2, (h+1)/2). If you need exact dimensions on odd-sized inputs, crop to even first, or use an explicit resize.

OpenCV rejects my dstsize. It has to be within ~1 pixel of exactly half; this input exists for the cases where the rounding isn't what you need, not for arbitrary target sizes.

The image got soft. It did - there's a Gaussian blur in the pipeline by definition. If softness is unexpected, you probably wanted a resampler (INTER_AREA) rather than a pyramid reduce.

It errors on a mask. It shouldn't; MASK input is supported and echoes back as MASK. If you get a channel complaint, check what's upstream - a 2-channel or 4-channel array is the usual cause.

Contrib nodes missing from the menu. Different symptom, same pack: verify your OpenCV wheel is the contrib build (tools/repair_opencv_contrib.py --check).

Categoryimage/CV/low-level/cv2 P

Inputs (3)

NameTypeDefaultDescription
srcCOMFY_MATCHTYPE_V3input image. 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.
dstsizeoptCV_TUPLE0,0size of the output image. 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.
borderTypeoptCOMBOBORDER_DEFAULTPixel extrapolation method, see #BorderTypes (#BORDER_CONSTANT isn't supported)

Outputs (1)

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