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

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

在数学上,数据 D D D 的阈值 d ∗ d^* d 可以表示为以下优化问题:
d ∗ = O T S U ( D ) = a r g   max ⁡ 1 ≤ d ≤ L σ B 2 ( d ) d^*=OTSU(D)=arg\ \max \limits_{1\leq d \leq L} \sigma_B^2(d) d=OTSU(D)=arg 1dLmaxσB2(d)

其中:
σ B 2 ( d ) = [ μ T ω ( d ) − μ ( d ) ] 2 ω ( d ) [ 1 − ω ( d ) ] \sigma_B^2(d)=\dfrac{[\mu_T^{}\omega(d)-\mu(d)]^2}{\omega(d)[1-\omega(d)]} σB2(d)=ω(d)[1ω(d)][μTω(d)μ(d)]2
μ T = ∑ i = 1 L i p i ω ( d ) = ∑ i = 1 d p i μ ( d ) ∑ i = 1 d i p i \mu_T^{}=\sum \limits_{i=1}^L ip_i^{} \\ \omega(d)=\sum \limits_{i=1}^d p_i^{} \\ \mu(d)\sum \limits_{i=1}^d ip_i^{} μT=i=1Lipiω(d)=i=1dpiμ(d)i=1dipi

其中 p i p_i^{} pi 为数据中 i i i 的概率, L L L 为数据 D D 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);	
}

欢迎大家批评指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A-Chin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值