Histogram Equalize
Drag flat, hazy footage up by spreading its tones
- video
- video
The tell of cheap or overcast footage is a histogram humped in the middle - no real blacks, no real whites, everything a foggy gray. Histogram equalization is the classic fix: it stretches the tonal distribution so the dark pixels get darker and the bright ones brighter, and a washed-out frame suddenly has contrast. It's the algorithmic cousin of cranking contrast, but smarter - it doesn't just lift one end, it re-spreads the whole histogram for maximum range.
ComfyTV is jtydhr88's canvas app (~190 stages, each its own node). Histogram Equalize sits in the VideoFX color suite, and it's a good first move on any AI-generated or phone-camera clip that looks "thin." Like the other color stages it's deterministic and previews live.
How it works
Equalization rebuilds each output pixel's brightness from where it sat in the input histogram, spreading the crowded middle into the empty ends. Two controls temper the classic problem with it:
- strength (0–1, default 0.5) - how much of the equalization to apply. Full-strength equalization is aggressive and can look harsh or noisy, which is why the default is half. This is the dial you actually live on.
- clip_limit (0–0.1, default 0, "cap per-bin fraction, 0 = off") - this is the "CLAHE" trick. Instead of letting a few over-full histogram bins dominate, it caps each bin's share and redistributes the overflow, which stops equalization from exaggerating noise in large flat areas. 0 turns the cap off; a small value like 0.01–0.02 is the "controlled" setting most people end up wanting.
The short version: leave strength where you can see the result but not the artifacts, and reach for clip_limit the moment the sky or a wall starts looking splotchy.
The hidden inputs, explained once
Every ComfyTV stage carries force_run_token, project_id, and parent_output_id - all marked "Internal" in the schema and populated by the frontend's projectStore for per-node Run. There's also the optional video input and a single video output. You never set the internals by hand.
Installing it
Same pack, same steps:
cd ComfyUI/custom_nodes
git clone https://github.com/jtydhr88/ComfyTV
or ComfyUI Manager ("ComfyTV"), full backend restart, then ComfyTV → VideoFX. The one gotcha that bites people: on ComfyUI Desktop, macOS, or multiple installs, clone into the running instance by absolute path and confirm custom_nodes/ComfyTV/__init__.py exists (not nested), then fully restart. The pack declares no pip deps, but video stages lazily import PyAV - pip install av if a video node errors.
Common issues
- The frame now looks noisy, especially in flat areas - that's un-capped equalization amplifying sensor noise. Add a small
clip_limit(0.01–0.02) and dropstrength. - Skin tones go weird - equalization operates on luminance here, but pushed hard it can still blow highlights. Back
strengthdown; this node is a starting point, not the whole grade. - No visible change -
strengthis very low, or the clip already spans a full tonal range (in which case equalization has little left to do).
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| force_run_token | INT | 00–2147483647 | Internal — bumped on Run to invalidate ComfyUI's input cache. |
| project_id | STRING | Internal — populated by the projectStore on the frontend. | |
| parent_output_id | INT | 00–2147483647 | Internal — lineage parent set by spawn handlers on the frontend. |
| strength | FLOAT | 0.500–1 | — |
| clip_limit | FLOAT | 0.0000–0.1 | cap per-bin fraction, 0 = off |
| videoopt | COMFYTV_VIDEO | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video | COMFYTV_VIDEO | — |