OTSU算法对图像二值化

文章来源:http://blog.csdn.net/WuHaibing_CVer

       OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。
       1. OTSU算法原理简介
       对于一幅图像,设当前景与背景的分割阈值为t时,前景点占图像比例为w0,均值为u0,背景点占图像比例为w1,均值为u1。则整个图像的均值为u = w0*u0+w1*u1。建立目标函数g(t)=w0*(u0-u)^2+w1*(u1-u)^2,g(t)就是当分割阈值为t时的类间方差表达式。OTSU算法使得g(t)取得全局最大值,当g(t)为最大时所对应的t称为最佳阈值。OTSU算法又称为最大类间方差法。
       2.OTSU算法例程
下面是OSTU算法的C语言代码及其测试,代码基于opencv。
 
 
#include <cv.h>
#include <highgui.h>

int otsu(IplImage *image)
{
	assert(NULL != image);

	int width = image->width;
	int height = image->height;
	int x=0,y=0;
	int pixelCount[256];
	float pixelPro[256];
	int i, j, pixelSum = width * height, threshold = 0;

	uchar* data = (uchar*)image->imageData;

	//初始化
	for(i = 0; i < 256; i++)
	{
		pixelCount[i] = 0;
		pixelPro[i] = 0;
	}

	//统计灰度级中每个像素在整幅图像中的个数
	for(i = y; i < height; i++)
	{
		for(j = x;j <width;j++)
		{
			pixelCount[data[i * image->widthStep + j]]++;
		}
	}


	//计算每个像素在整幅图像中的比例
	for(i = 0; i < 256; i++)
	{
		pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
	}

	//经典ostu算法,得到前景和背景的分割
	//遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值
	float w0, w1, u0tmp, u1tmp, u0, u1, u,deltaTmp, deltaMax = 0;
	for(i = 0; i < 256; i++)
	{
		w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;

		for(j = 0; j < 256; j++)
		{
			if(j <= i) //背景部分
			{
				//以i为阈值分类,第一类总的概率
				w0 += pixelPro[j];		
				u0tmp += j * pixelPro[j];
			}
			else       //前景部分
			{
				//以i为阈值分类,第二类总的概率
				w1 += pixelPro[j];		
				u1tmp += j * pixelPro[j];
			}
		}

		u0 = u0tmp / w0;		//第一类的平均灰度
		u1 = u1tmp / w1;		//第二类的平均灰度
		u = u0tmp + u1tmp;		//整幅图像的平均灰度
		//计算类间方差
		deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
		//找出最大类间方差以及对应的阈值
		if(deltaTmp > deltaMax)
		{	
			deltaMax = deltaTmp;
			threshold = i;
		}
	}
	//返回最佳阈值;
	return threshold;
}

int main(int argc, char* argv[])
{
	IplImage* srcImage = cvLoadImage("D:\\technology\\CV\\Database\\image\\rice.png",0);
	assert(NULL != srcImage);

	cvNamedWindow("src");
	cvShowImage("src",srcImage);

	IplImage* biImage = cvCreateImage(cvGetSize(srcImage),8,1);

	//计算最佳阈值
	int threshold = otsu(srcImage);
	//对图像二值化
	cvThreshold(srcImage,biImage,threshold,255,CV_THRESH_BINARY);

	cvNamedWindow("binary");
	cvShowImage("binary",biImage);
	
	cvWaitKey(0);

	cvReleaseImage(&srcImage);
	cvReleaseImage(&biImage);
	cvDestroyWindow("src");
	cvDestroyWindow("binary");

	return 0;
}
下面是上述代码的运行结果图片。其中左边为原图像,右边为使用OTSU算法进行二值化后的图像。

 
 
————————————————————我是分割线————————————————————————
 
以上为转载部分。
以下为另一种表述:
 

OSTU算法目的就是计算出一连通区域的阈值,然后对该区域二值化。

 

数学描述为:令连通区域S,其中象素灰度范围为[0,255],点(x,y)的灰度表示为I(x,y),灰度级x的点的概率为P(x);则OSTU就是求下式达到最大值的灰度级m

 

 

可以证明:

w0*(u0-u)^2+w1*(u1-u)^2与上图公式,这两者是等价的。

 

而显然,第二种方式经过了简化,减少了计算机的工作量,这对于图像处理来说是好的。

 

PS:此算法的简称为OTSU,而很多地方很多论文中均写作OSTU,这是错误的。



 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值