Nodes/ComfyUI CV/cv2.pyrUp
ComfyUI Node

cv2.pyrUp

It doubles the pixels, it does not sharpen the image

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.pyrUp
  • src
  • dstsize
  • result
◄borderTypeBORDER_DEFAULT►

Half the people searching for this node want an upscaler. It isn't one. pyrUp inserts zeros between pixels and blurs the result, which is the mathematically correct inverse of a Gaussian pyramid reduce step - and it is soft, because the information that was thrown away in the reduce step isn't coming back. If your goal is "make this 1024px image 2048px and make it look good", the honest answer is a proper resampler or one of the neural upscalers that upscaling.md covers. If your goal is "rebuild a pyramid level I just modified", you're in the right place and there's no substitute.

What it's for

Pyramid reconstruction, almost exclusively. The pattern is: reduce an image a few times with cv2.pyrDown, modify one of those small levels (blend it, filter it, mask it), then climb back up with pyrUp, adding the level's detail back at each step. That's how Laplacian pyramids - and multi-band blending, and a whole family of tone-mapping and compositing techniques - work. The pack's CV Multi-Band Blend (Laplacian pyramid) subgraph is the concrete example: a three-level blend along a soft seam.

The second legitimate use is "I need this array twice as big and I'm going to blur it anyway" - an intermediate step in a processing chain, where nobody will ever look at it.

Mechanism and gotchas

Two things to keep straight:

  • Sizes double, with rounding. The output is nominally 2× the input. The optional dstsize is a CV_TUPLE - (width, height), typed in place or wired from CV Tuple - and OpenCV only accepts a value within a pixel or two of exactly double. Leave it at (0, 0) and let the function pick.
  • borderType is a dropdown, and only BORDER_DEFAULT is supported on this function. The widget offers more, the docs say one, so don't go fiddling - you'll get an OpenCV error rather than a subtly different image.

Inputs and outputs

src accepts IMAGE, MASK or NPARRAY. An IMAGE is unwrapped to uint8 BGR, frame 0 of a batch - this function is in the pack's per-frame batch set, so a batch comes back as a batch. LATENT links work too, and here's the interesting part from the node's own tooltip: a latent is processed in latent space, frame 0 becoming a float32 [H, W, C] array with values untouched. So you can double the spatial size of a latent with a blur-based resampler, which is a legitimate alternative to latent upscale-via-VAE in some pipelines.

The output result echoes the input's format: IMAGE in, IMAGE out, MASK in, MASK out, NPARRAY stays NPARRAY. Wire it into CV Array → Image if you went the latent route, or straight into the next pyramid step.

Install

Part of ComfyUI CV (bmad4ever) - a large pack: ~470 auto-generated cv2.* wrappers plus curated nodes, all built on ComfyUI's V3 node API. 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 afterwards. Python ≥ 3.12 required. No models.

Common issues

"It's blurry." Correct. Zero-stuffing plus a Gaussian is a blur; the aliasing-free part is the point. If you wanted a sharp 2×, this is the wrong node - and if you wanted invented detail, no resampler will do it either; that's the neural upscaler's job.

Mismatched sizes in a pyramid round trip. pyrDown then pyrUp is not bit-exact on odd dimensions. If you're subtracting the reconstructed image from the original to get a Laplacian band, crop to even dimensions first or your arrays won't line up and the subtraction will throw.

The node offers border types that error. Only BORDER_DEFAULT is supported; the dropdown is generic machinery shared by every wrapper in the pack.

"It changed only one frame of my clip." Shouldn't happen here - pyrUp is batch-aware. If you see it, check whether the other node in the chain (a mean-shift pass, for instance) is the one collapsing the batch.

Missing contrib nodes. As with the whole pack: a non-contrib opencv-python wheel installed over the contrib build silently removes the contrib submodules. tools/repair_opencv_contrib.py --check diagnoses it.

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 (only #BORDER_DEFAULT is 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.