“This is the 16th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Gray histogram

In this article, we will learn how to draw histograms of images in OpenCV. The cv2.calchist () function is used in OpenCV to compute histograms of one or more arrays. Therefore, the function can be applied to single-channel and multi-channel images. We first understand how to calculate the histogram of grayscale image:

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
Copy the code

Where, function parameters are as follows:

parameter explain
images Source images of the uint8 or Float32 type provided as a list, such as [image_gray]
channels Index of channels for which histograms need to be computed, provided as a list (for example, using [0] in grayscale images, or computing histograms for the first, second, or third channel respectively in multi-channel images [0], [1], [2])
mask Mask map, used to calculate the histogram of a specific area of the image defined by the mask. If this parameter is None, the histogram will be computed using the full image without the mask
histSize It represents the number of bins supplied as a list, such as [256]
range Range of strength values to be measured, e.g. [0,256]

Gray histogram without mask

The code for calculating the histogram of the full grayscale image (without mask) is as follows:

image = cv2.imread('example.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist([gray_image], [0].None[256], [0.256])
show_img_with_matplotlib(cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR), "gray".1)
show_hist_with_matplotlib_gray(hist, "grayscale histogram".4.'m')
Copy the code

In the code above, hist is an array of shape (256, 1), with each value (bin) corresponding to the number of pixels with the corresponding hue value.

The brightness of a grayscale image can be defined as the average intensity of all pixels of the image, which is given by the following formula:


B r i g h t n e s s = 1 m n x = 1 m y = 1 n I ( x . y ) Brightness=\frac1 {m\cdot n}\sum ^m_{x=1}\sum ^n_{y=1}I(x,y)

Here, I(x,y)I(x, y)I(x,y) is the tonal value of a particular pixel in the image. Therefore, if the average hue of the image is high, it means that most pixels of the image will be very close to white; Conversely, if the average hue of the image is low, it means that most pixels of the image will be very close to black.

We can perform image addition and subtraction on the grayscale image in order to modify the grayscale intensity of each pixel in the image to see how to change the brightness of the image and how the histogram changes:

M = np.ones(gray_image.shape, dtype="uint8") * 30
# Add 30 to each gray value
added_image = cv2.add(gray_image, M)
# Histogram of the computed result image
hist_added_image = cv2.calcHist([added_image], [0].None[256], [0.256])
# Decrease each gray value by 30
subtracted_image = cv2.subtract(gray_image, M)
# Histogram of the computed result image
hist_subtracted_image = cv2.calcHist([subtracted_image], [0].None[256], [0.256])
# visualization
show_img_with_matplotlib(cv2.cvtColor(added_image, cv2.COLOR_GRAY2BGR), "gray lighter".2)
show_hist_with_matplotlib_gray(hist_added_image, "grayscale histogram".5.'m')
show_img_with_matplotlib(cv2.cvtColor(subtracted_image, cv2.COLOR_GRAY2BGR), "gray darker".3)
show_hist_with_matplotlib_gray(hist_subtracted_image, "grayscale histogram".6.'m')
Copy the code

The gray image in the middle corresponds to each pixel of the original image plus 35 images, resulting in a brighter image. The histogram of the image will shift to the right because there are no pixels with intensity in the range [0-35]; The grayscale image on the right corresponds to the image in which 35 is subtracted from each pixel of the original image, resulting in darker images, and the histogram of the image will be shifted to the left because there are no pixels with intensity within the range of [220-255].

Gray histogram with mask

If you need to apply a mask, you need to create one first.

Load and modify the image
image = cv2.imread('example.png')
height, width = image.shape[:2]
# Added some small black and white circles with 0 and 255 grayscale intensities
for i in range(0, width, 20):
    cv2.circle(image, (i, 390), 5, (0.0.0), -1)
    cv2.circle(image, (i, 10), 5, (255.255.255), -1)
# Convert the image to grayscale image
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
Create a mask
mask = np.zeros(gray_image.shape[:2], np.uint8)
mask[30:190.30:190] = 255
Copy the code

The mask consists of a black image of the same size as the loaded image, with the white image corresponding to the region of the histogram to be computed. Then calculate the histogram using the created mask, call cv2.calchist () and pass the created mask:

hist_mask = cv2.calcHist([gray_image], [0], mask, [256], [0.256])
# visualization
show_img_with_matplotlib(cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR), "gray".1)
show_hist_with_matplotlib_gray(hist, "grayscale histogram".2.'m')
show_img_with_matplotlib(cv2.cvtColor(masked_img, cv2.COLOR_GRAY2BGR), "masked gray image".3)
show_hist_with_matplotlib_gray(hist_mask, "grayscale masked histogram".4.'m')
Copy the code

As shown in the figure above, we have modified the image by adding some small black and white circles respectively, which results in the histogram having larger values in bins = 0 and 255, as shown in the first histogram. However, these added changes do not appear in the histogram because masks are applied, so they are not taken into account in the histogram calculation.

A link to the

Basic concept of OpenCV histogram