OpenCV — Histogram Equalization

HOW TO Equalize Histograms Of Images — #PyVisionSeries — Episode #04

J3
Jungletronics
5 min readOct 7, 2022

--

INDEX
01 step — Equalizing Manually
02 step — And by using the OpenCV function

What is an Image Histogram?

It is a graphical representation of the intensity distribution of an image. It quantifies the number of pixels for each intensity value considered.

01 step — Equalizing Manually

%matplotlib inlinefrom IPython.display import display, Math, Lateximport numpy as npimport matplotlib.pyplot as pltfrom PIL import Imageimg = Image.open('DATA/einstein.jpg')
plt.imshow(img)
<matplotlib.image.AxesImage at 0x1d0b37d2250>
Displaying the color image

Convert image into a numpy array, so OpenCV can work with:

img = np.asanyarray(img)img.shape(2354, 2560, 3)

Converting RGB to Gray Scale:

import cv2img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img.shape(2354, 2560)

display the image:

plt.imshow(img, cmap='gray')<matplotlib.image.AxesImage at 0x1d0b415e100>
In gray tones now we have how to work the histogram…
img.max()255img.min()0img.shape(2354, 2560)

Flatting it out:

flat = img.flatten()# 1 row 2354 x 2560 = 6.026.240
flat.shape
(6026240,)

show the histogram

plt.hist(flat, bins=50)
Note that the grayscale values ​​are badly distributed around some value…

What is Histogram Equalization?

To make it clearer, from the image above, you can see that the pixels seem clustered around the middle of the available range of intensities. What Histogram Equalization does is to stretch out this range.

# formula for creating the histogramdisplay(Math(r'P_x(j) = \sum_{i=0}^{j} P_x(i)'))
# create our own histogram functiondef get_histogram(image, bins):  # array with size of bins, set to zeros  histogram = np.zeros(bins)  # loop through pixels and sum up counts of pixels  for pixel in image:    histogram[pixel] += 1    # return our final result    return histogramhist = get_histogram(flat, 256)plt.plot(hist)[<matplotlib.lines.Line2D at 0x1d0b4e4da90>]
# create our cumulative sum functiondef cumsum(a):  a = iter(a)  b = [next(a)]  for i in a:    b.append(b[-1] + i)

return np.array(b)
# execute the fncs = cumsum(hist)# display the resultplt.plot(cs)[<matplotlib.lines.Line2D at 0x1d0b4eafb20>]
# formula to calculate cumulation sumdisplay(Math(r's_k = \sum_{j=0}^{k} {\frac{n_j}{N}}'))
# re-normalize cumsum values to be between 0-255# numerator & denomenatornj = (cs - cs.min()) * 255N = cs.max() - cs.min()# re-normalize the cdfcs = nj / Nplt.plot(cs)[<matplotlib.lines.Line2D at 0x1d0b4f0b7c0>]

Casting:

# cast it back to uint8 since we can't use floating point values in imagescs = cs.astype('uint8')plt.plot(cs)[<matplotlib.lines.Line2D at 0x1d0b5f8bd60>]

Get CDF:

# get the value from cumulative sum for every index in flat, and set that as img_newimg_new = cs[flat]# we see a much more evenly distributed histogramplt.hist(img_new, bins=50)

How does it work?

Equalization implies mapping one distribution (the given histogram) to another distribution (a wider and more uniform distribution of intensity values) so the intensity values are spread over the whole range.

# get the value from cumulative sum for every index in flat, and set that as img_newimg_new = cs[flat]# we see a much more evenly distributed histogramplt.hist(img_new, bins=50)
# put array back into original shape since we flattened itimg_new = np.reshape(img_new, img.shape)img_newarray([[233, 231, 228, ..., 216, 216, 215],
[233, 230, 228, ..., 215, 215, 214],
[233, 231, 229, ..., 213, 213, 212],
...,
[115, 107, 96, ..., 180, 187, 194],
[111, 103, 93, ..., 187, 189, 192],
[111, 103, 93, ..., 187, 189, 192]], dtype=uint8)

Check it out:

# set up side-by-side image displayfig = plt.figure()fig.set_figheight(15)fig.set_figwidth(15)fig.add_subplot(1,2,1)plt.imshow(img, cmap='gray')# display the new imagefig.add_subplot(1,2,2)plt.imshow(img_new, cmap='gray')plt.show(block=True)

Using OpenCV equalizeHist(img) Method

02 step — And by using the OpenCV function

# Reading image via OpenCV and Equalize it right away!img = cv2.imread('DATA/einstein.jpg',0)equ = cv2.equalizeHist(img)

Ready! that’s all you need to do!

fig = plt.figure()fig.set_figheight(15)fig.set_figwidth(15)fig.add_subplot(1,2,1)plt.imshow(img, cmap='gray')# display the Equalized (equ) imagefig.add_subplot(1,2,2)plt.imshow(equ, cmap='gray')plt.show(block=True)
print("That´s it! Thank you once again!\nI hope will be helpful.")That´s it! Thank you once again!
I hope will be helpful.

👉Jupiter notebook link :)

👉Github (EX_04)

Credits & References:

Jose Portilla — Python for Computer Vision with OpenCV and Deep Learning — Learn the latest techniques in computer vision with Python, OpenCV, and Deep Learning!

https://www.tutorialspoint.com/dip/histogram_equalization.htm

https://medium.com/@kyawsawhtoon/a-tutorial-to-histogram-equalization-497600f270e2

https://docs.opencv.org/3.4/d4/d1b/tutorial_histogram_equalization.html

https://docs.opencv.org/4.x/d4/d86/group__imgproc__filter.html

https://stackoverflow.com/questions/32838802/numpy-with-python-convert-3d-array-to-2d

https://techtutorialsx.com/2018/06/02/python-opencv-converting-an-image-to-gray-scale/

https://docs.opencv.org/3.4/d4/d1b/tutorial_histogram_equalization.html

https://docs.opencv.org/4.x/d5/daf/tutorial_py_histogram_equalization.html

https://stackoverflow.com/questions/61583991/opencv-python-error-unsupported-data-type-4-in-function-cvopt-avx2getmo

https://ai.stanford.edu/~syyeung/cvweb/tutorial1.html

https://medium.com/hackernoon/histogram-equalization-in-python-from-scratch-ebb9c8aa3f23

Posts Related:

00 Episode#Hi Python Computer Vision — PIL! — An Intro To Python Imaging Library #PyVisionSeries

01 Episode# Jupyter-lab — Python — OpenCV — Image Processing Exercises #PyVisionSeries

02 Episode# OpenCV — Image Basics — Create Image From Scratch #PyVisionSeries

03 Episode# OpenCV — Morphological Operations — How To Erode, Dilate, Edge Detect w/ Gradient #PyVisionSeries

04 Episode# OpenCV — Histogram Equalization — HOW TO Equalize Histograms Of Images — #PyVisionSeries

05 Episode# OpenCV — OpenCV — Resize an Image — How To Resize Without Distortion

07 Episode# YOLO — Object Detection — The state of the art in object detection Framework!

08 Episode# OpenCV — HaashCascate — Object Detection — Viola–Jones object detection framework — #PyVisionSeries

--

--

J3
Jungletronics

Hi, Guys o/ I am J3! I am just a hobby-dev, playing around with Python, Django, Ruby, Rails, Lego, Arduino, Raspy, PIC, AI… Welcome! Join us!