[opencv] Histogram equalization (increase contrast)

4_10_2_Histogram-2: Histogram equalization - OpenCV Chinese official documentation

Learn the concept of histogram equalization and use it to improve the contrast of images.

Recap 

Histogram equalization increases the contrast of an image.

Through a transformation function, the input pixels of the bright region are mapped to the output pixels of the whole region. This is what histogram equalization does. (make all images have the same lighting conditions)

  • Histogram equalization works well when the histogram of an image is restricted to a specific area.
  • It doesn't work well where the histogram covers a large area (i.e. there are both bright and dark pixels) with large intensity variations.
  • Background contrast does improve after histogram equalization. But most of the information is lost due to the high brightness. This is because its histogram is not limited to a specific area as we have seen in the previous case .
  • To solve this problem, Adaptive Histogram Equalization is used . In this case, the image is divided into small pieces called "tiles" (in OpenCV, tileSize is by default 8x8). Each of these blocks is then histogram equalized as usual.
  • In smaller regions, the histogram will be limited to a smaller region (unless there is noise). If there is noise, it will be amplified. To avoid this, a contrast limit is applied .
  • If any histogram bins exceed the specified contrast limit (default 40 in OpenCV), those pixels are cropped and evenly distributed to other bins before applying histogram equalization. After equalization, to remove artifacts in tile boundaries, apply bilinear interpolation .  

content

Recap 

theory

Histogram equalization in OpenCV

CLAHE (Contrast Limited Adaptive Histogram Equalization)


 

theory

The pixel values ​​of an image are limited to a specific range of values. For example, a brighter image will limit all pixels to high values.

But a good image will have pixels from all regions of the image.

So you need to stretch this histogram to both ends (as shown in the image below, from wikipedia), which is what histogram equalization does (in simple terms). This usually increases the contrast of the image.

I suggest you read the Wikipedia page on Histogram Equalization for more details on it. It explains the examples so well that you can understand almost everything after reading it. Instead, here we will see its Numpy implementation. After that, we will see OpenCV functions.

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('wiki.jpg',0)
hist,bins = np.histogram(img.flatten(),256,[0,256])
cdf = hist.cumsum()
cdf_normalized = cdf * float(hist.max()) / cdf.max()
plt.plot(cdf_normalized, color = 'b')
plt.hist(img.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.show()

You can see that the histogram is in the lighter areas. We need the full spectrum. For this, we need a transformation function that maps the input pixels of the bright region to the output pixels of the whole region. This is what histogram equalization does.

Now we find the smallest histogram value (excluding 0) and apply the histogram equalization equation given in the wiki page. But I have used here, masked array concept array from Numpy. For masked arrays, all operations are performed on non-masked elements. You can learn more about masked arrays from the Numpy documentation.

cdf_m = np.ma.masked_equal(cdf,0)
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
cdf = np.ma.filled(cdf_m,0).astype('uint8')

Now we have a lookup table that gives us information about what the output pixel value is for each input pixel value. Therefore, we only apply the transform.

img2 = cdf[img] 

Now, we compute its histogram and cdf as before (you do) and the result looks like this:

Another important feature is that even though the image is a darker one (instead of the one we used a brighter one), after equalization we will get almost the same image. Therefore, this is used as a "reference tool" so that all images have the same lighting conditions. This is useful in many situations. For example, in face recognition, before training on the face data, the histogram equalization process is performed on the face images to make them have the same lighting conditions.

Histogram equalization in OpenCV

OpenCV has a function cv.equalizeHist() to do this. Its input is just a grayscale image and the output is our histogram equalized image. Below is a simple code snippet showing its usage with the same image we use:

img = cv.imread('wiki.jpg',0)
equ = cv.equalizeHist(img)
res = np.hstack((img,equ)) #stacking images side-by-side
cv.imwrite('res.png',res)

So now you can take different images in different lighting conditions, equalize them and check the result.

  • Histogram equalization works well when the histogram of an image is restricted to a specific area.
  • It doesn't work well where the histogram covers a large area (i.e. there are both bright and dark pixels) with large intensity variations.

CLAHE (Contrast Limited Adaptive Histogram Equalization)

The first histogram equalization we just saw takes into account the overall contrast of the image. In many cases this is not a good idea. For example, the figure below shows the input image and its result after global histogram equalization.

  • Background contrast does improve after histogram equalization. But compare the face of the statue in both images . We lost most of the information there due to the high brightness. This is because its histogram is not limited to a specific area as we have seen in previous cases (try plotting the histogram of the input image and you will get more intuition).
  • To solve this problem, Adaptive Histogram Equalization is used . In this case, the image is divided into small pieces called "tiles" (in OpenCV, tileSize is by default 8x8). Each of these blocks is then histogram equalized as usual.
  • In smaller regions, the histogram will be limited to a smaller region (unless there is noise). If there is noise, it will be amplified. To avoid this, a contrast limit is applied .
  • If any histogram bins exceed the specified contrast limit (default 40 in OpenCV), those pixels are cropped and evenly distributed to other bins before applying histogram equalization. After equalization, to remove artifacts in tile boundaries, apply bilinear interpolation .

The following code snippet shows how to apply CLAHE in OpenCV:

import numpy as np
import cv2 as cv
img = cv.imread('tsukuba_l.png',0)
# create a CLAHE object (Arguments are optional).
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
cv.imwrite('clahe_2.jpg',cl1)

Check out the results below and compare them to the results above, especially the statue area:

Guess you like

Origin blog.csdn.net/dujuancao11/article/details/122438209