自适应二值化的经典方法------大律法

http://blog.sina.com.cn/s/blog_98ddf7cb0101chu3.html

http://blog.csdn.net/tingfengshr/article/details/2910075

大津法由大津于1979年提出,对图像Image,记t为前景与背景的分割阈值,前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。图像的总平均灰度为:u=w0*u0+w1*u1。从最小灰度值到最大灰度值遍历t,当t使得值g=w0*(u0-u)2+w1*(u1-u)2 最大时t即为分割的最佳阈值。对大津法可作如下理解:该式实际上就是类间方差值,阈值t分割出的前景和背景两部分构成了整幅图像,而前景取值u0,概率为 w0,背景取值u1,概率为w1,总均值为u,根据方差的定义即得该式。因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差别越大, 当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。

直接应用大津法计算量较大,因此我们在实现时采用了等价的公式g=w0*w1*(u0-u1)2。部分计算过程如下:

  1. OpenCV代码:  
  2. int myOtsu(const IplImage *frame) //大津法求阈值   
  3. {  
  4. #define GrayScale 256   //frame灰度级   
  5.     int width = frame->width;  
  6.     int height = frame->height;  
  7.     int pixelCount[GrayScale]={0};  
  8.     float pixelPro[GrayScale]={0};  
  9.     int i, j, pixelSum = width * height, threshold = 0;  
  10.     uchar* data = (uchar*)frame->imageData;  
  11.   
  12.     //统计每个灰度级中像素的个数   
  13.     for(i = 0; i < height; i++)  
  14.     {  
  15.         for(j = 0;j < width;j++)  
  16.         {  
  17.             pixelCount[(int)data[i * width + j]]++;  
  18.         }  
  19.     }  
  20.   
  21.     //计算每个灰度级的像素数目占整幅图像的比例   
  22.     for(i = 0; i < GrayScale; i++)  
  23.     {  
  24.         pixelPro[i] = (float)pixelCount[i] / pixelSum;  
  25.     }  
  26.   
  27.     //遍历灰度级[0,255],寻找合适的threshold   
  28.     float w0, w1, u0tmp, u1tmp, u0, u1, deltaTmp, deltaMax = 0;  
  29.     for(i = 0; i < GrayScale; i++)  
  30.     {  
  31.         w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = 0;  
  32.         for(j = 0; j < GrayScale; j++)  
  33.         {  
  34.             if(j <= i)   //背景部分   
  35.             {  
  36.                 w0 += pixelPro[j];  
  37.                 u0tmp += j * pixelPro[j];  
  38.             }  
  39.             else   //前景部分   
  40.             {  
  41.                 w1 += pixelPro[j];  
  42.                 u1tmp += j * pixelPro[j];  
  43.             }  
  44.         }  
  45.         u0 = u0tmp / w0;  
  46.         u1 = u1tmp / w1;  
  47.         deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)) ;  
  48.         if(deltaTmp > deltaMax)  
  49.         {  
  50.             deltaMax = deltaTmp;  
  51.             threshold = i;  
  52.         }  
  53.     }  
  54.     return threshold;  
  55. }  
posted @ 2017-03-01 19:56  体育.委员  阅读(413)  评论(0编辑  收藏  举报