Histograms and Equalisation

The histogram tells you what an image is made of. Equalisation rewrites it to use the whole range.

Overview

Counting, not looking

An image histogram is a count: for each of the 256 possible brightness values, how many pixels hold it. Nothing else. It discards position entirely — an image and the same image shuffled into random order have identical histograms.

That sounds like a weakness and is mostly a strength. Exposure, contrast and the presence of distinct regions are all properties of the *distribution* of values, not of where they sit, so the histogram is exactly the right summary for judging them. Photographers read one on the back of a camera for this reason.

Watch the two histograms under the visualisation above. The input image is deliberately low in contrast, so its histogram is a narrow spike: almost every pixel sits between roughly 100 and 160, and the ranges below and above are empty. Two hundred of the 256 available values are being wasted.

Histograms and Equalisation

This module needs JavaScript: the images are computed in the page rather than downloaded.

Worth knowing

A histogram counts how many pixels hold each brightness value. It says nothing about where they are.
A narrow histogram means low contrast: the image is using a fraction of the range available to it.
Equalisation applies the cumulative distribution as a lookup table, stretching crowded regions apart and squeezing empty ones together.
It is a global operation. CLAHE does the same thing per tile, which avoids amplifying noise in already-flat areas.

Histograms and Equalisation

What an image is made of, and how to make it use the range it has.

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.

Check yourself

0 of 3

Answer without scrolling back up.

  1. What does a histogram tell you nothing about?

  2. Which function does histogram equalisation use as its lookup table?

  3. Why does CLAHE clip the histogram before computing the CDF?

Cheat sheet

Histograms and Equalisation

An image histogram is a count: for each of the 256 possible brightness values, how many pixels hold it. Nothing else. It discards position entirely — an image and the same image shuffled into random order have identical histograms.

COMPUTER VISION · vizlearn.in/computer_vision/histograms_and_equalisation.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.