Nodes/ComfyUI CV/cv2.multiply
ComfyUI Node

cv2.multiply

The scalar multiply you'll actually reach for

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.multiply
  • src1
  • src2
  • result
◄scale1.0000►
◄dtypesame as input►

cv2.multiply is element-wise multiplication of two arrays, with an optional scale factor. Humble, and it covers three jobs you'd otherwise chain nodes for: dimming or gain-scalping an image, applying a mask as a multiplier rather than as an alpha blend, and multiplying two score/weight maps together. The KB's post-processing doc makes the general case well - brightness and contrast are curves, not model passes - and this is the raw pixel-arithmetic version of that argument.

How it behaves

The math is result = src1 * src2 * scale, cast to the output depth. Two consequences matter in practice.

First, saturation. On the default "same as input" depth with a uint8 IMAGE, 200 × 2 lands on 255, not 400. Multiplying a picture to brighten it clips highlights and flattens the top end; if you want a smooth gain, cast to CV_32F with the dtype dropdown first, or use the scale parameter as the gain and keep the data in float.

Second, the scalar trick. src2 will happily take a constant array - the pack has a scalar-array node for authoring one - and the bundled subgraphs cv2.multiply (by scalar) and the Fourier playground both do exactly this: a constant float array in src2, scale left at 1. But you can also skip the array entirely for a pure gain: a constant array of 1s times a scale of 0.3 is the same as 0.3× the image, and the second form is one fewer node. For a scalar multiple, scale is the honest knob.

Third, single-channel broadcasting. Multiply a 3-channel IMAGE by a MASK and OpenCV applies the one-channel operand across the colour channels, which is the "cut the brightness down where the mask is" idiom. That's a genuine way to darken a background behind a subject - just remember it darkens toward black multiplicatively, so a 0.5 mask halves every channel rather than fading to a blur.

Inputs and outputs

src1 decides the output's format: an IMAGE comes back an IMAGE, a MASK a MASK, an NPARRAY stays an NPARRAY. src2 accepts NPARRAY, IMAGE, MASK or LATENT and doesn't affect the echo. scale (default 1.0) multiplies the whole product. dtype defaults to "same as input" - the depth dropdown is there when you want the result in CV_32F so it stops clipping.

The LATENT support is real and worth knowing about: arithmetic ops in this pack accept a full latent batch ({samples: [B, C, H, W]}) and the whole batch flows through when both inputs have the same batch size. That's latent-space arithmetic with the values untouched - no uint8 round trip - which is the correct way to scale a sigma/latent field. Keep both sides in the same space, though: mixing a 0–255 BGR IMAGE with a float latent array is numerically fine and semantically nonsense.

Install

ComfyUI Manager → search ComfyUI CV → install → restart, or:

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

Python ≥ 3.12 and a recent ComfyUI on the V3 API. No contrib submodule needed, no models.

Where it bites

  • Black pixels stay black. Multiplicative changes can't lift a 0 - that's what cv2_add is for. Reach for cv2_addWeighted when you want a proper blend of two images; plain multiply is for gain and masking.
  • Shape mismatch. Both inputs must be the same size and type (the single-channel-operand case aside), and the batch sizes have to agree for the batched path. The error is usually a silently odd result or a cv2 assertion, not a helpful message.
  • Mixing a MASK with an IMAGE gives you a dimmed image, not a cut-out with transparency. If you want transparency, you want a 4-channel composite, not a multiply.
  • The pack's low-level nodes exist for exactly this kind of raw arithmetic, but the README is upfront that they're auto-generated and uncurated - check the result visually the first time rather than trusting the wiring.
Categoryimage/CV/low-level/cv2 M

Inputs (4)

NameTypeDefaultDescription
src1COMFY_MATCHTYPE_V3first input array. 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.
src2NPARRAY,IMAGE,MASK,LATENTsecond input array of the same size and the same type as src1. 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.
scaleoptFLOAT1.0000-1e+38–1e+38optional scale factor. Preset to the OpenCV default (1.0).
dtypeoptCOMBOsame as inputoptional depth of the output array

Outputs (1)

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