In this tutorial, we will learn how to apply thresholding and morphology algorithms to segment objects from the background. Thresholding is a powerful tool to segment object images into regions or from the background based on the image intensity values. After applying thresholding methods, morphology methods are usually applied for post-processing such as pruning unwanted spikes, filling holes, and connecting broken pieces. Also, you will learn how to draw and analyze the histogram of a digital image to determine the contrast of the image intensity and use this information to balance the contrast and determine an optimal value for the thresholding.
II. Tutorial
Part 1. Binary Thresholding
This tutorial shows how to create a simple code to apply the OpenCV function for local thresholding.
void plotHist(Mat src, string plotname, int width, int height) {
/// Compute the histograms
Mat hist;
/// Establish the number of bins (for uchar Mat type)
int histSize = 256;
/// Set the ranges (for uchar Mat type)
float range[] = { 0, 256 };
const float* histRange = { range };
calcHist(&src, 1, 0, Mat(), hist, 1, &histSize, &histRange);
double min_val, max_val;
cv::minMaxLoc(hist, &min_val, &max_val);
Mat hist_normed = hist * height / max_val;
float bin_w = (float)width / histSize;
Mat histImage(height, width, CV_8UC1, Scalar(0));
for (int i = 0; i < histSize - 1; i++) {
line(histImage,
Point((int)(bin_w * i), height - cvRound(hist_normed.at<float>(i, 0))),
Point((int)(bin_w * (i + 1)), height - cvRound(hist_normed.at<float>(i + 1, 0))),
Scalar(255), 2, 8, 0);
}
imshow(plotname, histImage);
}
//adaptiveThreshold()
void cv::adaptiveThreshold ( InputArray src,
OutputArray dst,
double maxValue,
int adaptiveMethod,
int thresholdType,
int blockSize,
double C
)
#Python:
dst=cv.adaptiveThreshold( src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
void cv::adaptiveThreshold (
InputArray src,
OutputArray dst,
double maxValue,
int adaptiveMethod,
int thresholdType,
int blockSize,
double C
)
adaptiveThreshold(src, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY,3, 11);
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('sudoku.png',0)
img = cv.medianBlur(img,5)
ret,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
th2 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,\
cv.THRESH_BINARY,11,2)
th3 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv.THRESH_BINARY,11,2)
titles = ['Original Image', 'Global Thresholding (v = 127)',
'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]
for i in range(4):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
// Structuring Element
int shape = MORPH_RECT; // MORPH_CROSS, MORPH_ELLIPSE
Mat element = getStructuringElement( shape, Size(M, N) )
// Apply a morphology operation
dilate( src, dst_morph, element);
erode ( src, dst_morph, element);
import cv2 as cv
import numpy as np
img = cv.imread('j.png',0)
cv.getStructuringElement(cv.MORPH_RECT,(5,5))
kernel = np.ones((5,5),np.uint8)
erosion = cv.erode(img,kernel,iterations = 1)