“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:


h ( i ) = number of pixels with intensity  i . ( i [ 0 . 255 ] ) h(i) = \text{number of pixels with intensity }i,(i\in[0, 255])

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