ComfyUI Node Runs on cloud

CLAHE

The fix for uneven lighting before you even think about thresholding

By bmad4ever·Created 3 years ago·Updated about a year ago· 64
CLAHE
  • src
  • IMAGE
clip_limit2
tile_grid_x8
tile_grid_y8

If you've ever tried to binarize a photo of a document with a lamp shining on one side of it, you already know the problem CLAHE solves. A global threshold picks one cutoff for the whole image, so the bright half reads as "white" and the shadowed half reads as "black," and your mask comes out wrong no matter what. CLAHE - Contrast Limited Adaptive Histogram Equalization - fixes contrast locally, per small tile of the image, instead of globally. It's the standard preprocessing step before thresholding or edge detection on anything photographed rather than rendered.

The name is a mouthful, but the idea is simple: divide the image into a grid of tiles, equalize the histogram of each tile so local contrast gets a boost, then blend the tile boundaries so you don't get ugly seams. The "limited" part is what keeps it sane - contrast gain is capped per tile, which stops CLAHE from amplifying noise the way plain histogram equalization does. That's the whole reason people reach for CLAHE over the equalize-everything option.

How it works here

The node wraps OpenCV's cv.createCLAHE. Mechanically it's worth knowing three things:

  • It processes the image as single-channel grayscale - that's what CLAHE operates on - and hands the result back as an IMAGE. The output is RGB (the gray values copied into all three channels), which keeps every downstream Bmad node happy.
  • clip_limit (default 2) is the contrast ceiling per tile. Raise it for a punchier result, but the noise will find you eventually.
  • tile_grid_x / tile_grid_y (default 8 each, minimum 2) set the grid density. Smaller tiles = more local adaptation; bigger tiles = closer to global equalization.

src is the only other input, and the output IMAGE is what you route onward.

Where it fits

The natural workflow: photograph or screenshot → CLAHEAdaptiveThresholding (or the pack's OtsuThreshold) → mask. CLAHE evens the lighting field so the threshold step sees a flat, high-contrast image instead of a gradient. It's also handy as a detail pass before inpainting or before feeding a low-contrast image into feature detection - same trick photo editors call "local contrast."

Install

This is part of bmad4ever/comfyui_bmad_nodes, the catch-all utility pack from bmad4ever. Install via ComfyUI Manager (search comfyui_bmad_nodes) or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_bmad_nodes
cd comfyui_bmad_nodes
pip install -r requirements.txt

Restart after. The pack's requirements.txt pins opencv-python~=4.8.1.78 plus scikit-image and gray2color, so Manager's dependency install will pull those. No models, no downloads beyond that.

Gotchas

Two things bite people. First, tile_grid_x / tile_grid_y have a minimum of 2, and OpenCV itself will throw if you go below that - the UI enforces it, but if you're building workflows programmatically, respect it. Second, remember the output is grayscale-as-RGB. If you chain this into a node that needs a real single-channel mask (some ComfyUI-native nodes expect 1-channel tensors), you may need a channel-split first. For the pack's own masking chain it's seamless, which is probably where you should stay.

CategoryBmad/CV/Thresholding

Inputs (4)

NameTypeDefaultDescription
srcIMAGE
clip_limitINT2
tile_grid_xINT8
tile_grid_yINT8

Outputs (1)

NameTypeDescription
IMAGEIMAGE