cv2.detail.normalizeUsingWeightMap
The second half of the stitcher's blend
- weight
- src
- nparray
This node is one half of a two-step operation, and it's the half that makes a weighted average actually an average. The stitching pipeline accumulates each frame multiplied by its weight map, and separately accumulates the weights. cv2.detail.normalizeUsingWeightMap does the division that turns those two accumulators back into a picture - divide the weighted sum by the weight sum, and the result is a per-pixel average across every frame that contributed. Without it, your panorama comes out roughly as bright as the sum of its parts.
Inputs and output
Two inputs, NPARRAY or ComfyUI IMAGE/MASK links: weight - the accumulated weight map, which is what cv2.detail.createWeightMap produces for each frame, summed - and src, the accumulated weighted image. Note the order: weight comes first, which is cv2's own argument order and not what most people guess. The output is a single NPARRAY.
Pixels with zero total weight are the interesting edge case in any blend like this: divide by zero and you get NaN, which then propagates into everything downstream and shows up as black or white speckles in the finished panorama. The stitcher handles it by construction - you only accumulate frames inside their own valid masks - and if you build the same thing by hand, you have to handle it too.
Nothing in this node is configurable, because there's nothing to configure: it's one arithmetic step that the module needs between its blend and its output. Its tooltips in the UI are blank placeholder text, which is what the pack falls back to for functions OpenCV ships without parameter documentation - the stitching internals are largely undocumented by design.
Should you use it?
Almost never. CV Stitch and CV Stitch (Advanced) in this same pack run the whole stitching pipeline, weights and normalization included; nobody hand-assembles a blender unless they're doing research, teaching, or building a very specific multi-image composite that OpenCV's stitcher can't express (different exposures, a moving subject you're deliberately ghosting, that kind of thing).
Where it is genuinely useful is as the missing piece of a manual blend if you've decided to do that anyway. If you're compositing two or more images with feathering weights you computed yourself - with createWeightMap, or with a mask you blurred by hand - this is the normalization step, and having it as a node saves you from reimplementing the divide-by-zero handling in numpy. In the ComfyUI mask domain, most people never need more than alpha-blending nodes; this is the array-level equivalent.
One genuinely honest framing: this node exists because the pack is generated. It parses what cv2 exposes and turns it into nodes, so the stitcher's internals come along for the ride. That's a feature if you like being able to see and use the parts; it's a curiosity if you just want panoramas.
Install
Manager → Install Custom Nodes → ComfyUI CV (publisher bmad4ever), or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Restart ComfyUI. Python ≥ 3.12 and a recent V3-API ComfyUI. The contrib headless OpenCV wheel is the only dependency; no models are involved. If the whole cv2.detail.* group is absent from your menu, the pack silently skips wrappers whose function your cv2 doesn't expose - which, for the contrib-adjacent modules, usually traces back to a plain opencv-python installed over the contrib build (python tools/repair_opencv_contrib.py --check, then --apply). The pack is GPL-3.0, forked from geroldmeisinger/opencv-comfyui, written with heavy LLM involvement, and the author states it is not production-ready and won't be promptly supported.
Common issues
- The output is blank or full of NaN speckles. Zero-weight pixels being divided. Make sure your weight map is non-zero wherever the image has data - or clamp the weights, or add a tiny epsilon.
- The output is far too bright or too dark. You've normalized by the wrong axis - the divisor has to be the same weight map that multiplied the image, accumulated over the same frames.
- You can't find documentation for the parameters. There isn't any. These are stitcher internals; every function in the
detailgroup has the same problem, and the pack's placeholders admit it rather than inventing text.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| weight | NPARRAY,IMAGE,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. | |
| src | NPARRAY,IMAGE,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)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |