Nodes/ComfyUI CV/cv2.reduce
ComfyUI Node

cv2.reduce

Collapse a matrix to a row or a column (and don't overflow it)

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.reduce
  • src
  • nparray
◄dim0►
◄rtypeREDUCE_SUM►
◄dtypesame as input►

What it is

cv2.reduce takes a 2-D matrix and squashes one axis down to a single row or column: sum it, average it, take the max or min, or sum squares. It's the cv2 spelling of np.sum(arr, axis=…), with a dtype parameter that matters more than it looks.

Where you'd actually want that: turning a mask into a projection profile (how many white pixels per row → a signal of where the object is vertically), collapsing a dense optical-flow field to a per-row mean motion, or producing a 1-D signal you can plot. Output is an NPARRAY - a real array, not a picture - so it lands in the pack's data lane rather than the image lane.

Inputs

  • src - the array. IMAGE / MASK / NPARRAY all resolve here, and it's on the pack's per-frame safe list, so an IMAGE batch is looped frame by frame and re-stacked rather than truncated. Note this one has no LATENT socket (the pack only offers that for channel-agnostic ops that behave on arbitrary channel counts).
  • dim - the author's tooltip: "Axis to collapse: 0 = reduce each column to a single row, 1 = reduce each row to a single column." Leave it at 0 for a horizontal profile (height collapsed away, one number per column); set it to 1 for a vertical profile.
  • rtype - REDUCE_SUM, REDUCE_AVG, REDUCE_MAX, REDUCE_MIN, REDUCE_SUM2. Dropdown, resolved against your installed cv2's constants, so the names are always right for your build.
  • dtype (optional) - same as input by default, or an explicit CV_8U … CV_64F. The author's tooltip is the reason this parameter exists: "use a wider type, e.g. CV_32F, to avoid overflow on SUM."

Output: nparray.

The overflow trap, spelled out

An IMAGE arrives as uint8 BGR. Sum a 1080-pixel column of a near-white image and you're at ~275,000 - which wraps in uint8 and gives you a confidently wrong profile with no error message. If your reduction is anything other than MAX/MIN and your input is 8-bit, set dtype to CV_32F or CV_64F. The default same as input is correct for mean and max, and quietly wrong for sum. Two seconds of clicking versus an afternoon of "why is my profile spiky".

Second shape issue: reduce is documented against a single-channel matrix. Feed it an IMAGE and you're handing it three channels. If you want a per-channel answer you can do that and read the result as channels, but if you want one profile, pull a channel first with cv2.extractChannel (there's also a curated CV Color Range / threshold path if what you actually wanted was "where is the subject"). MASK inputs sidestep this entirely - a MASK is single-channel by construction.

Where it fits

Think of it as the bridge from 2-D data to 1-D data: reduce to get a profile, then feed that array into the pack's array nodes - CV Array Shape, CV ArrayStat, CV CVPreview/CV Plot2D if you want to see the curve rather than reason about it. It's the kind of node that shows up in the pack's own playground workflows (the stereo multiview and RAPID model-tracking examples both wire a cv2.reduce in) doing exactly this job: summarising an array into something a human can read.

One scope note so you don't reach for the wrong tool: this reduces within one frame. Reducing across frames - a background plate from a clip, a median over time - is a different node, CV Temporal Reduce (Background Plate). cv2.reduce has no idea time exists.

Install

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

Or from Manager: search "ComfyUI CV" (bmad4ever). Python ≥ 3.12, plus a ComfyUI new enough for the V3 node API - this pack's nodes are written against comfy_api.latest, and on older versions they don't register at all. Restart ComfyUI after installing.

Troubleshooting

Values look saturated or wrapped. Overflow. Widen dtype.

The output is the wrong way round. You wanted a per-row value and got per-column (or vice versa): flip dim.

The output shape surprises you. Reduction to a row gives something like (1, W); a 3-channel input keeps channels. Look at it with CV Array Shape or CV CV Inspect rather than guessing - one glance beats three hypotheses.

Node missing / an attribute error from cv2. A non-contrib OpenCV wheel installed over the contrib one this pack needs can empty the contrib submodules. reduce is core cv2 so it survives, but if a contrib node of the pack has gone missing, that's the cause and the pack's repair script fixes it:

python ComfyUI/custom_nodes/comfyui_cv/tools/repair_opencv_contrib.py --check
Categoryimage/CV/low-level/cv2 R

Inputs (4)

NameTypeDefaultDescription
srcNPARRAY,IMAGE,MASKinput 2D matrix. 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.
dimINT0-2147483648–2147483647dimension index along which the matrix is reduced. 0 means that the matrix is reduced to a single row. 1 means that the matrix is reduced to a single column.
rtypeCOMBOREDUCE_SUMreduction operation that could be one of #ReduceTypes
dtypeoptCOMBOsame as inputwhen negative, the output vector will have the same type as the input matrix, otherwise, its type will be CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels()).

Outputs (1)

NameTypeDescription
nparrayNPARRAY—