OpenCV-最大类间方差(大津法OTSU)实现

一、OTSU算法原理

OTSU(大津法或最大类间方差法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每个部分之间的灰度差异最小,通过方差的计算来寻找一个合适的灰度级别来划分。 所以可以在二值化的时候采用OTSU算法来自动选取阈值进行二值化。OTSU算法被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响。

设t为设定的阈值。

w0 分开后前景像素点数占图像的比例
u0 分开后前景像素点的平均灰度
w1 分开后背景像素点数占图像的比例
u1 分开后背景像素点的平均灰度

 

 

 

 

图像总平均灰度为: u = w0∗u0 + w1∗u1 

 从L个灰度级遍历 t,使得 t 为某个值的时候,前景和背景的方差最大,则 这个 t 值便是我们要求得的阈值。其中,方差的计算公式如下:

 g = wo∗(u0−u)∗(u0−u) + w1∗(u1−u)∗(u1−u) 

此公式计算量较大,可以采用:

 g = w0∗w1∗(u0−u1)∗(u0−u1) 

由于OTSU算法是对图像的灰度级进行聚类,因此在执行OTSU算法之前,可以计算该图像的灰度直方图。


二、代码实现

//OTSU法函数实现
int OTSU(cv::Mat image)
{
	int row = image.rows, col = image.cols;
	//初始化统计参数
	int numPix[256], threshold = 0;
	double nProDis[256];
	for (int i = 0; i < 256; i++) numPix[i] = 0;
	//统计灰度级中各个像素在整幅图像中的个数
	for (int i = 0; i < row; i++)
		for (int j = 0; j < col; j++)
			numPix[(int)image.at(i, j)]++;
	//统计每个弧度级占图像中的概率分布
	for (int i = 0; i < 256; i++) nProDis[i] = (double)numPix[i] / (row*col);
	//遍历灰度级,计算出最大类间方差的阈值
	double w0, w1, u0_temp, u1_temp, u0, u1, delta_temp, delta_max = 0;
	for (int i = 0; i < 256; i++)
	{
		w0 = w1 = u0_temp = u1_temp = delta_temp = 0;
		for (int j = 0; j < 256; j++)
		{
			//背景部分
			if (j <= i)
			{
				//当前i为分割阈值,第一类总的概率
				w0 += nProDis[j];
				u0_temp += j * nProDis[j];
			}
			//前景部分
			else
			{
				//当前i为分割阈值,第一类总的概率
				w1 += nProDis[j];
				u1_temp += j * nProDis[j];
			}
		}
		//分别计算各类的平均灰度值
		u0 = u0_temp / w0;
		u1 = u1_temp / w1;
		delta_temp = (double)(w0*w1*pow((u0 - u1), 2));
		//依次找到最大类间方差下的阈值
		if (delta_temp > delta_max)
		{
			threshold = i;
			delta_max = delta_temp;
		}
	}
	return threshold;
}

运行结果:

OpenCV-最大类间方差(大津法OTSU)实现_第1张图片

你可能感兴趣的:(----opencv学习)