“This is the 15th day of my participation in the First Challenge 2022. For details: First Challenge 2022”
preface
Histograms are a powerful technique for better understanding image content. For example, many cameras display a histogram of the scene being captured in real time to adjust some of the camera’s parameters (such as exposure time, brightness, or contrast, etc.). In this article, we will learn about the concepts of histograms.
Introduction to histograms
An image histogram is a histogram that reflects the tonal distribution of an image and plots the number of pixels for each tonal value. The number of pixels per hue value is also called frequency. Therefore, the histogram of the gray image whose intensity value is within the range of [0, k-1] will contain exactly K rectangles. For example, in the case of 8-bit grayscale images, K =256 (28=2562^8 = 25628=256), thus, the intensity values are in the range [0, 255]. The height of each rectangle of the histogram is defined as:
For example, h(80)h(80)h(80) is the number of pixels with an intensity of 80.
To better understand the histogram, we construct a graph composed of 7 different grayscale squares. The gray values are 30, 60, 90, 120, 150, 180 and 210 respectively.
def build_sample_image() :
# Define different gray values: 60, 90, 120... , 210,
tones = np.arange(start=60, stop=240, step=30)
Initialize the first 60x60 square with a grayscale value of 30
result = np.ones((60.60.3), dtype="uint8") * 30
# Connect all grayscale squares built
for tone in tones:
img = np.ones((60.60.3), dtype="uint8") * tone
result = np.concatenate((result, img), axis=1)
return result
def build_sample_image_2() :
# Flip constructed grayscale image
img = np.fliplr(build_sample_image())
return img
Copy the code
Next, build the histogram and visualize it:
def show_img_with_matplotlib(color_img, title, pos) :
img_RGB = color_img[:, :, ::-1]
ax = plt.subplot(2.2, pos)
plt.imshow(img_RGB)
plt.title(title)
plt.axis('off')
def show_hist_with_matplotlib_gray(hist, title, pos, color) :
ax = plt.subplot(2.2, pos)
plt.title(title)
plt.xlabel("bins")
plt.ylabel("number of pixels")
plt.xlim([0.256])
plt.plot(hist, color=color)
plt.figure(figsize=(14.10))
plt.suptitle("Grayscale histograms introduction", fontsize=14, fontweight='bold')
# Build the image and convert it to grayscale image
image = build_sample_image()
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image_2 = build_sample_image_2()
gray_image_2 = cv2.cvtColor(image_2, cv2.COLOR_BGR2GRAY)
# Build the histogram
hist = cv2.calcHist([gray_image], [0].None[256], [0.256])
hist_2 = cv2.calcHist([gray_image_2], [0].None[256], [0.256])
# Draw grayscale image and histogram
show_img_with_matplotlib(cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR), "image with 60x60 regions of different tones of gray".1)
show_hist_with_matplotlib_gray(hist, "grayscale histogram".2.'m')
show_img_with_matplotlib(cv2.cvtColor(gray_image_2, cv2.COLOR_GRAY2BGR), "image with 60x60 regions of different tones of gray".3)
show_hist_with_matplotlib_gray(hist_2, "grayscale histogram".4.'m')
plt.show()
Copy the code
The histogram (figure on the right in the image below) shows the number of occurrences (frequency) of each hue value in the image. Since the size of each square area is 60 x 60 = 3600 pixels, the frequency of all the above gray values is 3,600, and the other values are 0:
As shown above, the histogram only shows statistics, not the location of pixels. You can also load real photos and draw histograms by modifying the build_sample_image() function:
def build_sample_image() :
image = cv2.imread('example.png')
return image
Copy the code
Histogram related terms
We’ve seen a simple example of building a histogram in the above example. Here are some terms related to histograms:
The term | introduce |
---|---|
bins | The histogram shows the number of pixels for each hue value, which ranges from 0 to 255. Each hue value is called a bin. The number of bins can be selected as desired. Common values include 8, 16, 32, 64, 128, 256. OpenCV uses histSize to denote bins |
range | The range of tonal values to be measured, usually [0,255], to correspond to all tonal values |