In the previous blog, we discussed how global thresholding can be a tedious task when dealing with images having non-uniform illumination. This is because you need to ensure that while subdividing an image, each sub-image histogram is bimodal. Otherwise, the segmentation task will fail.
In this blog, we will discuss adaptive thresholding that works well for varying conditions like non-uniform illumination, etc. In this, the threshold value is calculated separately for each pixel using some statistics obtained from its neighborhood. This way we will get different thresholds for different image regions and thus tackles the problem of varying illumination.
The whole procedure can be summed up as:
- For each pixel in the image
- Calculate the statistics (such as mean, median, etc.) from its neighborhood. This will be the threshold value for that pixel.
- Compare the pixel value with this threshold
Now, let’s discuss the OpenCV function for adaptive thresholding.
1 |
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C) |
- src: 8-bit greyscale image
- thresholdType: This tells us what value to assign to pixels greater/less than the threshold. Must be either THRESH_BINARY or THRESH_BINARY_INV. (You can read more about it here).
- maxValue: This is the value assigned to the pixels after thresholding. This depends on the thresholding type. If the type is cv2.THRESH_BINARY, all the pixels greater than the threshold are assigned this maxValue.
- adaptiveMethod: This tells us how the threshold is calculated from the pixel neighborhood. This currently supports two methods:
- cv2.ADAPTIVE_THRESH_MEAN_C: In this, the threshold value is the mean of the neighborhood area.
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C: In this, the threshold value is the weighted sum of the neighborhood area. This uses Gaussian weights computed using getGaussiankernel() method. You can read more about it here.
- blockSize: This is the neighborhood size.
- C: a constant which is subtracted from the threshold.
As discussed OpenCV only provides mean and weighted mean to serve as the threshold. But don’t limit yourself to these two statistics. Try other statistics like standard deviation, median, etc. by writing your own helper function. Let’s see how to use this.
1 2 3 4 5 6 7 8 9 10 11 12 |
import cv2 # Load the image img1 = cv2.imread("D:/downloads/adap1.jpg",0) # Apply Otsu method ret, thres = cv2.threshold(img2,127,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) # Apply adaptive threshold th3 = cv2.adaptiveThreshold(img2,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,5,2) # Display the result cv2.imshow('original',img1) cv2.imshow('otsu', thres) cv2.imshow('adaptive', th3) cv2.waitKey(0) |
See how effective adaptive thresholding is in the case of non-uniform illumination. Hope you enjoy reading.
If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.