Nodes/ComfyUI CV/cv2.scaleAdd
ComfyUI Node

cv2.scaleAdd

Alpha×A + B, and Why the Default alpha of 0 Looks Broken

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.scaleAdd
  • src1
  • src2
  • result
◄alpha0.0000►

cv2.scaleAdd does one line of arithmetic: dst = alpha*src1 + src2. That's it. No model, no kernel, no magic - just the two-term linear combine that shows up constantly once you stop thinking only in terms of generation and start matching plates, subtracting backgrounds, or building a frame from parts.

You'd reach for it when only one of the two inputs needs a coefficient: subtract a dark frame scaled by some factor, add a dimmed copy of a previous frame for an echo/ghost trail, tint one layer of a composite before summing, add a flat offset derived from a measured level. Its sibling cv2.addWeighted gives you two free weights and is the better tool for a crossfade; scaleAdd is the case where one side is plain.

Inputs and outputs that matter

Three inputs, and the batch handling is the reason this node is nicer than a generic math node:

  • src1 - the primary input, and the one that determines the output's type. IMAGE in, IMAGE out; MASK in, MASK out; NPARRAY in, NPARRAY out. It's a MatchType socket, like core's Resize.
  • alpha - the scale factor on src1. It defaults to 0. A brand-new node therefore returns src2 untouched and looks like it's doing nothing at all. Set this first, before you go hunting for the bug.
  • src2 - the second array, same size and type as src1.

Both image inputs accept a full IMAGE or MASK batch, and when both sides carry the same batch size the whole batch is processed together rather than silently collapsing to frame 0 - which is how you want a per-frame exposure match or a video-scale accumulation to behave.

One output: result, echoing src1's format. No bridge nodes, no manual CV Array → Image conversion - that's the convenience of these type-preserving wrappers.

How it works, and the one real trap

Underneath it's OpenCV element-wise arithmetic with saturate-cast into the output type. If your inputs are uint8 - which is what an IMAGE link resolves to when it enters the low-level nodes - then the result is clipped to 0..255 and the fraction gets rounded away. Multiply by 0.5 and you lose low-order detail; multiply by 2 and everything bright blows out to white. Negative values clamp to 0 rather than wrapping, which is at least predictable.

So the trap is the boring one: decide what headroom you need before this node, not after. If the arithmetic must stay signed or fractional, work in float space - send the images through Image → CV Array with float32 (0-1) and do the combine there, or cast an existing array with CV Cast Array.

The second, smaller trap is alpha's default again: 0 is a legitimate OpenCV default for a general linear-combination function, but in node form it reads as "this node is broken." It isn't. Type a number.

Install

Manager → search ComfyUI CV, or from a shell:

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

Restart ComfyUI afterwards. This pack needs Python ≥ 3.12 and a ComfyUI recent enough to ship the V3 node API - an older install will fail to register the nodes rather than degrade gracefully.

Where people get burned

The shared site-packages/cv2. opencv-python, opencv-python-headless and their contrib counterparts all install into the same place. Put a non-contrib wheel on top of the contrib one and the shared binary quietly becomes core-only; contrib-backed nodes then vanish from the node menu with no error message in the log. tools/repair_opencv_contrib.py --check diagnoses it, --apply repairs it. This is the single most common way to break the pack.

Mismatched batch sizes. The full-batch path only engages when both inputs have the same batch size; otherwise you fall back to single-frame behaviour and get one output frame where you expected twelve. Check your batches before you blame the math.

Assuming it's a blend mode. alpha*src1 + src2 has no alpha channel semantics and no mask. If you want "blend these two with a mask," that's a masked composite, not arithmetic.

Categoryimage/CV/low-level/cv2 S

Inputs (3)

NameTypeDefaultDescription
src1COMFY_MATCHTYPE_V3first input array. The image output(s) echo this input's format. 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.
alphaFLOAT0.0000-1e+38–1e+38scale factor for the first array.
src2NPARRAY,IMAGE,MASKsecond input array of the same size and type as src1. 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.

Outputs (1)

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