What a shape means
A spike in the middle is low contrast. The image is grey and flat, and detail exists but the differences are too small to see.
A wide, flat spread is high contrast, using the full range.
Two separated humps — a bimodal histogram — means the image has two distinct populations of pixel, usually an object and a background. This is the shape that makes [thresholding](thresholding.html) work, and the valley between the humps is where the threshold belongs.
A pile against the right edge is clipping: pixels that were brighter than 255 have all been recorded as 255. That detail is gone and no amount of processing brings it back, which is why photographers expose to avoid it.
How equalisation works
Histogram equalisation asks a specific question: what mapping from old values to new ones would make the histogram as flat as possible?
The answer is the cumulative distribution function. For each value *v*, compute the fraction of pixels whose value is at most *v*. That fraction is between 0 and 1; multiply by 255 and you have the new value for *v*.
cdf[v] = (number of pixels <= v) / (total pixels)
new[v] = round(cdf[v] * 255)
Why this works is worth a moment. If a value is very common, the CDF climbs steeply across it, so values on either side get mapped far apart — crowded regions are spread out. If a range of values is rare or absent, the CDF is nearly flat there, so that whole range collapses to almost a single output value. The transformation gives range to where the pixels actually are, and takes it away from where they are not.
Toggle the control above and watch both the image and the output histogram. The narrow spike is pulled apart across the full width, and detail that was present but invisible — the difference between the triangle and the background — becomes plainly visible.
What it costs
Equalisation is not free, and the costs follow directly from the mechanism.
It amplifies noise. In a region that is genuinely flat, the small random variations between neighbouring pixels are still variations, and stretching the range stretches them too. A clear sky becomes a mottled one.
It is global. One lookup table is computed from the whole image and applied everywhere. An image that is correctly exposed on the left and dark on the right gets a compromise that suits neither.
The result is not natural. Faces in particular look wrong after equalisation, because skin tones occupy a narrow band and equalisation deliberately spreads narrow bands apart.
CLAHE
The standard fix for the second and third problems is CLAHE, Contrast Limited Adaptive Histogram Equalisation. It divides the image into tiles, equalises each tile against its own histogram, and interpolates between tiles so the boundaries do not show. The dark region gets its own aggressive stretch; the well-exposed region is left more or less alone.
The "contrast limited" half addresses the noise. Before computing the CDF, any histogram bin taller than a set limit is clipped and the excess redistributed across the other bins. This caps how steeply the CDF can climb, which caps how far apart nearly-identical values can be pushed — and since noise amplification *is* pushing nearly-identical values apart, capping it directly limits the damage.
Where it goes wrong
Equalising an already well-exposed image. There is nothing to gain and noise to lose. Look at the histogram first; if it already spans the range, leave it alone.
Equalising each RGB channel separately. The three channels get three different mappings, so the colours shift. Convert to a space with a separate brightness channel, equalise that one channel, and convert back.
Comparing histograms across images to judge similarity. Two completely different photographs can share a histogram. It describes the palette, not the picture.