- In this tutorial, you will learn Simple thresholding, Adaptive thresholding, Otsu's thresholding
- In this tutorial, you will learn Simple thresholding, Adaptive thresholding and Otsu's thresholding.
etc.
- You will learn the functions **cv.threshold** and **cv.adaptiveThreshold**.
- You will learn these functions : **cv.threshold**, **cv.adaptiveThreshold** etc.
Simple Thresholding
Simple Thresholding
-------------------
-------------------
Here, the matter is straight forward. If pixel value is greater than a threshold value, it is
Here, the matter is straight forward. For every pixel, the same threshold value is applied.
assigned one value (may be white), else it is assigned another value (may be black). The function
If the pixel value is smaller than the threshold, it is set to 0, otherwise it is set to a maximum value.
used is **cv.threshold**. First argument is the source image, which **should be a grayscale
The function **cv.threshold** is used to apply the thresholding.
image**. Second argument is the threshold value which is used to classify the pixel values. Third
The first argument is the source image, which **should be a grayscale image**.
argument is the maxVal which represents the value to be given if pixel value is more than (sometimes
The second argument is the threshold value which is used to classify the pixel values.
less than) the threshold value. OpenCV provides different styles of thresholding and it is decided
The third argument is the maximum value which is assigned to pixel values exceeding the threshold.
by the fourth parameter of the function. Different types are:
OpenCV provides different types of thresholding which is given by the fourth parameter of the function.
Basic thresholding as described above is done by using the type cv.THRESH_BINARY.
All simple thresholding types are:
- cv.THRESH_BINARY
- cv.THRESH_BINARY
- cv.THRESH_BINARY_INV
- cv.THRESH_BINARY_INV
@ -25,12 +26,12 @@ by the fourth parameter of the function. Different types are:
- cv.THRESH_TOZERO
- cv.THRESH_TOZERO
- cv.THRESH_TOZERO_INV
- cv.THRESH_TOZERO_INV
Documentation clearly explain what each type is meant for. Please check out the documentation.
See the documentation of the types for the differences.
Two outputs are obtained. First one is a **retval** which will be explained later. Second output is
The method returns two outputs.
our**thresholded image**.
The first is the threshold that was used and the second output is the**thresholded image**.
Code :
This code compares the different simple thresholding types:
@code{.py}
@code{.py}
import cv2 as cv
import cv2 as cv
import numpy as np
import numpy as np
@ -53,34 +54,31 @@ for i in xrange(6):
plt.show()
plt.show()
@endcode
@endcode
@note To plot multiple images, we have used plt.subplot() function. Please checkout Matplotlib docs
@note To plot multiple images, we have used the plt.subplot() function. Please checkout the matplotlib docs for more details.
for more details.
Result is given below :
The code yields this result:
![image](images/threshold.jpg)
![image](images/threshold.jpg)
Adaptive Thresholding
Adaptive Thresholding
---------------------
---------------------
In the previous section, we used a global value as threshold value. But it may not be good in all
In the previous section, we used one global value as a threshold.
the conditions where image has different lighting conditions in different areas. In that case, we go
But this might not be good in all cases, e.g. if an image has different lighting conditions in different areas.
for adaptive thresholding. In this, the algorithm calculate the threshold for a small regions of the
In that case, adaptive thresholding thresholding can help.
image. So we get different thresholds for different regions of the same image and it gives us better
Here, the algorithm determines the threshold for a pixel based on a small region around it.
results for images with varying illumination.
So we get different thresholds for different regions of the same image which gives better results for images with varying illumination.
It has three ‘special’ input params and only one output argument.
Additionally to the parameters described above, the method cv.adaptiveThreshold three input parameters:
**Adaptive Method** - It decides how thresholding value is calculated.
The **adaptiveMethod** decides how the threshold value is calculated:
- cv.ADAPTIVE_THRESH_MEAN_C : threshold value is the mean of neighbourhood area.
- cv.ADAPTIVE_THRESH_MEAN_C: The threshold value is the mean of the neighbourhood area minus the constant **C**.
- cv.ADAPTIVE_THRESH_GAUSSIAN_C : threshold value is the weighted sum of neighbourhood
- cv.ADAPTIVE_THRESH_GAUSSIAN_C: The threshold value is a gaussian-weighted sum of the neighbourhood
values where weights are a gaussian window.
values minus the constant **C**.
**Block Size** - It decides the size of neighbourhood area.
The **blockSize** determines the size of the neighbourhood area and **C** is a constant that is subtracted from the mean or weighted sum of the neighbourhood pixels.
**C** - It is just a constant which is subtracted from the mean or weighted mean calculated.
The code below compares global thresholding and adaptive thresholding for an image with varying
Below piece of code compares global thresholding and adaptive thresholding for an image with varying
illumination:
illumination:
@code{.py}
@code{.py}
import cv2 as cv
import cv2 as cv
@ -106,33 +104,30 @@ for i in xrange(4):
plt.xticks([]),plt.yticks([])
plt.xticks([]),plt.yticks([])
plt.show()
plt.show()
@endcode
@endcode
Result:
Result:
![image](images/ada_threshold.jpg)
![image](images/ada_threshold.jpg)
Otsu’s Binarization
Otsu's Binarization
-------------------
-------------------
In the first section, I told you there is a second parameter **retVal**. Its use comes when we go
In global thresholding, we used an arbitrary chosen value as a threshold.
for Otsu’s Binarization. So what is it?
In contrast, Otsu's method avoids having to choose a value and determines it automatically.
In global thresholding, we used an arbitrary value for threshold value, right? So, how can we know a
Consider an image with only two distinct image values (*bimodal image*), where the histogram would only consist of two peaks.
value we selected is good or not? Answer is, trial and error method. But consider a **bimodal
A good threshold would be in the middle of those two values.
image** (*In simple words, bimodal image is an image whose histogram has two peaks*). For that
Similarly, Otsu's method determines an optimal global threshold value from the image histogram.
image, we can approximately take a value in the middle of those peaks as threshold value, right ?
That is what Otsu binarization does. So in simple words, it automatically calculates a threshold
In order to do so, the cv.threshold() function is used, where cv.THRESH_OTSU is passed as an extra flag.
value from image histogram for a bimodal image. (For images which are not bimodal, binarization
The threshold value can be chosen arbitrary.
won’t be accurate.)
The algorithm then finds the optimal threshold value which is returned as the first output.
For this, our cv.threshold() function is used, but pass an extra flag, cv.THRESH_OTSU. **For
Check out the example below.
threshold value, simply pass zero**. Then the algorithm finds the optimal threshold value and
The input image is a noisy image.
returns you as the second output, retVal. If Otsu thresholding is not used, retVal is same as the
In the first case, global thresholding with a value of 127 is applied.
threshold value you used.
In the second case, Otsu's thresholding is applied directly.
In the third case, the image is first filtered with a 5x5 gaussian kernel to remove the noise, then Otsu thresholding is applied.
Check out below example. Input image is a noisy image. In first case, I applied global thresholding
See how noise filtering improves the result.
for a value of 127. In second case, I applied Otsu’s thresholding directly. In third case, I
filtered image with a 5x5 gaussian kernel to remove the noise, then applied Otsu thresholding. See