C++实现OTSU算法(大津法)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/L_J_Kin/article/details/102776159

OTSU算法,即最大类间方差,是由日本学者大津(Nobuyuki Otsu)于1979年提出的一种自适应阈值确定方法。算法假设一组数据能够根据阈值,被分为两部分,使得两类的区分度最大。两类之间的界限即为最佳分割阈值。大家有兴趣可以参考:Otsu, N. (1979)

在数学上,数据D的阈值d可以表示为以下优化问题:
OTSU公式
其中:
OTSU1
OTSU2 OTSU3 OTSU4
其中
pi为数据中i的概率,L为数据D*的最大值。
代码实现如下:

int otsu(float *pix, int pixsize, float pixmin, float pixmax)
{
	//pix 输入的数据
	//pixsize 数据的长度
	//pixmin 数据最小值
	//pixmax 数据最大值
	int pixsi = (int)pixmax - (int)pixmin+1;
	int nThresh = (int)pixmin;
	float *fStdHistogram = new float [pixsi]; // 图像直方图,pixsi个点
	float *fGrayAccu = new float [pixsi];
	float *fGrayAve = new float [pixsi]; 
	float HistogramSum = 0.0;
	float fAverage = 0;  
	float fTemp, fMax = 0;
	memset(fStdHistogram, 0.0, sizeof(float) * pixsi);
	memset(fGrayAccu, 0.0, sizeof(float) * pixsi);
	memset(fGrayAve, 0.0, sizeof(float) * pixsi);
	for (int i = 0; i < pixsize; ++i)
		fStdHistogram[(int)pix[i] - (int)pixmin] += 1.0;
	
	for (int i = 0; i < pixsi; ++i)
		fStdHistogram[i] /= (pixsize * 1.0);

	int minnew = 0, maxnew = pixsi;
	for(int i = 0;i < pixsi; ++i)  
	{  
		for(int j = 0; j <= i; ++j)  
		{  
			fGrayAccu[i] += fStdHistogram[j];
			fGrayAve[i] += j * fStdHistogram[j];  
		} 
		fAverage += i * fStdHistogram[i];
	}  

	for(int i = 0; i < pixsi; ++i)  
	{
		if (HistogramSum < 0.02) minnew = i;
		if (HistogramSum >= 0.98)
		{
			maxnew = i;
			break;
		}
		HistogramSum += fStdHistogram[i];
	}

	for(int i = minnew; i < maxnew; ++i)
	{  
		fTemp = (fAverage * fGrayAccu[i] - fGrayAve[i]) * (fAverage * fGrayAccu[i] - fGrayAve[i]) / (fGrayAccu[i] * (1 - fGrayAccu[i])); 
		if(fTemp > fMax)  
		{  
			fMax = fTemp;
			nThresh = i;
		}  
	}
	delete [] fStdHistogram;
	delete [] fGrayAccu;
	delete [] fGrayAve;
	return 1 * (nThresh + (int)pixmin);	
}

未完待续。

猜你喜欢

转载自blog.csdn.net/L_J_Kin/article/details/102776159