Class Difference Threshold Method (Otsu) image binarization Threshold Selection
The Otsu method was proposed by Dajin in 1979. For image, note T as the segmentation threshold between foreground and background. The ratio of foreground points to image points is w0, and the average gray scale is U0; the proportion of the number of background points to the image is W1, and the average gray scale is U1. The average gray scale of the image is u = W0 * U0 + W1 * U1. From the minimum gray value to the maximum gray value traversing T, when T makes the value G = W0 * (u0-u) 2 + W1 * (u1-u) 2 maximum t is the best threshold for segmentation. The Dajin method can be understood as follows: This formula is actually an inter-Class Variance. The foreground and background produced by the threshold t constitute the entire image, and the foreground value U0 and the probability is W0, the value of the background is U1, the probability is W1, and the total mean is U. This formula is obtained based on the variance definition. Because variance is a measure of gray distribution uniformity, the greater the difference, the greater the difference between the two parts of the image, when some target errors are classified into the background or some background errors are classified into the target, the difference between the two parts is reduced. Therefore, the maximum variance division between classes means that the error score probability is minimized.
Therefore, the equivalent formula G = W0 * W1 * (u0-u1) 2 is adopted in the implementation. Some calculation processes are as follows:
// Retrieve all gray values for Max G.
For intcurrentlevel: = 0 to intarrlen do
Begin
If intsclgraylevel [intcurrentlevel] = 0 then
Continue
Else
Begin
// Calculate the G value when the threshold is intcurrentlevel
Intcount: = 0;
Intsumpels: = 0;
For intloop: = 0 to intcurrentlevel do
Begin
Intcount: = intcount + intsclgraylevel [intloop];
Intsumpels: = intsumpels + intsumpelsarr [intloop];
End;
W0: = intcount/intsize;
U0: = intsumpels/intcount;
W1: = 1-w0;
If intsize-intcount <> 0 then
U1: = (inttotalpels-intsumpels)/(intsize-intcount)
Else
U1: = 0;
Rltempo: = W0 * W1 * (u0-u1) * (u0-u1 );
If rltempo> rlmaxo then
Begin
Rlmaxo: = rltempo;
Result: = intcurrentlevel;
End;
End;
During the test, we found that the threshold value selected by the Dajin method is very good, and it performs well in various situations. Although it is not the best segmentation in many cases, the quality of segmentation is usually guaranteed, which can be said to be the most stable segmentation. We can see from the above that the Dajin algorithm is a common segmentation algorithm. Inspired by its ideas, people have further proposed algorithms for evaluating threshold values of various types. For more information, see [5] and [6.
The Otsu algorithm is easy to use.
/*
The Otsu algorithm is a simple and efficient method for adaptive Calculation of a single threshold (used to convert a gray image to a binary image. The following code was first provided by Ryan Dibble, and was revised by many people, such as Joerg. Schulenburg and R. Z. Liu.
The algorithm analyzes the histogram of the input grayscale image and divides the histogram into two parts to maximize the distance between the two parts. The dividing point is the obtained threshold.
Parameter: * image --- buffer for Image
Rows, cols --- size of Image
Vvv --- debug option, is 0, no debug information outputed
*/
/* ===================================================== ======================================= */
/* Otsu global thresholding routine */
/* Takes a 2D unsigned char array pointer, number of rows, and */
/* Number of Cols in the array. returns the value of the threshold */
/* ===================================================== ======================================= */
Int funmain: Otsu (unsigned char * image, int rows, int cols, int vvv)
{
// Unsigned char * NPS; // image pointer
Int NPS = 0;
Int thresholdvalue = 1; // Threshold Value
Int ihist [256]; // image histogram, 256 points
Int I, j, k; // various counters
Int N, N1, N2, gmin, gmax;
Double M1, M2, sum, csum, FMAX, Sb;
// Set the histogram to zero...
// Memset (ihist, 0, sizeof (ihist ));
For (I = 0; I <256; I ++)
Ihist [I] = 0;
Gmin = 255; gmax = 0;
// Generate a Histogram
For (I = 0; I <rows; I ++)
{
For (j = 0; j <Cols; j ++)
{
NPS = (INT) image [I * Cols + J];
Ihist [NPs] ++;
If (NPs> gmax) gmax = NPS;
If (NPs <gmin) gmin = NPS;
// * NPS ++;/* Next pixel */
}
}
// Set up everything
Sum = csum= 0.0;
N = 0;
For (k = 0; k <= 255; k ++ ){
Sum + = (double) K * (double) ihist [k];/* x * f (x) moment of mass */
N + = ihist [k];/* f (x) Quality */
}
If (! N ){
// If n has no value, there is problems...
Fprintf (stderr, "not normal thresholdvalue = 160/N ");
Return (160 );
}
// Do the Otsu global thresholding method
Fmax =-1.0;
N1 = 0;
For (k = 0; k <255; k ++ ){
N1 + = ihist [k];
If (! N1) {continue ;}
N2 = N-N1;
If (n2 = 0) {break ;}
Csum + = (double) K * ihist [k];
M1 = csum/N1;
M2 = (Sum-csum)/N2;
SB = (double) N1 * (double) N2 * (M1-m2) * (M1-m2 );
/* BBG: Note: can be optimized .*/
If (Sb> fmax ){
Fmax = Sb;
Thresholdvalue = K;
}
}
// At this point we have our thresholding Value
// Debug code to display thresholding values
If (vvv & 1)
Fprintf (stderr, "# Otsu: thresholdvalue = % d gmin = % d gmax = % d/N ",
Thresholdvalue, gmin, gmax );
Return (thresholdvalue );
}