Nodes/ComfyUI CV/cv2.gemm
ComfyUI Node

cv2.gemm

Actual matrix multiplication inside a ComfyUI graph

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.gemm
  • src1
  • src2
  • src3
  • nparray
◄alpha0.0000►
◄beta0.0000►
◄flagsnone (0)►

cv2.gemm is the general matrix multiply: alpha * src1 @ src2 + beta * src3. Wired up in ComfyUI it's the node that lets a graph do linear algebra - compose a chain of camera transforms into one matrix, build a weighted sum of two systems, check that a decomposition you just ran actually reconstructs what you started with. There is no prompt, no pixel, no model. It's numpy in a trench coat, and ComfyUI has surprisingly little of that.

It's a data node, not an image node

This is worth stating before anything else, because the sockets are unforgiving: src1, src2 and src3 are NPARRAY only. No IMAGE, no MASK, no LATENT - the tooltips say "a data array (points / matrix), NOT an image". If you have pictures and want them multiplied you're in the wrong node; the pack's own CV MatMul (left @ right) is the friendlier curated wrapper for a plain product.

Everything this node touches comes pre-shaped from elsewhere in the pack's geometry and calibration families: CV Parse Matrix, CV Pose to Matrix, the various estimateAffine* nodes and getDerivKernels all emit NPARRAY matrices. This is where you combine them.

The inputs

  • src1, src2, src3, alpha, beta are all required, and src3 being required is a mild annoyance: if you only want src1 @ src2, feed it anything of the right type and set beta to 0.
  • alpha - weight of the matrix product.
  • beta - weight of src3.
  • flags - a dropdown with one toggle per transpose flag: GEMM_1_T, GEMM_2_T, GEMM_3_T, pipe-joined in the string (none (0) | GEMM_2_T). Transposing src1 is how you compute AᵀA or Aᵀb without a separate transpose node, which is the shape most least-squares work ends up in. The UI renders these as checkboxes; the underlying value stays a string, so it survives in saved workflows and API calls either way.

One output, nparray - the product, same type as the inputs.

Watch the defaults

The widgets open at alpha = 0 and beta = 0. Neither is what you want. Multiply anything by zero and you get a matrix of zeros that travels happily downstream to something that then produces zeros, or a black image, or a pose of nothing - no error, no warning. Set alpha to 1.

The type rule is cv2's: both inputs must share a type, real (CV_32FC1, CV_64FC1) or complex (CV_32FC2, CV_64FC2), and src3 must match. A float32 against a float64 will raise at execution, not at wiring time.

If you need the flags but not the multiply, the pack ships CV GEMM Flags as a standalone authoring node for exactly that string.

Install

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, recent ComfyUI on the V3 node API. This is a plain core-cv2 wrapper with no models and no extra dependencies.

Where people get burned

  • The zeros-from-zero-alpha thing above. It's the single most common result of wiring this node.
  • Shape mismatch: gemm doesn't broadcast. (3,4) @ (3,4) is an error, (3,4) @ (4,3) is a 3×3. If you're used to numpy's convenience this will feel strict, because it is.
  • These constant-node results cache. An NPARRAY computed from fixed inputs is computed once and then reused across runs - that's ComfyUI's graph caching doing its job, and a node that never declares itself changed will keep serving the old value. If you changed a widget and nothing moved, check you actually changed an upstream value rather than just pressing Run again.
  • To see what came out, wire it to Inspect CV Data (prints shape/dtype/values) or Preview CV Array - a matrix is not a picture, and dropping it on a preview node generally shows you a useless normalised thumbnail.
Categoryimage/CV/low-level/cv2 G

Inputs (6)

NameTypeDefaultDescription
src1NPARRAYfirst multiplied input matrix that could be real(CV_32FC1, CV_64FC1) or complex(CV_32FC2, CV_64FC2). A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.
src2NPARRAYsecond multiplied input matrix of the same type as src1. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.
alphaFLOAT0.0000-1e+38–1e+38weight of the matrix product.
src3NPARRAYthird optional delta matrix added to the matrix product; it should have the same type as src1 and src2. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.
betaFLOAT0.0000-1e+38–1e+38weight of src3.
flagsoptSTRINGnone (0)operation flags (cv::GemmFlags) cv2.gemm flags: one of none (0) plus any of GEMM_1_T, GEMM_2_T, GEMM_3_T, pipe-joined (e.g. "none (0) | GEMM_1_T"). In the UI this renders as a dropdown with one toggle per flag.

Outputs (1)

NameTypeDescription
nparrayNPARRAY—