cv2.illuminationChange
Flatten a glare spot without repainting the whole frame
- src
- mask
- result
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 passesNonethrough, 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 assrc.
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.
betatoo low (sharp border) or the mask boundary cutting across a gradient. Feather the mask a few pixels and raisebetaa little. - The region turned into flat colour and lost its texture.
alphatoo 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
alphaat the low end, you get a perfect no-op and no error. Check the mask withPreview CV Arrayor gate it withcv2.hasNonZerobefore 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
srcneeds to be copied to 3 channels first (cv2.cvtColorwith 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.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| src | COMFY_MATCHTYPE_V3 | Input 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. | |
| maskopt | NPARRAY,IMAGE,MASK | Input 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. | |
| alphaopt | FLOAT | 0.2000-1e+38–1e+38 | Value ranges between 0-2. Preset to the OpenCV default (0.2). |
| betaopt | FLOAT | 0.4000-1e+38–1e+38 | Value 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)
| Name | Type | Description |
|---|---|---|
| result | COMFY_MATCHTYPE_V3 | Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY. |