OTSU一维算法,我自己的理解是自适应阈值分割法,通过对灰度图的处理自行得到一个最佳的阈值,并最后用这个阈值二值化灰度图,参考了商丘师范学院的胡颖老师的<<OTSU算法的改进与纠正>>一文,但是我用的时候效果不是很理想,于是自己进行了稍微的变动,
OTSU算法:就是计算出灰度图最佳阈值的算法
1.先对灰度图进行直方图计算并归一化处理,得到0-255之间每个像素在灰度图中出现的概率,即表示为某个像素在灰度图中出现了n个,灰度图总的像素点为N个,则这个像素的出现概率为Pi=n/N
2.每个灰度图可以由阈值k将灰度图分为A,B两大类,很容易得到A,B类在灰度图中的出现概率以及灰度均值
3.计算灰度图A,B类得类间方差,在最佳阈值K处,求得的类间方差最大,也就是类间方差最大的那个时刻的阈值就为灰度图的最佳阈值
最大类间方差法(otsu)的原理:
阈值将原图象分成前景,背景两个图象。
前景:用n1,csum,
m1来表示在当前阈值下的前景的点数,质量矩,平均灰度
后景:用n2, sum-csum, m2来表示在当前阈值下的背景的点数,质量矩,平均灰度
当取最佳阈值时,背景应该与前景差别最大,关键在于如何选择衡量差别的标准
而在otsu算法中这个衡量差别的标准就是最大类间方差(英文简称otsu,这也就是这个算法名字的来源)
在本程序中类间方差用sb表示,最大类间方差用fmax
关于最大类间方差法(otsu)的性能:
类间方差法对噪音和目标大小十分敏感,它仅对类间方差为单峰的图像产生较好的分割效果。
当目标与背景的大小比例悬殊时,类间方差准则函数可能呈现双峰或多峰,此时效果不好,但是类间方差法是用时最少的。
最大最大类间方差法(otsu)的公式推导:
记t为前景与背景的分割阈值,前景点数占图像比例为w0, 平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。
则图像的总平均灰度为:u=w0*u0+w1*u1。
前景和背景图象的方差:g=w0*(u0-u)*(u0-u)+w1*(u1-u)*(u1-u)=w0*w1*(u0-u1)*(u0-u1),此公式为方差公式,可参照概率论课本
下面结合代码讲解
- int ThresholdOtsu(IplImage *src)
- {
- assert(src->nChannels == 1);
- float histogram[256] = {0};
-
- for(int h=0;h<src->height;h++)
- {
- unsigned char* p = (unsigned char *)src->imageData +h*src->height;
- for(int w=0;w<src->width ;w++)
- {
- histogram[*p++]++;
- }
- }
-
- int totalpixel = src->width *src->height;
-
- for(int i=0;i<256;i++)
- histogram[i] =(float) histogram[i]/(float)totalpixel;
-
- float maxavgvalue = 0;
-
- for(int i=0;i<256;i++)
- maxavgvalue = i*histogram[i];
-
- float PA = 0;
- float PB = 0;
- float Agrayvalue = 0;
- float Bgrayvalue = 0;
- float maxvariance = 0;
- float variance ;
- int threshold;
-
- for(int i=0;i<256;i++)
- {
- PA += histogram[i];
- PB = 1-PA;
- Agrayvalue += i*histogram[i];
- Bgrayvalue += maxavgvalue - Agrayvalue;
-
-
- variance = PA*(Agrayvalue-maxavgvalue)*(Agrayvalue-maxavgvalue)+PB*(Bgrayvalue-maxavgvalue)*(Bgrayvalue-maxavgvalue);
-
-
- if(variance>maxvariance)
- {
- maxvariance = variance;
- threshold = i;
- }
- }
-
- return threshold;
-
- }