Histogram Equalisation From Scratch in Python

Rohit Krishna
Geek Culture
Published in
4 min readApr 11, 2023
Image by Tumisu from Pixabay

What is Histogram?

It is a way to visually represent the distribution of a dataset by dividing it into equal intervals (or “bins”) and counting the number of data points that fall into each bin. The resulting bars in the histogram display the frequency of the data points that belong to each bin.

gray scaled x-ray and it’s histogram of pixel intensities | Image by Author

Histogram/Image Equalisation

Often images may be difficult for human observer to decipher due to the picture being, for example, too dark. It has been determined that humans can distinguish between 700 and 900 shades of grey under optimal viewing conditions, Although in very dark or bright sections of a image the just noticeable difference (JND) reduces significantly. However, it is also clear that it is easier for humans to distinguish larger differences.

So if the distribution of grey-scale in an image is improved, this facilitates better understandability by human observers. One technique for improving the distribution of grey-scale in an image is histogram equalisation.

This technique attempts to distribute the greyscale of an image evenly, so that the resulting histogram is almost flat, which results in increasing the contrast of the image.

illustration of with out and with the histogram equalisation | Image by Author

So, you get the idea of what is it, now get into the implementation in python.

the steps are;

1. Find the histogram of the grayscale of the image

When equalising a colour image, we generally only equalise the luminance channel(gray scale) as otherwise the colours can become distorted. For that convert the RGB or CMY image into YUV or HSV image format.

In the YUV format Y channel is the luminance, U and V are chrominance. In HSV format V channel is the luminance others are Saturation and Hue.

image = cv2.imread("<path-to-img>")
image = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)
hist, _ = np.histogram(luminance_channel.flatten(), 256, [0, 255])

2. Calculate the cumulative density function of the histogram

The algorithm is trying to effectively spreading out the number of intensities of each pixel value in the image almost evenly without removing the information containing the luminance.

Plot of without and with the equalisation | Image by Author

Note: in the above plot of the cumulative density function is normalized between 0 and 10,000.

So, now if you ask me “ok, our goal is to try to equalize the number of pixels, but why do we have to calculate the cdf?

It is to map new intensities to the image, which results in equalising the channel.

you will get clear understanding if you check out the below plots.

with and without zoomed plot of the image’s histogram and cdf | Image by Author

As you can see there are not that much number of pixels values between 40 and 65, so if we put almost same value(the cdf in that region) in that region then the pixels of those places will become almost same(according to the cdf) which will increase the contrast.

hist, _ = np.histogram(luminance_channel.flatten(), 256, [0, 255])
cdf = hist.cumsum()

3. Normalize the cumulative sum distribution between 0 and 255

When we map the intensitie of the cdf into the image, it is obvious that in a 8 bit image the minimum pixel value that can hold is 0 and maximum is 255, but the cumulative density function will be far bigger than that, so we gotta normalize it between 0 and 255.

cdf_normalized = ((cdf - cdf.min()) * 255) / (cdf.max() - cdf.min())

4. Map the intensities of the cumulative sum into the image

# NOTE: cdf_normalized is a np.ndarray
channel_result = cdf_normalized[luminance_channel.flatten()]
channel_result = np.reshape(channel_result, luminance_channel.shape)

The complete code,

Limitations of Global Histogram Equalization

If an image contains multiple varying image brightnesses, then this method won’t work as expected, in those cases you can use Adaptive Histogram Equlization or Contrast Limited Adaptive Histogram Equlization(CLAHE).

Conclusion

I hope you now have a clear understanding of Histogram Equalization Algorithm.

When you work on real-world projects you don’t have to do all this struggle, you can use libraries such as OpenCV for your needs. In Python using OpenCV, you can perform the Histogram Equlisation as below,

import cv2
img = cv2.imread("<path-to-img>")
result = cv2.equalizeHist(img)

If this article helps you in any way, i really appreciate if you could support me through BuyMeACoffee, it really motivates me to produce amazing articles for you guys 🥰.

References

  1. https://en.wikipedia.org/wiki/Histogram_equalization
  2. https://medium.com/hackernoon/histogram-equalization-in-python-from-scratch-ebb9c8aa3f23

--

--