# Histogram Adjustments in MATLAB – Part II – Equalization

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')); img_adjusted = histeq(img);

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'); img_adjusted = adjusthisteq(img);

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'); img_adjusted = zeros(size(img),'uint8'); for ch=1:3 img_adjusted(:,:,ch) = adapthisteq(img(:,:,ch)); 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); labimg(:,:,1) = adapthisteq(labimg(:,:,1)); img_adjusted = applycform(labimg, c_lab2rgb);

If you don’t have the Image Processing Toolbox, you could try Leslie Smith’s implementation of the CLAHE algorithm: (http://www.mathworks.com/matlabcentral/fileexchange/22182-contrast-limited-adaptive-histogram-equalization-clahe).

Histogram equalization focuses on making the CDF flat so that each pixel value is equally likely to occur. The final post in this series will extend that concept to matching an image’s CDF (or histogram) to an arbitrary CDF.

*Nick Loomis writes for loomsci.wordpress.com and uses the methods from this series of posts for various projects: histogram stretching to correct the colors of underwater photos and histogram matching to replicate the effect of color filters.*

how can i do histogram equalization without using any builtin function in matlab….

Anon,

Part III actually talks about (and has sample code) for doing histogram matching — without using the image processing toolbox functions (only base Matlab functions). Histogram equalization is the same as matching, but with a linear cumulative density function of pixel values; for example, see the CDF in the first image in Part II.

NL

Hello everyone, sorry if am posting at the wrong venue.Please can any one help. I wish to perform threshold based on the thresholdValue from an histogram. I have perform the normalized gradient magnitude. Also found the histogram of it. But I wish to apply an authomatic thresholding technique based on the histogram of the normalized gradient magnitude. All edge map pixel with values greater than the threshold retains their original values, while those edge map pixels with values less than the threshold had their values set to zero.

Daniel,

If I’m understanding your problem correctly, you have an array of gradient values, and would like to set the pixels which have values less than some thresholdValue to zero. What I would do is use a logical filter to quickly select appropriate pixels. For example,

>> t = imread(‘mytestimage.png’);

>> [gx,gy] = gradient(t);

>> Gmag = sqrt(sum(gx.^2 + gy.^2, 3)); %length of the gradient vector if image has three dimensions (ie, color channels); else, sqrt(gx.^2 + gy^2) for grayscale images

>> Gmag_norm = Gmag/max(Gmag(:)); %normalized? I’m not sure what you mean by normalized gradient, I’m guessing here

>> thresholdValue = graythresh(Gmag_norm); %image processing toolbox, Otsu’s method

>> Gmag_norm( Gmag_norm<thresholdValue ) = 0;

There are, of course, alternate methods for selecting an appropriate threshold. If you have one using statistics of the image pixels or the histogram which fits your application, all the better.

Good luck,

NL

Hello nick this was really helpful. I will post my findings when I apply the idea.

kind,

Daniel