Nodes/ComfyUI CV/cv2.illuminationChange
ComfyUI Node

cv2.illuminationChange

Flatten a glare spot without repainting the whole frame

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.illuminationChange
  • src
  • mask
  • result
◄alpha0.2000►
◄beta0.4000►

A local exposure fixer that only touches the region you point it at. Give it an image and a mask and it flattens the shading inside that mask - kills the specular blowout on a forehead, evens the hot corner of an over-lit product shot, lifts a dark patch that the sampler left too dim - while leaving the rest of the frame bit-for-bit alone. Then you blend or regenerate from there.

This is a gradient-field edit, from OpenCV's photo module, the same family as seamlessClone and textureFlattening. The mask is not a brush stroke; it selects where the shading model is allowed to interfere. That distinction is why it looks better than simply darkening the highlight: it is re-solving for smooth illumination rather than multiplying pixel values.

Reach for it when one region of an otherwise-fine image has an illumination defect. Reach for CV Contrast (CLAHE/Equalize) when the whole frame is flat, for CV Photometric Align (Gain/Bias) when you need one image to match another's exposure, and for inpainting when the problem is content rather than lighting (post-processing.md lays out that whole deterministic-pixel layer).

How it works

cv2.illuminationChange(src, mask, alpha, beta). Inside the mask, OpenCV normalises the image gradients and then integrates them back into pixels - a Poisson-style reconstruction that keeps the region's texture and edges while dialling down the large-scale shading variation behind them. Outside the mask, nothing changes.

Two knobs, both unitless and both easy to over-apply:

  • alpha - how strongly the illumination is flattened. Default 0.2. Values run 0–2; near 0 is a no-op, high values push the region toward flat colour and start to look like a plastic patch.
  • beta - the sharpness of the transition at the mask border. Default 0.4. The tooltip notes the effect is useful for highlighting under-exposed foreground objects or reducing specular reflections, which is a decent summary of what it is for. Values are 0–2.

Both are curve-shaping parameters, so a small change does more than you expect. Start at the defaults and move one of them.

Inputs and output

  • src - 8-bit 3-channel image. The output echoes the input's type: wire an IMAGE and you get an IMAGE back, wire an NPARRAY and you keep raw data. No conversion nodes needed in either direction.
  • mask - optional. The tooltip calls it an 8-bit 1- or 3-channel image, and it is safe to leave unconnected: the pack passes None through, which OpenCV reads as "the whole image". A mask that is hard-edged works fine; a feathered one blends better.
  • alpha, beta - as above.
  • Output result - same size and type as src.

Two things the wrapper does that are worth knowing: the function is in the pack's per-frame list, so a whole IMAGE batch is processed frame by frame and restacked into a batch - you do not have to unstack it yourself. And unlike cv2.grabCut, which the pack runs in a cancellable subprocess because it is slow, this one runs inline, so a very large mask on a very large frame is work you cannot interrupt.

Downstream, the natural next steps are a mask-blur-and-composite back onto the original, or cv2.seamlessClone if you are placing this region into another image. The pack's 17_seamless_clone.json and 18_inpainting_playground.json are the workflows to open to see how the photo module's operators sit next to each other, and 10_ximgproc_edge_aware_filters.json is worth a look for the edge-preserving side of the same problem.

Install

Manager → search comfyui_cv (bmad4ever), 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 and a recent ComfyUI built on the V3 node API. One pinned dependency, no models. The pack is a fork of geroldmeisinger/opencv-comfyui, GPL-3.0, and it is honest in its README that it is not production-grade software.

When it goes wrong

  • A visible rectangle where the mask was. beta too low (sharp border) or the mask boundary cutting across a gradient. Feather the mask a few pixels and raise beta a little.
  • The region turned into flat colour and lost its texture. alpha too high. This operator normalises gradients; at the extreme it normalises away the good detail along with the bad.
  • Nothing happened. The mask was empty or nearly so - combined with alpha at the low end, you get a perfect no-op and no error. Check the mask with Preview CV Array or gate it with cv2.hasNonZero before you spend time re-tuning.
  • Feeding a grayscale or single-channel image. The tooltip says 3-channel input; this is a colour-module operation. A MASK routed in as src needs to be copied to 3 channels first (cv2.cvtColor with a gray-to-BGR code, or the pack's own conversions).
  • A soft, washed result after a batch. Remember the mask applies to every frame as-is; if your frames have the subject in different places, you need a per-frame mask rather than one static rectangle.
Categoryimage/CV/low-level/cv2 I

Inputs (4)

NameTypeDefaultDescription
srcCOMFY_MATCHTYPE_V3Input 8-bit 3-channel image. 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.
maskoptNPARRAY,IMAGE,MASKInput 8-bit 1 or 3-channel image. Optional - leave unconnected for the OpenCV default (None). 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.
alphaoptFLOAT0.2000-1e+38–1e+38Value ranges between 0-2. Preset to the OpenCV default (0.2).
betaoptFLOAT0.4000-1e+38–1e+38Value ranges between 0-2. This is useful to highlight under-exposed foreground objects or to reduce specular reflections. Preset to the OpenCV default (0.4).

Outputs (1)

NameTypeDescription
resultCOMFY_MATCHTYPE_V3Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY.