OTSU算法提取图像阈值的C语言实现

OTSU算法也称最大类间差法,有时也称之为大津算法,被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

设灰度图像灰度级是L,则灰度范围为[0,L-1],利用OTSU算法计算图像的最佳阈值为:
t = Max[w0(t) * (u0(t) - u)^2 + w1(t) * (u1(t) - u)^2)]
其中的变量说明:当分割的阈值为t时,w0为背景比例,u0为背景均值,w1为前景比例,u1为前景均值,u为整幅图像的均值。
使以上表达式值最大的t,即为分割图像的最佳阈值。

以下是一段在OpenCV中实现的C语言程序,即一个使用OTSU算法提取图像阈值的函数,输入参数为一个图像指针,返回分割该图像的最佳阈值。

int otsuThreshold(IplImage *frame)
{
	int width = frame->width;
	int height = frame->height;
	int pixelCount[GrayScale];
	float pixelPro[GrayScale];
	int i, j, pixelSum = width * height, threshold = 0;
	uchar* data = (uchar*)frame->imageData;

	for(i = 0; i < GrayScale; i++)
	{
		pixelCount[i] = 0;
		pixelPro[i] = 0;
	}

	//统计灰度级中每个像素在整幅图像中的个数
	for(i = 0; i < height; i++)
	{
		for(j = 0;j < width;j++)
		{
			pixelCount[(int)data[i * width + j]]++;
		}
	}
	
	//计算每个像素在整幅图像中的比例
	for(i = 0; i < GrayScale; i++)
	{
		pixelPro[i] = (float)pixelCount[i] / pixelSum;
	}

	//遍历灰度级[0,255]
	float w0, w1, u0tmp, u1tmp, u0, u1, u, 
			deltaTmp, deltaMax = 0;
	for(i = 0; i < GrayScale; i++)
	{
		w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
		for(j = 0; j < GrayScale; j++)
		{
			if(j <= i)   //背景部分
			{
				w0 += pixelPro[j];
				u0tmp += j * pixelPro[j];
			}
			else   //前景部分
			{
				w1 += pixelPro[j];
				u1tmp += j * pixelPro[j];
			}
		}
		u0 = u0tmp / w0;
		u1 = u1tmp / w1;
		u = u0tmp + u1tmp;
		deltaTmp = 
			w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);
		if(deltaTmp > deltaMax)
		{
			deltaMax = deltaTmp;
			threshold = i;
		}
	}
	return threshold;
}


作者:Steven Wang | 可以转载, 转载时务必以超链接形式标明文章原始出处和作者信息及版权声明

网址:http://blog.stevenwang.name/ostu-threshold-56002.html


(222)

它是1979年由日本大津提出的,在最小二乘法原理基础上推导出来的。适用于双峰的直方图,它的基本原理是:

OSTU算法 - 伊之魅 - jumay angel

/*************************************************************************************************************/
/*作者:jumay                                 blog:ljm426.blog.163.com                                       */
/*Ostu算法 opencv                                                                                                          */
/*************************************************************************************************************/
/************************************************************************/
/* otsu 根据输入的直方图,自适应的返回分割阈值                          */
/* Histogram:单通道图像的直方图                                         */
/*HistogramBins:划分为Hist的个数                                        */
/* 返回值:阈值                                                         */
/************************************************************************/
int ostu(CvHistogram *Histogram,int HistogramBins)
{
double sum,csum,fmax,sb,m1,m2;
int n,n1,n2,k,threshold_value=160;
n=n1=0;
sum=csum=0.0;
fmax=-1.0;
for (k=0;k<HistogramBins;k++)
{
   sum+=k*cvGetReal1D(Histogram->bins,k);
   n+=cvRound(cvGetReal1D(Histogram->bins,k));
}
if (!n)
{
   return threshold_value;
}
for (k=1;k<HistogramBins;k++)
{
   double val=cvGetReal1D(Histogram->bins,k);
   n1+=cvRound(val);
   if (!n1)
   {
    continue;
   }
   n2=n-n1;
   if (!n2)
   {
    break;
   }
   csum+=k*val;
   m1=csum/n1;
   m2=(sum-csum)/n2;
   sb=n1*n2*(m1-m2)*(m1-m2);
   if (sb>fmax)
   {
    fmax=sb;
    threshold_value=k;
   }
}
return threshold_value;
}



  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值