cv2.pyrDown
The half-size step you build pyramids with, not the resizer you want
- src
- dstsize
- result
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. dstsizeonly nudges it. The optional size input is aCV_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).borderTypeis a dropdown for edge extrapolation;BORDER_CONSTANTisn't supported on this one. DefaultBORDER_DEFAULTis 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).
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| src | COMFY_MATCHTYPE_V3 | input 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. | |
| dstsizeopt | CV_TUPLE | 0,0 | size 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. |
| borderTypeopt | COMBO | BORDER_DEFAULT | Pixel extrapolation method, see #BorderTypes (#BORDER_CONSTANT isn't supported) |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| result | COMFY_MATCHTYPE_V3 | Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY. |