图像分割中OTSU算法

OTSU算法是图像处理里面一个常用的方法,它主要用来自动的选择一个阈值,以此来对图片进行分割,更好的区别前景区域和背景区域。OTSU方法的思路比较简单,大体如下:

1.  将图像定义为两个部分,前景和背景;

a. 前景(foreground),缩写为fg,其像素个数所占图像的比例为 ,其像素的颜色的均值为

b. 背景(background),缩写为bg,其像素个数所占图像的比例为 ,其像素的颜色的均值为

整体图像的均值为  


2.  建立目标函数

求取最佳阈值t,满足g(t)取得全局最大值,此表达式称为类间方差表达式。


下面给出OTSU算法的代码:

int otsu(const IplImage *src_image)
{
	double sum = 0.0;
	double w0 = 0.0;
	double w1 = 0.0;
	double u0_temp = 0.0;
	double u1_temp = 0.0;
	double u0 = 0.0;
	double u1 = 0.0;
	double u = 0.0;
	double delta_temp = 0.0;
	double delta_max = 0.0;

	int pixel_count[256]={0};	//256个灰度级
	float pixel_pro[256]={0};	//每个灰度级出现的概率
	int threshold = 0;			//所求的最佳临界阈值

	uchar* data = (uchar*)src_image->imageData;
	//统计每个灰度级中像素的个数
	for(int i = 0; i < src_image->height; i++)
	{
		for(int j = 0;j < src_image->width;j++)
		{
			pixel_count[(int)data[i * src_image->width + j]]++;
			sum += (int)data[i * src_image->width + j];
		}
	}

    u = sum / ( src_image->height * src_image->width );

	//计算每个灰度级的像素数目占整幅图像的比例
	for(int i = 0; i < 256; i++)
	{
		pixel_pro[i] = (float)pixel_count[i] / ( src_image->height * src_image->width );
	}

	//遍历灰度级[0,255],寻找合适的threshold
	for(int i = 0; i < 256; i++)
	{
		w0 = w1 = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;
		for(int j = 0; j < 256; j++)
		{
			//i值为当前暂定的阈值,小于i为背景,大于i为前景
			if(j <= i)   //背景部分
			{
				w0 += pixel_pro[j];
				u0_temp += j * pixel_pro[j];
			}
			else   //前景部分
			{
				w1 += pixel_pro[j];
				u1_temp += j * pixel_pro[j];
			}
		}
		u0 = u0_temp / w0;
		u1 = u1_temp / w1;
		u = u0_temp + u1_temp;
		delta_temp = w0 * pow((u0 - u), 2) + w1 * pow((u0 - u), 2);

		if(delta_temp > delta_max)
		{
			delta_max = delta_temp;
			threshold = i;
		}
	}
	return threshold;
}

下面是用OSTU算法的效果,三幅图依次是原图,掩码图,和提取的灰度图

图像分割中OTSU算法_第1张图片

图像分割中OTSU算法_第2张图片



你可能感兴趣的:(opencv基础)