大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大
原理:
对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。
假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有:
ω1=N1/ M×N (2)
N0+N1=M×N (3)
ω0+ω1=1 (4)
μ=ω0*μ0+ω1*μ1 (5)
g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)
将式(5)代入式(6),得到等价公式:
g=ω0ω1(μ0-μ1)^2 (7) 这就是类间方差
采用遍历的方法得到使类间方差g最大的阈值T,即为所求。
C#代码
/大津法/
/*最大类间方差法是由日本学者大进展之于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。
* 它是按图像的灰度特性,将图像分成背景和目标两部分。背景和目标之间的类间方差越大,说明构成图像的两部分
* 的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小。因此,使类间方差最大的分
* 割意味着错分概率最小。对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图
* 像的比例记为\omega_0 ,,其平均灰度\mu_0;背景像素点数占整幅图像的比例为\omega_1,其平均灰度为\mu_1。
* 图像的总平均灰度记为\mu,类间方差记为g。假设图像的背景较暗,并且图像的大小为M*N,图像中像素的灰度值小
* 于阈值T的像素个数记作N_0,像素灰度大于阈值T的像素个数记作N_1,则有:*/
public static int GetOSTUThreshold(int[] HistGram)
{
int X, Y, Amount = 0;
int PixelBack = 0, PixelFore = 0, PixelIntegralBack = 0, PixelIntegralFore = 0, PixelIntegral = 0;
double OmegaBack, OmegaFore, MicroBack, MicroFore, SigmaB, Sigma; // 类间方差;
int MinValue, MaxValue;
int Threshold = 0;
for (MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++) ;//获取最小灰度的值
for (MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue--) ;//获取最大灰度的值
if (MaxValue == MinValue)
return MaxValue; // 图像中只有一个颜色
if (MinValue + 1 == MaxValue)
return MinValue; // 图像中只有二个颜色
for (Y = MinValue; Y <= MaxValue; Y++)
{
Amount += HistGram[Y]; // 像素总数
}
PixelIntegral = 0;
for (Y = MinValue; Y <= MaxValue; Y++)
{
PixelIntegral += HistGram[Y] * Y;//灰度值总数
}
SigmaB = -1;
for (Y = MinValue; Y < MaxValue; Y++)
{
PixelBack = PixelBack + HistGram[Y]; //前景像素点数
PixelFore = Amount - PixelBack; //背景像素点数
OmegaBack = (double)PixelBack / Amount;//前景像素百分比
OmegaFore = (double)PixelFore / Amount;//背景像素百分比
PixelIntegralBack += HistGram[Y] * Y; //前景灰度值
PixelIntegralFore = PixelIntegral - PixelIntegralBack;//背景灰度值
MicroBack = (double)PixelIntegralBack / PixelBack;//前景灰度百分比
MicroFore = (double)PixelIntegralFore / PixelFore;//背景灰度百分比
Sigma = OmegaBack * OmegaFore * (MicroBack - MicroFore) * (MicroBack - MicroFore);//g
if (Sigma > SigmaB)//遍历最大的类间方差g
{
SigmaB = Sigma;
Threshold = Y;
}
}
return Threshold;
}