Nodes/ComfyUI CV/CV Contrast (CLAHE/Equalize)
ComfyUI Node

CV Contrast (CLAHE/Equalize)

The contrast fix that doesn't hallucinate

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
CV Contrast (CLAHE/Equalize)
  • image
  • IMAGE
◄methodCLAHE (adaptive)►
◄channelsluminance only (LAB)►
◄clip_limit2.0►
◄tile_size8►

What it's for

Most "make this look better" moves in ComfyUI cost you a diffusion pass: a new seed, a new face, a new lottery. Contrast is not that problem. A flat, muddy, low-dynamic-range image has a tonal defect, and tonal defects have had deterministic answers for thirty years. That's the whole argument of the KB's post-processing notes - reach for the lookup table, not the sampler - and CV Contrast (CLAHE/Equalize) is the OpenCV half of that argument.

Where it actually earns its place: dark phone photos, old scans, microscope and x-ray-ish footage, screenshots of washed-out video, and anything you're about to feed into a detector (the pack's own feature-detection nodes carry a CLAHE toggle for exactly that reason). If the info is in the pixels and just sits in a narrow band, this pulls it out in milliseconds.

How it works

Two different algorithms behind one dropdown.

Histogram equalization (cv2.equalizeHist) is the blunt one. It builds the histogram of the whole frame and remaps grey levels so each band gets roughly equal population. Contrast jumps. So does noise in the flat areas, because a band with almost no pixels in it gets stretched as hard as the band with all of them inside it.

CLAHE - Contrast Limited Adaptive Histogram Equalization - is the version people mean when they recommend CLAHE: the frame is cut into a grid of tiles, each tile is equalized on its own (so a dark corner is stretched locally, not by the global average), and before redistribution the tile histogram is clipped at clip_limit, with the trimmed count spread evenly. Tiles are blended so you don't get a checkerboard. Local detail comes back without the global noise blowout.

The inputs that matter

  • image - an IMAGE, processed frame by frame on a batch.
  • method - CLAHE (adaptive) or histogram equalization. Default CLAHE, and you should leave it there unless you specifically want the vintage "everything is grey mush except the midtones" look.
  • channels - luminance only (LAB) (default) or each RGB channel. Luminance-only converts to LAB, equalizes L, converts back, so colour stays put. Per-channel runs the transform on R, G and B separately: more dramatic, and it will shift colour, sometimes a lot.
  • clip_limit (0.1–40, default 2) and tile_size (1–64, default 8) - CLAHE only. Higher clip limit = stronger effect, and past about 4 you're amplifying sensor noise on purpose. Smaller tiles = more local, with a visible grid if you go too small; the classic default is 8×8.

Output is a single IMAGE, same shape, batch preserved. Wire it into a save, a detailer, or straight into a detector.

Install

ComfyUI Manager, search ComfyUI CV. By hand:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv

Then restart. The pack needs Python ≥ 3.12 and a recent ComfyUI built on the V3 node API, plus a contrib OpenCV wheel:

pip install "opencv-contrib-python-headless~=5.0.0.93"

Where people get burned

The numbers still look live in equalize mode. clip_limit and tile_size only exist for CLAHE - flip method to histogram equalization and they stay on the node doing nothing. Turning them doesn't help; that's not a bug you can work around, it's two different algorithms sharing a widget row.

"It's grainy now." You asked for per-channel equalization on a noisy image. Go back to CLAHE + luminance only (LAB), drop clip_limit to 1.5, raise tile_size. If the frames still look like sandpaper, the input was underexposed rather than low-contrast and no histogram trick will fix it.

Per-channel is a colour shift, not a correction. Running the transform per channel desaturates some hues and saturates others. It's a real look, but it isn't colour management, and if you're trying to make a shot match something you want CV Create CCM Model instead.

Already-bright inputs go to white. Equalization on a well-exposed image flattens it and blows the highlights. Only push images that are actually compressed into a narrow band.

One last thing worth knowing about this pack: the author says it was written with heavy LLM assistance and warns against production use without reviewing the code yourself. For a node that calls createCLAHE and equalizeHist, that warning costs you nothing - the algorithm is visible in three lines.

Categoryimage/CV

Inputs (5)

NameTypeDefaultDescription
imageIMAGEInput image. A batch is processed frame by frame.
methodCOMBOCLAHE (adaptive)CLAHE equalizes contrast locally and limits noise amplification (recommended); histogram equalization stretches contrast globally (simpler, can blow out).
channelsCOMBOluminance only (LAB)Luminance-only keeps colors natural; per-channel can shift colors but is more dramatic.
clip_limitFLOAT2.00.1–40CLAHE only: contrast limiting; higher = stronger.
tile_sizeINT81–64CLAHE only: grid size of local regions.

Outputs (1)

NameTypeDescription
IMAGEIMAGE—