Nodes/ComfyUI CV/cv2.accumulateWeighted
ComfyUI Node

cv2.accumulateWeighted

The running average, and the alpha=0 trap

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.accumulateWeighted
  • src
  • dst
  • mask
  • nparray
◄alpha0.0000►

dst = (1 − α)·dst + α·src is a one-line exponential moving average, and exponential moving averages are how you get a clean background plate, a temporal denoise, or a "what does this static camera usually see" reference without training anything.

cv2.accumulateWeighted is that line. It's the most practically useful node in the accumulate family in comfyui_cv, and it has two traps that make people think it's broken. Neither is exotic.

How it works

Four inputs: the incoming src, the accumulator dst, the weight alpha, and an optional mask. The output is the new accumulator as an NPARRAY.

OpenCV documents dst as a 32-bit or 64-bit float accumulator with the same channel count as the source. That's not a suggestion. Wire an IMAGE into dst and you're feeding OpenCV uint8, which is out of spec.

alpha is the weight of the new image. Small (0.01–0.05) means the accumulator barely moves - a slow, stable background that resists anything transient crossing the frame. Larger (0.2–0.5) means it chases change quickly, which is what you want for a fast-adapting reference and not what you want for background extraction, because a subject that lingers long enough becomes the background.

The wrapper hands OpenCV a private copy of dst, so nothing persists between runs, and per the pack's own batching notes each frame in a batch starts from the dst you supplied. One weighted average per execution. The stateful version of this idea, done properly, is the pack's curated CV Background Subtract (Batch) - MOG2/KNN/GMG/CNT learned over a clip.

Inputs and outputs

  • src (NPARRAY,IMAGE,MASK) - 1- or 3-channel, 8-bit or float.
  • dst (NPARRAY,IMAGE,MASK) - the float accumulator. Start from CV Constant Like (zeros) → CV Cast Array (float32), or from a previous accumulator.
  • alpha (FLOAT) - the weight of the incoming image.
  • mask (optional) - update only where it's set, which is how you keep a moving object out of your background.
  • nparray - the updated accumulator.

The two traps

alpha defaults to 0. OpenCV's C++ signature has no default for alpha; the wrapper fills in 0, which means "ignore the new image entirely". The output is your input dst, unchanged, and it looks like the node did nothing at all. Set it explicitly. This is the number-one reason people conclude accumulateWeighted doesn't work.

There's no state between runs. If you ran it once per frame and expected a rolling average, you got one average of frame n against an old accumulator. To make it roll, you have to iterate the graph - re-run with the output wired back, or use a pack with looping. For a clip in one shot, use the background-subtraction node instead.

What you wire in and what you get out

The realistic uses, in order of how often they come up:

  • Static-camera background plate. Feed a video batch through a per-frame loop with alpha ≈ 0.02 and you converge on the scene with people removed. Then cv2_absdiff against that plate and threshold - that's motion detection, assembled from three primitives.
  • Temporal denoise. A slow weighted average kills uncorrelated sensor noise and keeps the structure. alpha is the noise-vs-smear tradeoff.
  • Exposure/illumination drift tracking. Keep an accumulator of the lighting and compare the current frame to it.

View the accumulator with CV Array → Image - remember it's float and may exceed 1.0, so preview in normalize mode rather than trusting the thumbnail.

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. Python ≥ 3.12, a recent ComfyUI on the V3 node API, and behaviour pinned to OpenCV 5.0.0.93. Keep the contrib wheel: installing plain opencv-python on top silently empties the contrib submodules. Also worth knowing before you install a twelve-pack pile-up - this pack adds a hard pin on the OpenCV version, and OpenCV is exactly the dependency that gets clobbered by other packs' requirements, the perennial complaint in r/comfyui.

Where people get burned

alpha left at 0. As above. Set it.

uint8 dst. Errors or nonsense - cast to float32.

alpha outside (0, 1]. At 1 the accumulator is the current frame; above 1 it overshoots and then oscillates. The formula doesn't clamp for you.

Ghosting on a moving subject. A slow alpha is a long average: a person walking through leaves a fading trail for a while. Either speed up alpha or use the mask to exclude the region you don't want folded in.

Categoryimage/CV/low-level/cv2 A

Inputs (4)

NameTypeDefaultDescription
srcNPARRAY,IMAGE,MASKInput image as 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.
dstNPARRAY,IMAGE,MASK%Accumulator image with the same number of channels as input image, 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.
alphaFLOAT0.0000-1e+38–1e+38Weight of the input image.
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—