In the previous blog, we discussed image thresholding and when to use this for image segmentation. We also learned that thresholding can be global or adaptive depending upon how the threshold value is selected.
In this blog, we will discuss
- global thresholding
- OpenCV function for global thresholding
- How to choose threshold value using the iterative algorithm
In global thresholding, each pixel value in the image is compared with a single (global) threshold value. Below is the code for this.
1 2 3 4 5 6 7 8 9 |
def global_threshold(image, thres_value, val_high, val_low): img = image.copy() for i in range(image.shape[0]): for j in range(image.shape[1]): if image[i,j] > thres_value: img[i,j] = val_high else: img[i,j] = val_low return img |
Here, we assign a value of “val_high” to all the pixels greater than the threshold otherwise “val_low“. OpenCV also provides a builtin function for thresholding the image. So, let’s take a look at that function.
OpenCV
1 |
cv2.threshold(src, thresh, maxval, type) → retval, dst |
This function returns the thresholded image(dst) and the threshold value(retval). Its arguments are
- src: input greyscale image (8-bit or 32-bit floating point)
- thresh: global threshold value
- type: Different types that decide “val_high” and “val_low“. In other words, these types decide what value to assign for pixels greater than and less than the threshold. Below figure shows different thresholding types available.
- maxval: maximum value to be used with THRESH_BINARY and THRESH_BINARY_INV. Check the below image.
To specify the thresholding type, write “cv2.” as the prefix. For instance, write cv2.THRESH_BINARY if you want to use this type. Let’s take an example
1 2 3 4 5 |
import cv2 # Load an image in the greyscale img = cv2.imread('D:/downloads/opencv_logo1.PNG',cv2.IMREAD_GRAYSCALE) # threshold the image ret, thresh = cv2.threshold(img,75,255,cv2.THRESH_BINARY) |
Similarly, you can apply other thresholding types to check how they work. Till now we discussed how to threshold an image using a global threshold value. But we didn’t discuss how to get this threshold value. So, in the next section, let’s discuss this.
How to choose the threshold value?
As already discussed, that global thresholding is a suitable approach only when intensity distributions of the background and the ROI are sufficiently distinct. In other words, there is a clear valley between the peaks of the histogram. We can easily select the threshold value in that situation. But what if we have a number of images. In that case, we don’t manually want to first check the image histogram and then deciding the threshold value. We want something that can automatically estimate the threshold value for each image. Below is the algorithm that can be used for this purpose.
Below is the code for the above algorithm.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
def thres_finder(img, thres=20,delta_T=1.0): # Step-2: Divide the images in two parts x_low, y_low = np.where(img<=thres) x_high, y_high = np.where(img>thres) # Step-3: Find the mean of two parts mean_low = np.mean(img[x_low,y_low]) mean_high = np.mean(img[x_high,y_high]) # Step-4: Calculate the new threshold new_thres = (mean_low + mean_high)/2 # Step-5: Stopping criteria, otherwise iterate if abs(new_thres-thres)< delta_T: return new_thres else: return thres_finder(img, thres=new_thres,delta_T=1.0) |
Now, let’s take an example to check how’s this working.
1 2 3 4 5 6 7 8 9 10 11 |
import cv2 # Load an image in the greyscale img = cv2.imread('D:/downloads/opencv_logo1.PNG',cv2.IMREAD_GRAYSCALE) # apply threshold finder vv1 = thres_finder1(img, thres=30,delta_T=1.0) # threshold the image ret, thresh = cv2.threshold(img,vv1,255,cv2.THRESH_BINARY) # Display the image side by side out = cv2.hconcat([img,thresh]) cv2.imshow('threshold',out) cv2.waitKey(0) |
That’s all for this blog. In the next blog, we will discuss how to perform optimum global thresholding using Otsu’s method. 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.