Nodes/ComfyUI CV/cv2.mulTransposed
ComfyUI Node

cv2.mulTransposed

The Gram matrix in one node

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.mulTransposed
  • src
  • nparray
◄aTafalse►
◄scale1.0000►
◄dtypesame as input►

If you ever wondered what's underneath PCA, eigenfaces, the normal equations in a least-squares fit, or a covariance matrix of keypoint coordinates, the answer is usually this: multiply a matrix by its own transpose. cv2.mulTransposed is that operation as a node, with the transpose on whichever side you want.

Concretely, with aTa false it computes src · srcᵀ; with aTa true it computes srcᵀ · src; and scale multiplies the product. Which one you want is decided by which way your data is laid out - OpenCV's own documentation spells out the convenience cases (for a set of points stored as rows, the transposed form gives you the second-moment matrix you actually want in the small dimension).

Why it's here and not in your nightly workflow

In an image-generation graph this node is upstream of nothing popular. Its natural customers are the analysis nodes: cv2_SVDecomp (eigen-decompose the result for principal directions), cv2_PCACompute, cv2_eigen, and any least-squares solve. The pack's calibration and shape-matching pipelines are where that math lives - a N×2 array of keypoints goes in, a 2×2 structure tensor comes out, and the orientation of the dominant direction comes out of the eigenvector. Feed it a stack of flattened region descriptors and it's the Gram matrix behind a covariance/PCA feature reduction, which is the honest way to shrink a feature matrix before matching.

Two details from the author's own tooltip worth knowing. It takes a single-channel matrix, and unlike gemm it can multiply not only floating-point matrices - so you can hand it 8-bit or 16-bit integer data and let the output depth do the setting. And dtype is where you set that: the dropdown offers the whole depth list, but the valid choices here are CV_32F and CV_64F. Everything else will error or surprise you.

It does not subtract the mean. mulTransposed gives you a second-moment matrix; a covariance matrix also needs the mean removed first (cv2_subtract against the mean, or let cv2_calcCovarMatrix do both). If your PCA is giving you a principal direction that looks suspiciously like the data's overall magnitude, that's this mistake.

Inputs and outputs

src is a required NPARRAY - a data array, not an image; the socket won't take an IMAGE. aTa is a boolean, not optional: true means srcᵀ·src, false means src·srcᵀ. scale defaults to 1.0. dtype defaults to "same as input" and should be CV_32F or CV_64F for floating-point work. One output, nparray, holding the resulting matrix.

Getting the matrix in is the part that needs planning, because a graph isn't a script. The pack's type-bridge nodes are the answer: Parse Matrix for a delimited blob of text, CV Points for a literal point array, CV Concat Arrays to stack vectors, CV Reshape Array (required before cv2 arithmetic on (3,) rows), and CV Array To Numbers / Inspect CV Data on the other end to see what you got. And yes, the socket technically accepts an IMAGE link as a storable matrix - but a BGR uint8 picture is a nonsense Gram matrix, so don't.

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, V3-node-API ComfyUI. Core cv2, no models, no contrib submodule.

Small print

  • Layout decides aTa. Get it backwards and you get a matrix of the wrong shape, usually without a clear error. Know whether your rows or columns are the samples.
  • Mean-centre before you call it a covariance.
  • dtype is not a free choice. CV_32F/CV_64F; the dropdown's other entries are there because the same depth enum is shared across hundreds of wrappers.
  • The auto-generated wrappers carry no curated documentation of their own - for this one, OpenCV's own docs for mulTransposed are the reference, and the README admits the generated layer is uncurated.
Categoryimage/CV/low-level/cv2 M

Inputs (4)

NameTypeDefaultDescription
srcNPARRAYinput single-channel matrix. Note that unlike gemm, the function can multiply not only floating-point matrices. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.
aTaBOOLEANfalseFlag specifying the multiplication ordering. See the description below.
scaleoptFLOAT1.0000-1e+38–1e+38Optional scale factor for the matrix product. Preset to the OpenCV default (1.0).
dtypeoptCOMBOsame as inputOptional type of the output matrix. When it is negative, the output matrix will have the same type as src . Otherwise, it will be type=CV_MAT_DEPTH(dtype) that should be either CV_32F or CV_64F .

Outputs (1)

NameTypeDescription
nparrayNPARRAY—