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

Adaptive histogram equalization with contrast limitation

In “Histogram equalization in Detail”, we have learned the basic concepts of histogram equalization and can perform histogram equalization using the cv2.equalizehist () function.

In this section, we will introduce how to apply the Contrast Limited Adaptive Histogram Equalization (CLAHE) to equalize images. CLAHE is a variant of Adaptive Histogram Equalization (AHE), but the difference is that the increase of contrast is limited. Noise in relatively uniform areas of the image is over-amplified by AHE, and CLAHE solves this problem by limiting contrast increase. The algorithm is used to improve the contrast of an image by creating multiple histograms of the original image and using these histograms to redistribute the brightness of the image.

Next, CLAHE is applied to grayscale and color images. When CLAHE is applied, there are two important parameters. The first is clipLimit, which sets the threshold for contrast limits. The default is 40. The second is tileGridSize, which sets the number of tiles in rows and columns. When CLAHE is applied, the image is divided into small pieces called tiles (8 x 8 by default) to perform its calculations. To apply CLAHE to grayscale images, use the following code:

# load image
image = cv2.imread('example.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Grayscale image application CLAHE
clahe = cv2.createCLAHE(clipLimit=2.0)
gray_image_clahe = clahe.apply(gray_image)
# Use different clipLimit values
clahe.setClipLimit(5.0)
gray_image_clahe_2 = clahe.apply(gray_image)
clahe.setClipLimit(10.0)
gray_image_clahe_3 = clahe.apply(gray_image)
clahe.setClipLimit(20.0)
gray_image_clahe_4 = clahe.apply(gray_image)
Copy the code

Then, we apply CLAHE to color images, similar to the contrast equalization method of color images, and create four functions to equalize color images using CLAHE only on brightness channels in different color Spaces:

def equalize_clahe_color_hsv(img) :
    cla = cv2.createCLAHE(clipLimit=4.0)
    H, S, V = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))
    eq_V = cla.apply(V)
    eq_image = cv2.cvtColor(cv2.merge([H, S, eq_V]), cv2.COLOR_HSV2BGR)
    return eq_image

def equalize_clahe_color_lab(img) :
    cla = cv2.createCLAHE(clipLimit=4.0)
    L, a, b = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2Lab))
    eq_L = cla.apply(L)
    eq_image = cv2.cvtColor(cv2.merge([eq_L, a, b]), cv2.COLOR_Lab2BGR)
    return eq_image

def equalize_clahe_color_yuv(img) :
    cla = cv2.createCLAHE(clipLimit=4.0)
    Y, U, V = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2YUV))
    eq_Y = cla.apply(Y)
    eq_image = cv2.cvtColor(cv2.merge([eq_Y, U, V]), cv2.COLOR_YUV2BGR)
    return eq_image

def equalize_clahe_color(img) :
    cla = cv2.createCLAHE(clipLimit=4.0)
    channels = cv2.split(img)
    eq_channels = []
    for ch in channels:
        eq_channels.append(cla.apply(ch))
    eq_image = cv2.merge(eq_channels)
    return eq_image
# Color image application CLAHE
image_clahe_color = equalize_clahe_color(image)
image_clahe_color_lab = equalize_clahe_color_lab(image)
image_clahe_color_hsv = equalize_clahe_color_hsv(image)
image_clahe_color_yuv = equalize_clahe_color_yuv(image)

# visualization
show_img_with_matplotlib(cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR), "gray".1)
show_img_with_matplotlib(cv2.cvtColor(gray_image_clahe, cv2.COLOR_GRAY2BGR), "Gray CLAHE clipLimit = 2.0".2)
show_img_with_matplotlib(cv2.cvtColor(gray_image_clahe_2, cv2.COLOR_GRAY2BGR), "Gray CLAHE clipLimit = 5.0".3)
# The visualization methods of other images are similar and will not be repeated
#...
Copy the code

Compare the results after applying all these functions to the test images, as shown below:

In the figure above, we can see the different effects of applying CLAHE on test images by changing the clipLimit parameters, as well as the different results of applying CLAHE on brightness channels in different color Spaces (LAB, HSV and YUV). Among them, you can see the different effects of applying CLAHE on the three channels of the BGR image versus just using CLAHE on the brightness channels of different color Spaces.

Compare CLAHE with histogram equalization

To better show the effect of CLAHE, we then compare the effect of CLAHE and histogram equalization (cv2.equalizehist ()) on the same image, visualizing both the generated image and the generated histogram.

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

hist = cv2.calcHist([gray_image], [0].None[256], [0.256])
# Histogram equalization
gray_image_eq = cv2.equalizeHist(gray_image)
# Calculate the histogram
hist_eq = cv2.calcHist([gray_image_eq], [0].None[256], [0.256])
# to create clahe:
clahe = cv2.createCLAHE(clipLimit=4.0)
# Apply clahe to grayscale images
gray_image_clahe = clahe.apply(gray_image)
# Calculate the histogram
hist_clahe = cv2.calcHist([gray_image_clahe], [0].None[256], [0.256])
Copy the code

The visualization results are shown below:

From the above comparison, it is safe to say that CLAHE has better results and performance than applying histogram equalization in many cases.

A link to the

Basic concept of OpenCV histogram

OpenCV gray histogram details

OpenCV color histogram with custom histogram visualization

OpenCV histogram equalization in detail