“This is the 17th day of my participation in the First Challenge 2022.

Color histogram

In “Gray Histogram Explanation”, we know that The cv2.calchist () function is used in OpenCV to calculate the histogram of one or more arrays, and explain in detail how to use this function to draw the histogram of a gray image. Next, we’ll learn how to calculate color histograms.

In multi-channel images, computing the color histogram is essentially computing the histogram for each channel, so we need to create a function to compute the histogram for multiple channels:

def hist_color_img(img) :
    histr = []
    histr.append(cv2.calcHist([img], [0].None[256], [0.256]))
    histr.append(cv2.calcHist([img], [1].None[256], [0.256]))
    histr.append(cv2.calcHist([img], [2].None[256], [0.256]))
    return histr
Copy the code

We can also create a for loop or similar method to call cv2.calchist () three times.

Next we need to call the HIST_COLOR_img () function to calculate the color histogram of the image:

# load image
image = cv2.imread('example.png')
# Calculate the color histogram of the image
hist_color = hist_color_img(image)
# visualization
show_img_with_matplotlib(image, "image".1)
# Visualize color histogram functions
def show_hist_with_matplotlib_rgb(hist, title, pos, color) :
    ax = plt.subplot(2.3, pos)
    plt.xlabel("bins")
    plt.ylabel("number of pixels")
    plt.xlim([0.256])
    for (h, c) in zip(hist, color):
        plt.plot(h, color=c)
show_hist_with_matplotlib_rgb(hist_color, "color histogram".4['b'.'g'.'r'])
Copy the code

Again, use cv2.add() and cv2.Subtract () to modify the brightness of the loaded BGR image (add/subtract 10 per pixel value of the original BGR image) and see how the histogram changes:

M = np.ones(image.shape, dtype="uint8") * 10
# Add 10 per pixel value to the original BGR image
added_image = cv2.add(image, M)
hist_color_added_image = hist_color_img(added_image)

# Subtract 10 from each pixel value of the original BGR image
subtracted_image = cv2.subtract(image, M)
hist_color_subtracted_image = hist_color_img(subtracted_image)

# visualization
show_img_with_matplotlib(added_image, "image lighter".2)
show_hist_with_matplotlib_rgb(hist_color_added_image, "color histogram".5['b'.'g'.'r'])
show_img_with_matplotlib(subtracted_image, "image darker".3)
show_hist_with_matplotlib_rgb(hist_color_subtracted_image, "color histogram".6['b'.'g'.'r'])
Copy the code

Custom visualization of histograms

To visualize the histogram, we call the plt.plot() function, since there are no OpenCV functions that can be used to plot the histogram directly. Therefore, if we want to draw histograms using OpenCV, we must draw histograms using OpenCV primitives such as cv2.polylines() and cv2.Rectangle ().

We create the plot_hist() function to do this, which creates a BGR color image and plots the histogram in it. The code for this function is as follows:

def plot_hist(hist_items, color) :
    We added some offsets for visualization purposes
    offset_down = 10
    offset_up = 10
    # This will be used to create the point to visualize (x coordinates)
    x_values = np.arange(256).reshape(256.1)
    # create canvas
    canvas = np.ones((300.256.3), dtype='uint8') * 256

    for hist_item, col in zip(hist_items, color):
        # Normalize within the appropriate scope of visualization
        cv2.normalize(hist_item, hist_item, 0 + offset_down, 300 - offset_up, cv2.NORM_MINMAX)
        Cast value to int
        around = np.around(hist_item)
        Data type conversion
        hist = np.int32(around)
        # create points using histograms and x coordinates
        pts = np.column_stack((x_values, hist))
        # plot points
        cv2.polylines(canvas, [pts], False, col, 2)
        Draw a rectangle
        cv2.rectangle(canvas, (0.0), (255.298), (0.0.0), 1)
    
    # Flip the image up/down
    res = np.flipud(canvas)
    return res
Copy the code

This function takes the histogram and builds (x, y) points PTS for each element of the histogram, where the y value represents the frequency of the x element of the histogram. These points, PTS, are drawn using the cv2.polylines() function, which draws curves from the PTS array. Finally, the image needs to be flipped vertically because the y value is reversed. Finally, use plt.plot() and the custom function’s histogram plotting function for comparison:

# fetch image
image = cv2.imread('example.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Grayscale histogram plotted using plt.plot(
hist = cv2.calcHist([gray_image], [0].None[256], [0.256])

# Color histogram drawn using plt.plot()
hist_color = hist_color_img(image)

# Custom gray histogram
gray_plot = plot_hist([hist], [(255.0.255)])

# Custom color histogram
color_plot = plot_hist(hist_color, [(255.0.0), (0.255.0), (0.0.255)])

# visualization
show_img_with_matplotlib(cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR), "gray".1)
show_img_with_matplotlib(image, "image".4)
show_hist_with_matplotlib_gray(hist, "grayscale histogram (matplotlib)".2.'m')
show_hist_with_matplotlib_rgb(hist_color, "color histogram (matplotlib)".3['b'.'g'.'r'])
show_img_with_matplotlib(gray_plot, "grayscale histogram (custom)".5)
show_img_with_matplotlib(color_plot, "color histogram (custom)".6)
Copy the code

A link to the

Basic concept of OpenCV histogram

OpenCV gray histogram details