Tag Archives: histogram equalization

Adaptive Histogram Equalization (AHE)

In the previous blog, we discussed Histogram Equalization which considers the global contrast of an image. This means that the same transformation function is used to transform all the image pixels. This approach works well for most cases but when the image contains regions that are significantly lighter or darker than most of the image, the contrast in those regions will not be sufficiently enhanced. See the face of the statue in the image below

And sometimes we want to enhance details over small areas in an image rather than the whole image. This problem can be solved if we use a transformation function that is derived from the neighborhood of every pixel in the image. This is what Adaptive Histogram Equalization (AHE) do.

In Adaptive Histogram Equalization (AHE), the image is divided into small blocks called “tiles” (e.g. 64 tiles (8×8) is a common choice). Then each of these blocks is histogram equalized as we did earlier. Finally, we stitch these blocks together using bilinear interpolation.

But this method has a problem. If the pixel values are more or less constant in a block with some noise then the AHE tends to over-amplify the noise. To avoid this, contrast limiting is applied and the method is known as Contrast Limited Adaptive Histogram Equalization (CLAHE).

In CLAHE, we clip the histogram at a predefined value before computing the CDF and are distributed uniformly to other bins before applying histogram equalization as shown in the figure below.

Source: Wikipedia

Since the transformation function used in the Histogram Equalization is proportional to the CDF so clipping results in limiting the slope of the CDF and therefore of the transformation function. This way it prevents the noise from being overamplified.

Since for each pixel we are calculating the transformation function from its neighborhood, this is a computationally expensive process. To overcome this, we only compute the transformation function for each block’s center pixel and all the remaining pixels are transformed wrt. these center pixels using interpolation (bilinear or linear depending on the pixel location).

Another good approach is using Sliding Window Adaptive Histogram Equalization (SWAHE) where we slide the window one pixel at a time and incrementally update the histogram for each pixel.

So, let’s summarise the algorithm for CLAHE

CLAHE Algorithm

  • Divide the image into blocks or tiles (8×8 is common)
  • Plot the histogram and check whether to clip or not.
  • CDF and transformation function is then computed for each of the blocks. This transformation function is only appropriate for the block’s center pixel.
  • All the remaining pixels are transformed wrt. these center pixels using interpolation.

I hope you understood Adaptive Histogram Equalization and its variants. Now let’s see how to do this using OpenCV-Python

Code:

The output looks like this

Compare the CLAHE output image with the Histogram Equalized image and see the difference.

Note: To apply CLAHE on color(RGB) images, first, convert them into colorspaces where you have separate color and greyscale components like HSV or LAB and then apply CLAHE on the greyscale component like L or V. After that again convert it into RGB.

I hope this information will help you. Hope you enjoy reading.

If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.

Histogram Matching (Specification)

In the previous blog, we discussed Histogram Equalization that tries to produce an output image that has a uniform histogram. This approach is good but for some cases, this does not work well. One such case is when we have skewed image histogram i.e. large concentration of pixels at either end of greyscale.

One reasonable approach is to manually specify the transformation function that preserves the general shape of the original histogram but has a smoother transition of intensity levels in the skewed areas.

So, in this blog, we will learn how to transform an image so that its histogram matches a specified histogram. Also known as histogram matching or histogram Specification.

Histogram Equalization is a special case of histogram matching where the specified histogram is uniformly distributed.

First let’s understand the main idea behind histogram matching.

We will first equalize both original and specified histogram using the Histogram Equalization method. As we know that the transformation function is invertible, so by inverting we can get the mapping from original to specified histogram. The whole operation is shown in the below image

For example, suppose the pixel value 10 in the original image gets mapped to 20 in the equalized image. Then we will see what value in Specified image gets mapped to 20 in the equalized image and let’s say that this value is 28. So, we can say that 10 in the original image gets mapped to 28 in the specified image.

Most of you might be thinking why both original and specified histogram on equalization converges to same uniform histogram.

This is true only if we assume continuous intensity values. But in reality, the intensity values are discrete thus both original and specified histograms may not map to the same histogram on equalization. That’s why Histogram matching is not able to perfectly match the specified histogram.

Let’s take an example where we want to match the original image with the specified image, both histograms are shown below.

Here, I am taking the original image from the histogram equalization blog. All the steps of equalization are explained in this blog. Here, I will only show the final table

Original Image Histogram Equalization

Specified Image Histogram Equalization

After equalizing both the images, we need to perform a mapping from original to equalized to the specified image. For that, we need only the round columns of the original and specified image as shown below.

Pick one by one the values from the round column of the original image, find it in the round column of the specified image and note down the index. For example for 3 in the round original, we have 3 in the round specified column (with index 1) so we map it to 1.

If the value doesn’t exist then find the index of its nearest one. For example for 0 in round original, 1 is the nearest in round specified column (with index 0) so we map it to 0.

If multiple nearest values exist then pick the one which is greater than the value. For example for 2 in the round original, there are 2 closest values in round specified i.e. 1 and 3 so we pick 3 (with index 1) so we map it to 1.

After obtaining the Map column, replace the values in the original image with the map values. This is the final result.

The matched histogram(shown on left) approximately matches with the specified histogram(shown on right) as shown below

Now, let’s see how to perform Histogram matching using OpenCV-Python

Code

Note: Specified image can have different dimensions as compared to the original image.

The output looks like this

Hope you enjoy reading.

If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.

Histogram Equalization

In the previous blog, we discussed contrast stretching, a linear contrast enhancement method. In this blog, we will learn Histogram Equalization which automatically increase the dynamic range based on the information available in the histogram of the input image.

Histogram Equalization, as the name suggests, stretches the histogram to fill the dynamic range and at the same time tries to keep the histogram uniform as shown below

Source: Wikipedia

By doing this, the resultant image will have an appearance of high contrast and exhibits a large variety of grey tones.

Mostly we will not be able to perfectly equalize the histogram. This is only possible if we assume continuous intensity values.. But in reality, intensity values are discrete thus perfectly flat histograms are rare in practical applications of the histogram equalization.

The transformation function used in this is

where ‘s’ and ‘r’ are the output and input pixel intensities respectively. ‘L’ is the maximum intensity value(for n bit image L = 2n). The probability of occurrence of the intensity level rj in the image is approximated by

Here, MN is the total number of pixels in the image and nj is the number of pixels that have intensity rj.

Now, let’s take an example to understand how to perform Histogram Equalisation using the above equations.

Suppose we have a 3-bit, 8×8 image whose pixel count and corresponding histogram is shown below

Now, using the above transformation function we calculate the equalized intensity values. For instance

Doing this for all values we get

Because the pixel values can only be integers so we round the last column(sk) to the nearest integer as shown below

So, the round column is the output pixel intensity. The last step is to replace the pixel values in the original image( rk column) with the round column values. For example, replace 0 with 0, 1 with 1, 2 with 1 and so on. This results in the histogram equalized image.

To plot the histogram, count the total pixels belonging to the rounded intensity values(See Round and nk column). For example, 2 pixels belonging to 0, 8 pixels for 1, 6 pixels for 2 and so on.

The initial and equalized histogram is shown below

Sometimes rounding to nearest integer yield non-zero minimum value. If we want the output to range from say [0,255] for 8-bit, then we need to apply stretching (as we did in Min-Max stretching) after rounding.

Histogram Equalization often produces unrealistic effects in photographs and reduce color depth(no. of unique grey levels) as shown in the example above(See pixel value 5). It works best when applied to images with much higher color depth.

Let’s see OpenCV function for Histogram Equalization

Its input is grayscale image and output is our histogram equalized image.

Hope you enjoy reading.

If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.