C ++ and opencv achieve adaptive threshold algorithm OTSU

OTSU algorithm principle

Otsu algorithm (or between Otsu Otsu method) using the idea of clustering. It is the number of gradations of the image by a gray level is divided into two parts, so that the gradation value of the difference between the two portions of the maximum, minimum gradation difference between each section.
To find a suitable gray levels divided by the variance calculation. Otsu algorithm can be employed when the binarization threshold to automatically select binarization.
otsu algorithm is considered the best image segmentation algorithm of the threshold selection , simple calculation is not affected by the brightness and contrast of the image. Therefore, the largest variance divided between class means that the probability of misclassification minimum.
Let t be the set threshold value.

w0: the ratio of the number of pixels after the separation of the foreground image occupy
u0: mean gray foreground pixels after the separation point
w1: the ratio of the number of pixels after the separation of the background image representing
u1: mean gray background pixel point after separation

The total of the average gray image: u = w0 * u0 + w1 * u1

From L (grayscale 0-255) t gray levels to traverse, so that t is a value when the foreground and background of the largest variance , then the value of t is our asking too threshold. Wherein the variance is calculated as follows:

g = wo * (u0-u) * (u0-u) + w1 * (u1-u) * (u1-u)

This large amount of formula can be used:

g = w0∗w1∗(u0−u1)∗(u0−u1)

Since Otsu algorithm is a grayscale image clustering, so before performing Otsu algorithm necessary to calculate the histogram of the image.

C ++ / C code implementation

int avg256cal::getOTSUthread(Mat& src)
{
	int size = 256;

	int *NoArry = new int[size];// 直方图矩阵

	for (int i = 0; i < size; ++i)// 初始化
		NoArry[i] = 0;

	int r = src.rows;
	int c = src.cols;
	int sum = r*c;

//  建立直方图矩阵
	for (int i = 0; i < r; ++i)
	{
		for (int j = 0; j < c; ++j)
		{	
			uchar pix = src.at<uchar>(i, j);
			NoArry[pix]++;
		}
	}
	//delete[] NoArry;

	int thd = 0; // 阈值
	float w1 = 0, w2 = 0, u1 = 0, u2 = 0, u = 0, thg = 0, MaxTh = 0;
	int cnt1 = 0, cnt2 = 0;
	for (int i = 1; i <= 255; ++i)
	{
		u1 = u2 = w1 = w2 = 0; // 均值,比例初始化
		cnt1 = 0;cnt2 = 0;
		int wt1 = 0, wt2 = 0;// weight初始化

		for (int j = 0; j <i; ++j)
		{
			cnt1 += NoArry[j];
			wt1 += j*NoArry[j];
		}
		u1 = wt1 / cnt1;
		w1 = cnt1*1.0 / sum;

		for (int j = i; j < 256; ++j)
		{
			cnt2 += NoArry[j];
			wt2 += j*NoArry[j];
		}
		u2 = wt2 / cnt2;
		w2 = cnt2*1.0 / sum;

		thg = w1*w2*(u1 - u2)*(u1 - u2);
		if (MaxTh < thg)// 找最大类间方差阈值
		{
			MaxTh = thg;
			thd = i;
		}
	}

	return thd;
}
Published 56 original articles · won praise 10 · views 20000 +

Guess you like

Origin blog.csdn.net/birenxiaofeigg/article/details/98481019