Nodes/ComfyUI CV/cv2.normalize
ComfyUI Node

cv2.normalize

Two different nodes wearing one name

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.normalize
  • src
  • mask
  • result
◄alpha1.0000►
◄beta0.0000►
◄norm_typeNORM_L2►
◄dtypesame as input►

cv2.normalize is two operations in a trenchcoat, and which one you get is decided entirely by norm_type. Get that wrong and you'll spend twenty minutes wondering why your image looks almost the same.

The range form (NORM_MINMAX) is the one beginners want: a linear rescale so the array's minimum maps to alpha and its maximum to beta. alpha = 0, beta = 255 stretches a float score map into something displayable; alpha = 0, beta = 1 squashes any range into ComfyUI's float convention. The norm form (NORM_L1 / NORM_L2 / NORM_INF) divides the whole array by its norm and scales by alpha, so the result has norm alpha - the max value lands wherever it lands. Same node, wildly different results.

Note the default: norm_type ships as NORM_L2. People who came for a min-max stretch and left it alone get a subtly rescaled image instead. Set it explicitly.

Where it earns its place

The real job is making numbers into something a human or another node can consume. A distance transform or a Wiener filter result is a float field with arbitrary range - cv2.normalize is how you get it into 0–255 for a preview, and the pack's own Wiener-filter subgraph wires exactly that (0, 255, NORM_MINMAX). The other job is range discipline for masks. ComfyUI masks are 0–1 floats; a mask that arrives with values up to 255 is not "stronger", it's out of contract, and any consumer treating >0 as "on" will read it as a solid block. alpha = 0, beta = 1 is the fix.

alpha and beta carry OpenCV's exact meanings, and the author's tooltips say so: alpha is "the norm value to normalize to or the lower range boundary in case of the range normalization"; beta is the upper range boundary and "is not used for the norm normalization". So in the range form you set both; in the norm form beta is decoration.

Inputs, output, and the caveats

src is the single required input and decides the output's format - IMAGE in, IMAGE out; MASK in, MASK out; NPARRAY stays NPARRAY. The optional mask participates in the computation (it restricts which pixels define the range or the norm), same size as src, CV_8U/CV_8S/CV_Bool. dtype defaults to "same as input"; switch it to CV_32F when an 8-bit result would clip the stretched values.

Two honest warnings. A min-max stretch is not colour correction. It's one global linear map applied across every channel of the array, so a per-channel or perceptual stretch is not what you're getting - if the goal is "make this image look right", a gamma curve or a statistics-based colour match is the better tool, and the KB's post-processing doc makes a point of reaching for the deterministic primitive that matches the job. And a flat array has nothing to stretch: if min equals max (an all-black mask, a constant field), you're asking a range normalizer to normalize a range that doesn't exist, so don't build on the result.

One more: normalizing a constant-shaped array to a fixed norm (L2 to alpha = 1) is a genuine technique - that's how you make vectors comparable for matching without caring about their original scale. Just be sure that's what you meant.

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, a recent ComfyUI on the V3 node API. Core cv2; no contrib submodule, no models. The pack's CV Array -> Mask bridge min-max normalizes floats on the way in, so a float array and the mask socket agree by default - one less conversion to get wrong.

Categoryimage/CV/low-level/cv2 N

Inputs (6)

NameTypeDefaultDescription
srcCOMFY_MATCHTYPE_V3input array. The image output(s) echo this input's format. 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.
alphaoptFLOAT1.0000-1e+38–1e+38norm value to normalize to or the lower range boundary in case of the range normalization. Preset to the OpenCV default (1.0).
betaoptFLOAT0.0000-1e+38–1e+38upper range boundary in case of the range normalization; it is not used for the norm normalization. Preset to the OpenCV default (0.0).
norm_typeoptCOMBONORM_L2normalization type (see cv::NormTypes).
dtypeoptCOMBOsame as inputwhen negative, the output array has the same type as src; otherwise, it has the same number of channels as src and the depth =CV_MAT_DEPTH(dtype).
maskoptNPARRAY,IMAGE,MASKoptional operation mask of type CV_8U, CV_8S or CV_Bool. 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
resultCOMFY_MATCHTYPE_V3Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY.