Kittler二值化方法,是一种经典的基于直方图的二值化方法。由J. Kittler在1986年发表的论文“Minimum Error Thresholding”提出。论文是对贝叶斯最小错误阈值的准则做了改进,使得计算更加的简单和有效。
Divijver 和 Kittler的贝叶斯最小错误准则为:
因为需要求解二次方程和对正态分布的均值和方差进行估计,Nagawa 和 Rosenfeld提出了求解和估计的方法(Some Experiments on Variable Thresholding)。但他们的方法计算式很耗时的。作者做了一个修改,从而得到了计算更简单的准则函数。假设已知直方图h, 则通过以下目标函数寻找最优为:
,
其中
该方法对于双峰的图像,双峰差别特别大的图像有很好的分割效果,这样的的场景在工业视觉中的零部件中常常遇到。如打光部件后是很容易形成双波峰的,这样该方法的分割往往会得到很好的效果,下面的实验也说明该方法在这类场景中是要更优于大津法和一维最大熵法的。
论文中还提到了一种变化阈值的求解办法。其思想是:首先将图像割成大小一样的小块(patch),然后对每个小块都使用论文所提到的方法计算得到一个局部(相对于整幅图片)的阈值,接着用双边插值法对计算得到的阈值进行插值,从而得到了每个像素点的二值化分割阈值。文中对一个工业器件进行分割,并给出了效果图:
代码实现参考了ImageShop提供的C#版本(http://www.cnblogs.com/Imageshop/p/3307308.html),做了简单修改得到了C++版本,代码如下:
/*灰度图像的二值化方法*/
class CxThreshold { public: static int CalcKittlerMinError(int* HistGram) { int X, Y; int MinValue, MaxValue; int Threshold ; long PixelBack, PixelFore; double OmegaBack, OmegaFore, MinSigma, Sigma, SigmaBack, SigmaFore; 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; // 图像中只有二个颜色 Threshold = -1; MinSigma = 1E+20; for (Y = MinValue; Y < MaxValue; Y++){ PixelBack = 0; PixelFore = 0; OmegaBack = 0; OmegaFore = 0; for (X = MinValue; X <= Y; X++){ PixelBack += HistGram[X]; OmegaBack = OmegaBack + X * HistGram[X]; } for (X = Y + 1; X <= MaxValue; X++){ PixelFore += HistGram[X]; OmegaFore = OmegaFore + X * HistGram[X]; } OmegaBack = OmegaBack / PixelBack; OmegaFore = OmegaFore / PixelFore; SigmaBack = 0; SigmaFore = 0; for (X = MinValue; X <= Y; X++) SigmaBack = SigmaBack + (X - OmegaBack) * (X - OmegaBack) * HistGram[X]; for (X = Y + 1; X <= MaxValue; X++) SigmaFore = SigmaFore + (X - OmegaFore) * (X - OmegaFore) * HistGram[X]; if (SigmaBack == 0 || SigmaFore == 0){ if (Threshold == -1)Threshold = Y; } else{ SigmaBack = sqrt(SigmaBack / PixelBack); SigmaFore = sqrt(SigmaFore / PixelFore); //Sigma = 1 + 2 * (PixelBack * log(SigmaBack / PixelBack) + PixelFore * log(SigmaFore / PixelFore)); Sigma = PixelBack * log(SigmaBack / PixelBack) + PixelFore * log(SigmaFore / PixelFore) - PixelBack * log( PixelBack) - PixelFore* log(PixelFore); if (Sigma < MinSigma){ MinSigma = Sigma; Threshold = Y; } } } return Threshold; } };
实验不同算法的效果:
kettler法,获得最佳的分割效果,纽扣完整性最好。
大津法,对纽扣亮色部分分割不好。
一维最大熵法。获得了最差的效果,纽扣完整性不好。对和白色接近的颜色分割较差。