Nodes/ComfyUI CV/cv2.resize
ComfyUI Node

cv2.resize

Dsize, fx/fy, and the one interpolation choice that matters

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.resize
  • src
  • dsize
  • result
◄fx0.0000►
◄fy0.0000►
◄interpolationINTER_LINEAR►

Why use this instead of the core resize node

ComfyUI already has image resize and upscale nodes, and for "make this 1024 wide" they're fine. This wrapper earns its place in three situations: you want cv2's exact interpolation semantics (including the bit-exact variants), you're resizing something that isn't a ComfyUI IMAGE - an NPARRAY mask, a disparity map, a coordinate array, or a LATENT - or you're already in a cv2 pipeline and don't want to detour through tensor land and back. It's a straight wrapper over cv2.resize(src, dsize, fx, fy, interpolation), auto-generated from the type stubs, with the pack's socket conventions on top.

One note on scope, since it's a common hope: this is a resampler, not an upscaler. It has no model, no detail synthesis, no tile awareness. If you want better pixels, that's a diffusion upscaler or a dedicated SISR model - see the KB's upscaling essay for that lane. cv2.resize is for when you want the same pixels, in a different grid.

Inputs

  • src - IMAGE, MASK, NPARRAY, or LATENT. It's one of the few places in this pack that takes a LATENT directly: a latent arrives as float32 [H,W,C] with values untouched, and cv2 resamples it - a genuinely handy way to rescale a latent field without a decode/re-encode round trip. It handles arbitrary channel counts (the pack probed these socket types up to 16 channels), and it takes frame 0 of a latent batch.
  • dsize - a CV_TUPLE, (width, height), default (0, 0). Author it with CV Tuple or type the literal.
  • fx, fy - scale factors, floats, default 0. The tooltips spell out the deal: "0 (the default) derives it from dsize; to scale by ratio instead, set dsize to (0, 0) and give fx/fy." So it's an either/or - one of the two paths must be non-zero, and (0,0) with fx=0, fy=0 is a no-op-shaped error.
  • interpolation - dropdown: INTER_LINEAR (default), INTER_NEAREST, INTER_CUBIC, INTER_AREA, INTER_LANCZOS4, INTER_LINEAR_EXACT, INTER_NEAREST_EXACT.

Output: result, echoing the input's type - IMAGE in, IMAGE out, MASK in, MASK out. And it's on the pack's per-frame safe list, so an IMAGE batch is resized frame by frame and re-stacked rather than quietly truncated to frame 0. Resizing a whole clip in one node actually works here.

Picking the interpolation

This is the whole decision, and there are basically three answers:

  • Downscaling → INTER_AREA. It averages over the source footprint, which is what you want when you're throwing pixels away. INTER_LINEAR on a big downscale aliases, and you'll see it as shimmer in fine textures. The pack's own examples drop to 0.25–0.5 scale with INTER_AREA for previews and for feeding detectors.
  • Upscaling → INTER_LINEAR for speed, INTER_CUBIC or INTER_LANCZOS4 when you care about crispness at 2× or more. LANCZOS4 is the sharpest of the classical kernels and the slowest.
  • Masks, labels, or anything a network will consume → INTER_NEAREST. Never interpolate class labels or binary masks: a fractional mask value is a lie about the content, and it silently blurs your edges. The pack's ML decision-boundary example resizes to (224, 224) with INTER_NEAREST for exactly this reason.

The *_EXACT variants exist for reproducible bit-exact results across hardware; you'll know if you need them.

Two conventions to keep straight

dsize is (width, height) - the opposite of the order you might say out loud, and the same convention the rest of cv2 uses. A (512, 384) literal in the pack's pyramid-blend example is 512 wide, 384 tall.

Resizing does not move your coordinates. If you resize an image and then draw or crop using box coordinates computed at the original size, everything will be off by the scale factor. Either scale your boxes (CV Scale BBoxes exists precisely for this) or do the geometry in the resized space.

Install

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

Manager route: search "ComfyUI CV" (bmad4ever). Python ≥ 3.12 and a ComfyUI built against the V3 node API - on older ComfyUI releases nothing from this pack registers. Restart, then reload the page.

Troubleshooting

The output is the same size as the input. Both paths were zero: dsize (0,0) and fx/fy at 0. Pick one.

The output looks like a different aspect ratio. You scale by fx/fy with unequal values and then wonder why circles became ellipses. That's arithmetic, not a bug - use CV Transform or an explicit dsize if you want an aspect-preserving resize.

INTER_AREA on upscaling. It works, but it's just INTER_NEAREST in disguise at that point and looks blocky. Area is a downscale-only tool.

Missing-node reports when you load someone else's workflow. The pack's README is clear that the workflow JSONs reference other packs too (Inspire Pack, Custom-Scripts, Basic Data Handling) - those aren't in this install and Manager will ask for them separately.

Categoryimage/CV/low-level/cv2 R

Inputs (5)

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.
dsizeCV_TUPLE0,0output image size; if it equals zero (`None` in Python), it is computed as: $$\texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))}$$ Either dsize or both fx and fy must be non-zero. 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.
fxoptFLOAT0.0000-1e+38–1e+38scale factor along the horizontal axis; when it equals 0, it is computed as $$\texttt{(double)dsize.width/src.cols}$$ Preset to the OpenCV default (0.0).
fyoptFLOAT0.0000-1e+38–1e+38scale factor along the vertical axis; when it equals 0, it is computed as $$\texttt{(double)dsize.height/src.rows}$$ Preset to the OpenCV default (0.0).
interpolationoptCOMBOINTER_LINEARinterpolation method, see #InterpolationFlags

Outputs (1)

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