Nodes/ComfyUI CV/cv2.accumulateProduct
ComfyUI Node

cv2.accumulateProduct

The second-moment accumulator nobody explains

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.accumulateProduct
  • src1
  • src2
  • dst
  • mask
  • nparray

cv2.accumulateProduct computes dst += src1 × src2, pixel by pixel. If that reads like a solution in search of a problem, that's because it mostly is one - until you're doing statistics, where it's exactly the missing half of a correlation.

It lives in the same family as cv2_accumulate, cv2_accumulateSquare and cv2_accumulateWeighted, and the family exists for one reason: these are the accumulation primitives OpenCV's own estimators (calcCovarMatrix, the Harris/RANSAC internals, template statistics) are built from. You get them because the registry is generated from the type stubs - including the parts you don't have a use for yet.

How it works

dst += src1 * src2, with the multiplication done and the sum stored in a float accumulator. Both inputs must be the same size and type, dst must be 32-bit or 64-bit float with the same channel count, and an optional mask restricts which elements update.

The interesting property is the same one accumulate has: no saturation into 8-bit. Products of two bright uint8 pixels blow past 255 immediately - 255 × 255 = 65025 - so a float accumulator is not a nicety here, it's the only thing that works. Sum 100 frames of that and you're at six and a half million. The container holds it; your eyes won't, so inspect the numbers rather than the preview.

Like its siblings, this wrapper hands OpenCV a private copy of dst, so nothing persists between runs, and the batch path starts each frame from the dst you supplied. It is one multiply-accumulate, not a running estimator.

Inputs and outputs

  • src1, src2 (NPARRAY,IMAGE,MASK) - the pair. Same type, same size.
  • dst (NPARRAY,IMAGE,MASK) - the float accumulator you build with CV Constant Like → CV Cast Array (float32).
  • mask (optional) - update only where it's set.
  • nparray - the updated accumulator.

What it's actually for

Pair this with cv2_accumulate and you have a running cross-moment: Σxy next to Σx gives you covariance, and covariance over an image pair is how classic vision code gets orientation, anisotropic diffusion tensors and structure matrices. Pair it with cv2_accumulateSquare and you get variances.

Concretely, in ComfyUI terms:

  • Covariance between two channels or two frames - accumulate the products, then reduce with CV Array Statistic or feed the matrix into the pack's PCA/covariance nodes.
  • Averaging a product over a stack - sum A·B over N frames and divide; that's a mean product, which is the numerator of a correlation coefficient. Denoising by averaging assumes zero correlation; this is how you check whether that assumption holds.
  • Template statistics - the second moment of your template patch, computed ahead of cv2_matchTemplate, is the classic normalisation term in NCC-style matching.

If your actual goal is "multiply two images and get a picture", this is the wrong node - use cv2_multiply, which saturates and returns something displayable. accumulateProduct returns numbers, and it expects you to know why you wanted them.

Install

ComfyUI Manager → comfyui_cv (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 afterwards. Requires Python ≥ 3.12 and a recent ComfyUI built on the V3 node API; behaviour is pinned against OpenCV 5.0.0.93. Keep the contrib wheel - installing a non-contrib opencv-python over it empties the contrib submodules and hides nodes.

Where people get burned

A uint8 dst. Same trap as the rest of the family: OpenCV wants 32F/64F. Build the accumulator properly or it errors out (or does something worse).

Float64 input against a float32 accumulator. Mismatched depths raise. Get both sides consistent with CV Cast Array.

Reading the thumbnail as if it were an image. Min-max normalisation of a Σxy map shows you structure, not values. Use Inspect CV Data / CV Array Statistic when the number matters, CV Array → Image when it doesn't.

Expecting it to keep accumulating across runs. It won't. One call, one add.

And the standing caveat: these raw wrappers are auto-generated and uncurated, the OpenCV docs are the real manual, and the author explicitly warns the pack isn't production-hardened.

Categoryimage/CV/low-level/cv2 A

Inputs (4)

NameTypeDefaultDescription
src1NPARRAY,IMAGE,MASKFirst input image, 1- or 3-channel, 8-bit or 32-bit floating point. 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,MASKSecond input image of the same type and the same size 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.
dstNPARRAY,IMAGE,MASK%Accumulator image with the same number of channels as input images, 32-bit or 64-bit floating-point. The low-level cv2 function writes its result into this array in place, but this wrapper passes cv2 a private copy, so your input array is never modified. 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.
maskoptNPARRAY,IMAGE,MASKOptional operation mask. 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
nparrayNPARRAY—