OpenCV: Image Histogram Calculations (2024)

Sasani Perera

·

Follow

7 min read

·

Jul 14, 2023

OpenCV: Image Histogram Calculations (2)

Image histograms provide valuable insights into the distribution of pixel intensities in an image. By understanding the histogram, you can gain information about the image’s contrast, brightness, and overall tonal distribution. This knowledge can be useful for tasks like image enhancement, image segmentation, and feature extraction.

This article aims to provide a clear and comprehensive guide to learning how to perform image histogram calculations using OpenCV. By understanding and applying histogram analysis techniques, you are enabled to enhance image quality, perform thresholding operations, analyze colour compositions, extract useful features, and visualize and understand images more effectively.

Every image is composed of individual pixels, which are like tiny dots on a grid. Let’s say we have an image with a size of 250 columns and 100 rows, totalling 2500 pixels. Each of these pixels can have a different colour value, represented by a number ranging from 0 to 255 (for a greyscale image as we discussed in the earlier article).

To visualize the distribution of colour values within the image, we can create a histogram. This histogram acts as a set of bar graphs that displays the number of pixels having the same colour value. By comparing the heights of the bars, we can easily identify which colour values are more prominent or occur more frequently in the image. This graphical representation provides valuable insights into the overall colour composition and distribution of an image.

OpenCV: Image Histogram Calculations (3)

Now remember, pixel intensity
0 → Black
255 → White

So the image must contain more Black pixels if our histogram is shifted to the left (left-skewed) and the image must contain more White pixels if our histogram is shifted to the right (right-skewed).

OpenCV: Image Histogram Calculations (4)

So I am sure that you thoroughly understand that,
More black → darker image
More white → brighter image

OpenCV: Image Histogram Calculations (5)

Now let us do the Histogram Calculation in OpenCV.

First, we’ll load the image and visualize it.

#import necessary libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt

#using opencv to read an image
#BGR Image
image = cv2.imread("C:/users/public/pictures/nature.jpg")

#visualizing
cv2.namedWindow("BGR Image", cv2.WINDOW_NORMAL);
cv2.imshow("BGR Image",image);

cv2.waitKey(0) & 0xFF
cv2.destroyAllWindows()

OpenCV: Image Histogram Calculations (6)

Before we plot the histogram, we can separate the colour channels in this image.

B = image[:,:,0] #blue layer
G = image[:,:,1] #green layer
R = image[:,:,2] #red layer

Now we calculate and find the histograms for each layer using OpenCV function cv.calcHist() and plot those histograms, using OpenCV and Matplotlib functions

cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])

● images: it is the source image of type uint8 or float32. it should be given in square brackets, ie, “[img]”.

● channels: it is also given in square brackets. It is the index of the channel for which we calculate the histogram. For example, if the input is a grayscale image, its value is [0]. For colour images, you can pass [0], [1] or [2] to calculate histograms of blue, green or red channels respectively.

● mask: mask image. To find the histogram of the full image, it is given as “None”. But if you want to find a histogram of a particular region of the image, you have to create a mask image for that and give it as a mask.

● histSize: this represents our BIN count. Need to be given in square brackets. For full scale, we pass [256].

● ranges: this is our RANGE. Normally, it is [0,256].

B_histo = cv2.calcHist([image],[0], None, [256], [0,256])
G_histo = cv2.calcHist([image],[1], None, [256], [0,256])
R_histo = cv2.calcHist([image],[2], None, [256], [0,256])

Now we plot these in subplots using matplotlib.

OpenCV: Image Histogram Calculations (7)

You may try this on images of different settings.

OpenCV: Image Histogram Calculations (8)
OpenCV: Image Histogram Calculations (9)

COMPLETE CODE

#import necessary libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt

#using opencv to read an image
#BGR Image
image = cv2.imread("C:/users/public/pictures/nature.jpg")

#seperating colour channels
B = image[:,:,0] #blue layer
G = image[:,:,1] #green layer
R = image[:,:,2] #red layer

#calculating histograms for each channel
B_histo = cv2.calcHist([image],[0], None, [256], [0,256])
G_histo = cv2.calcHist([image],[1], None, [256], [0,256])
R_histo = cv2.calcHist([image],[2], None, [256], [0,256])

#visualizing histograms
plt.subplot(2, 2, 1)
plt.plot(B_histo, 'b')
plt.subplot(2, 2, 2)
plt.plot(G_histo, 'g')
plt.subplot(2, 2, 3)
plt.plot(R_histo, 'r')

#visualizing image
cv2.namedWindow("BGR Image", cv2.WINDOW_NORMAL);
cv2.imshow("BGR Image",image);
cv2.waitKey(0) & 0xFF
cv2.destroyAllWindows()

Then we can extend this idea to identify overexposed (too bright) images and underexposed (too dark) images.

OpenCV: Image Histogram Calculations (10)

Let us see the histograms of these images.

OpenCV: Image Histogram Calculations (11)

Clearly, one histogram is left-skewed which the image is underexposed and another histogram is right-skewed which the image is overexposed.

Here, we can clearly understand if an image is underexposed or overexposed just by looking at its histograms.

Consider an underexposed or overexposed image whose pixel values are confined to some specific range of values only.
For eg: the brighter image will have all pixels confined to high values.

But a good image will have pixels from all regions of the image. So you need to stretch this histogram to either end. This normally improves the contrast of the image.

When performing histogram equalization on colour images we usually apply the process separately to the Red, Green, and Blue components of the RGB colour values in the image.

First, we read the image and split the image into three colour layers.

import cv2
import numpy as np
import matplotlib.pyplot as plt

#using opencv to read an image
#BGR Image
image = cv2.imread("C:/users/public/pictures/underexposed_image.jpg")

#seperating colour channels
B = image[:,:,0] #blue layer
G = image[:,:,1] #green layer
R = image[:,:,2] #red layer

Then we use cv.equalizeHist() to equalize each of the colour layers’ histograms. Visualize them using Matplotlib and OpenCV.

b_equi = cv2.equalizeHist(B)
g_equi = cv2.equalizeHist(G)
r_equi = cv2.equalizeHist(R)

plt.imshow(b_equi)
plt.title("b_equi")
plt.show()
plt.imshow(g_equi)
plt.title("g_equi")
plt.show()
plt.imshow(r_equi)
plt.title("r_equi")
plt.show()

OpenCV: Image Histogram Calculations (12)

With the equalized colour layers’ we calculate each colour’s histogram using cv.calcHist(). And then plot them all.

B_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256]) 
G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])
R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])

plt.subplot(2, 2, 1)
plt.plot(G_histo, 'g')
plt.subplot(2, 2, 2)
plt.plot(R_histo, 'r')
plt.subplot(2, 2, 3)
plt.plot(B_histo, 'b')

You must have noticed that we have used only [0]s in the ‘channels’ place. In the previous case, we used all [0], [1] and [2]. This is due to, the availability of split channels. Therefore there’s only 1 channel. Hence for all histograms, ‘channels’ is [0]

Optionally, you can get the histograms of each channel in the original image and plot them with the equalized colour layers.

#calculate histograms for each channel seperately
#Equilized channels
B_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256])
G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])
R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])
#Original channels
BO_histo = cv2.calcHist([image],[0], None, [256], [0,256])
GO_histo = cv2.calcHist([image],[1], None, [256], [0,256])
RO_histo = cv2.calcHist([image],[2], None, [256], [0,256])

#visualize the channel histograms seperately
plt.figure(figsize=(10,12), )

plt.subplot(3, 2, 1)
plt.title("Green Original")
plt.plot(GO_histo, 'g')

plt.subplot(3, 2, 2)
plt.title("Green Equilized")
plt.plot(G_histo, 'g')

plt.subplot(3, 2, 3)
plt.title("Red Original")
plt.plot(RO_histo, 'r')

plt.subplot(3, 2, 4)
plt.title("Red Equilized")
plt.plot(R_histo, 'r')

plt.subplot(3, 2, 5)
plt.title("Blue Original")
plt.plot(BO_histo, 'b')

plt.subplot(3, 2, 6)
plt.title("Blue Equilized")
plt.plot(B_histo, 'b')

OpenCV: Image Histogram Calculations (13)

Moving on to the next step, what we have now are only layers. To get an image out of these, we need to merge these.

equi_im = cv2.merge([b_equi,g_equi,r_equi])

Now let us see the equalized image and the original image side by side.

cv2.namedWindow("Original Image", cv2.WINDOW_NORMAL);
cv2.imshow("Original Image",image);
cv2.namedWindow("New Image", cv2.WINDOW_NORMAL);
cv2.imshow("New Image",equi_im);

cv2.waitKey(0) & 0xFF
cv2.destroyAllWindows()

OpenCV: Image Histogram Calculations (14)

COMPLETE CODE

import cv2
import numpy as np
import matplotlib.pyplot as plt

#using opencv to read an image
#BGR Image
image = cv2.imread("C:/users/public/pictures/underexposed_image.jpg")

#seperating colour channels
B = image[:,:,0] #blue layer
G = image[:,:,1] #green layer
R = image[:,:,2] #red layer

#equilize each channel seperately
b_equi = cv2.equalizeHist(B)
g_equi = cv2.equalizeHist(G)
r_equi = cv2.equalizeHist(R)

#calculate histograms for each channel seperately
B_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256])
G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])
R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])

#merge thechannels and create new image
equi_im = cv2.merge([b_equi,g_equi,r_equi])

#visualize the equilized channels seperately
plt.imshow(b_equi)
plt.title("b_equi")
plt.show()
plt.imshow(g_equi)
plt.title("g_equi")
plt.show()
plt.imshow(r_equi)
plt.title("r_equi")
plt.show()

#visualize the channel histograms seperately
plt.subplot(2, 2, 1)
plt.plot(G_histo, 'g')
plt.subplot(2, 2, 2)
plt.plot(R_histo, 'r')
plt.subplot(2, 2, 3)
plt.plot(B_histo, 'b')

#visualize the original and equilized images
cv2.namedWindow("Original Image", cv2.WINDOW_NORMAL);
cv2.imshow("Original Image",image);
cv2.namedWindow("New Image", cv2.WINDOW_NORMAL);
cv2.imshow("New Image",equi_im);

cv2.waitKey(0) & 0xFF
cv2.destroyAllWindows()

Thanks For Reading, Follow For More.
Happy learning!

Connect with me on Linkedin

OpenCV: Image Histogram Calculations (2024)

FAQs

How to calculate the histogram of an image? ›

The histogram is computed by examining all pixels in the image and assigning each to a bin depending on the pixel intensity. The final value of a bin is the number of pixels assigned to it.

What is calcHist in OpenCV? ›

For simple purposes, OpenCV implements the function cv::calcHist , which calculates the histogram of a set of arrays (usually images or image planes). It can operate with up to 32 dimensions.

When not to use histogram equalization? ›

Histogram equalization well distributes the pixels intensity over the full intensity range. But HE has "mean-shift" problem [6], it shifts the mean intensity value to the middle gray level of the intensity range. So this technique is not useful where brightness preservation is required.

What is the formula for histograms? ›

A histogram is a type of graph that represents grouped data. Frequency density is used to plot a histogram, and it is calculated by dividing the frequency by the class width.

What does a good image histogram look like? ›

A well-exposed photograph has most of its pixels in the middle range of brightness and just a few black or white pixels. The histogram of a good photograph will also be smooth, showing continuous growth and no spikes. However, for night photos, the histogram should lean more towards the left side of the middle.

How do you equalize a histogram in OpenCV? ›

How can we use OpenCV for histogram equalization?
  1. Convert the input image to grayscale/extract a single channel from it.
  2. Instantiate the CLAHE algorithm using cv2. createCLAHE.
  3. Call the . apply method on the CLAHE object to apply histogram equalization.
Feb 1, 2021

What is histogram computation? ›

A Histogram is the graphical or visual representation of the distribution of categorical numeric data in a dataset. We can create them using the Analysis ToolPak or the Pivot Table, and by using the formulas. We can create the Histogram Formula using the FREQUENCY and COUNTIFS formulas.

Why do we use Waitkey in OpenCV? ›

waitkey method allows you to display a window that has been shown with the cv2. imshow method for a specified period of time. The cv2. waitkey(0) method is commonly used in video capture scripts to maintain a continuous window on which the latest frame can appear.

What does 0xFF mean in OpenCV? ›

0xFF is a hexadecimal constant which is 11111111 in binary. By using bitwise AND ( & ) with this constant, it leaves only the last 8 bits of the original (in this case, whatever cv2. waitKey(0) is). Copy link CC BY-SA 3.0. answered Feb 12, 2016 at 21:48.

What does interpolation mean in OpenCV? ›

Bilinear interpolation

This algorithm will generate new pixel values (that doesnt exist on the original) as the pixel values are calculated based on weighted averages of the surrounding pixels. By default, OpenCV applies this interpolation algorithm unless oterwise defined.

What are histograms not good for? ›

The drawbacks of a histogram include their great focus on the quantity of "bins," or lines, and their strong sensitivity to the maximum and lowest of the variable. A graph's appearance might change drastically when the max and min are changed, which can be deceptive.

What happens if histogram equalization is applied twice? ›

If histogram equalization is applied twice, there is no change. This is because a histogram equalization is idempotent. In other words, the value of the histogram equalization does not change when it is multiplied by itself.

What is the formula for drawing a histogram? ›

To draw a histogram we need to find the frequency density of each class interval. The frequency density (D) of a class interval is equal to the frequency (F) divided by the class width. (W).

How do you estimate the value of a histogram? ›

Step 1: For each bar on our histogram, multiply the category (number) by the height of our bar (how many of each number we have). Step 2: Add each of the products determined in Step 1 together to get the total sum of our data. Step 3: Divide this sum by the sum of the heights of the bars to get our mean.

What is the histogram of the whole image? ›

The histogram Hf of the digital image f is a plot or graph of the frequency of occurrence of each gray level in f. Hence, Hf is a one-dimensional function with domain { 0 , … , K − 1 } and possible range extending from 0 to the number of pixels in the image, MN.

How to calculate the histogram for a grayscale image? ›

A grayscale image has only one channel, so we have a value of [0] for channels . We don't have a mask, so we set the mask value to None . We will use 256 bins in our histogram, and the possible values range from 0 to 255 . An unnormalized histogram counts the raw frequencies of the distribution.

Top Articles
Latest Posts
Article information

Author: Jonah Leffler

Last Updated:

Views: 5875

Rating: 4.4 / 5 (45 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Jonah Leffler

Birthday: 1997-10-27

Address: 8987 Kieth Ports, Luettgenland, CT 54657-9808

Phone: +2611128251586

Job: Mining Supervisor

Hobby: Worldbuilding, Electronics, Amateur radio, Skiing, Cycling, Jogging, Taxidermy

Introduction: My name is Jonah Leffler, I am a determined, faithful, outstanding, inexpensive, cheerful, determined, smiling person who loves writing and wants to share my knowledge and understanding with you.