This is the second part of a three-part post on understanding and using histograms to modify the appearance of images. The first part covered introductory material on histograms and a method known as histogram stretching for improving contrast and color. This post will cover histogram equalization and an advanced technique called contrast-limited adaptive histogram equalization, both intended for increasing the contrast of an image. The final post will extend the concepts of histogram equalization to arbitrary distributions of pixel values.

Histogram Equalization
The next stop on our tour of histogram-processing techniques is histogram equalization. If you plotted the CDF of some of your image histograms, you may have noticed that the CDF does not form a straight line—meaning that the pixel values are not equally likely to occur (since the CDF is the integral of the PDF). The good news is that most natural images do not have flat CDFs. That said, some industrial applications can benefit from having a flat CDF. The process of flattening the CDF is called histogram equalization.

MATLAB’s Image Processing Toolbox includes the histeq function, which performs histogram equalization:

`img_histeq = histeq(img);`

One example:

```img = rgb2gray(imread('harborSydney.png'));

The resulting image has particularly dark islands and a bright sky, which is not visually appealing, but the detail within the buildings is improved significantly. The skyline also happens to be much easier to threshold:

`imagesc(histeq(img)>160);`

A more advanced version of histogram equalization, adaptive histogram equalization, makes the assumption that the image varies significantly over its spatial extent. The algorithm divides the image into smaller tiles, applies histogram equalization to each tile, then interpolates the results. MATLAB’s implementation, adapthisteq, includes limits on how much the contrast is allowed to be changed, called contrast-limited adaptive histogram equalization, or CLAHE for short. Again, CLAHE will modify the image in strange ways, but those may be better for certain tasks.

``` img = imread('Spores.jpg');

This test image highlights two peculiarities of CLAHE. First, sharp edges, like those around the spores, look like they are glowing. This occurs because CLAHE computes histograms over areas, and the sharp change in values from the background to the spore body affects the normalization. (The effect is related to what you would get by dividing the original image by the low-pass filtered version of the image.) Fortunately, that additional contrast near the edges can help some edge detection algorithms, even if the glow is not natural. The second effect from CLAHE is seen in the background areas, where some out-of-focus spores becomes visible and the overall noise increases. This is exactly what CLAHE is supposed to do: increase the contrast, even in the background areas. It is also limiting the amount of contrast adjustment; to see this in a dramatic way, try using histeq on the spores image and compare that against the adapthisteq result. (Hint: if you wanted to remove the out-of-focus spores but still increase the overall contrast, look at combining adapthisteq with bilateral filtering.)
MATLAB’s histeq and adapthisteq both assume a single-channel image. Similar to the discussion about multi-channel images in the first post, you could apply the histogram equalization to each channel:

``` img = imread('harborSydney.png');
for ch=1:3
end```

Or, apply the equalization to the L* component of a L*a*b*-transformed image:

```img = imread('harborSydney.png');
c_rgb2lab = makecform('srgb2lab');
c_lab2rgb = makecform('lab2srgb');
labimg = applycform(img, c_rgb2lab);