OTSU算法概述 含代码

原文:http://blog.youkuaiyun.com/qinjianganying/article/details/6648700

OTSU一维算法,我自己的理解是自适应阈值分割法,通过对灰度图的处理自行得到一个最佳的阈值,并最后用这个阈值二值化灰度图,参考了商丘师范学院的胡颖老师的<<OTSU算法的改进与纠正>>一文,但是我用的时候效果不是很理想,于是自己进行了稍微的变动,

OTSU算法:就是计算出灰度图最佳阈值的算法

1.先对灰度图进行直方图计算并归一化处理,得到0-255之间每个像素在灰度图中出现的概率,即表示为某个像素在灰度图中出现了n个,灰度图总的像素点为N个,则这个像素的出现概率为Pi=n/N

2.每个灰度图可以由阈值k将灰度图分为A,B两大类,很容易得到A,B类在灰度图中的出现概率以及灰度均值

3.计算灰度图A,B类得类间方差,在最佳阈值K处,求得的类间方差最大,也就是类间方差最大的那个时刻的阈值就为灰度图的最佳阈值

下面结合代码讲解

  1. int ThresholdOtsu(IplImage *src)  
  2. {  
  3.  assert(src->nChannels == 1);  
  4.  float histogram[256] = {0};  
  5.   
  6.  for(int h=0;h<src->height;h++)  
  7.  {  
  8.   unsigned char* p = (unsigned char *)src->imageData +h*src->height;  
  9.    for(int w=0;w<src->width ;w++)  
  10.    {  
  11.     histogram[*p++]++;//计算直方图   
  12.    }  
  13.  }  
  14.   
  15.  int totalpixel = src->width *src->height;  
  16.   
  17.  for(int i=0;i<256;i++)  
  18.     histogram[i] =(float) histogram[i]/(float)totalpixel;//归一化直方图   
  19.   
  20.  float maxavgvalue = 0;  
  21.   
  22.  for(int i=0;i<256;i++)  
  23.   maxavgvalue = i*histogram[i];//总的灰度均值,其实在这里可将其设为0   
  24.   
  25.  float PA = 0;//A类出现概率   
  26.  float PB = 0;//B类出现概率   
  27.  float Agrayvalue = 0;//A类灰度均值   
  28.  float Bgrayvalue = 0;//B类灰度均值   
  29.  float maxvariance = 0;  
  30.  float variance ;  
  31.  int threshold;  
  32.   
  33.  for(int i=0;i<256;i++)  
  34.  {  
  35.         PA += histogram[i];  
  36.   PB = 1-PA;  
  37.   Agrayvalue += i*histogram[i];//A类灰度均值   
  38.   Bgrayvalue += maxavgvalue - Agrayvalue;//B类灰度均值   
  39.   //Agrayvalue = Agrayvalue/PA;   
  40.   //Bgrayvalue = Bgrayvalue/PB;   
  41.         variance = PA*(Agrayvalue-maxavgvalue)*(Agrayvalue-maxavgvalue)+PB*(Bgrayvalue-maxavgvalue)*(Bgrayvalue-maxavgvalue);//计算类间方差   
  42.   
  43.   
  44.    if(variance>maxvariance)  
  45.    {  
  46.     maxvariance = variance;  
  47.     threshold = i;//求得最大类间方差时的像素值,即为最佳阈值   
  48.    }  
  49.      }  
  50.   
  51.  return threshold;//返回最佳阈值二值化图像   
  52.   
  53. }  
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];//总的灰度均值,其实在这里可将其设为0

 float PA = 0;//A类出现概率
 float PB = 0;//B类出现概率
 float Agrayvalue = 0;//A类灰度均值
 float Bgrayvalue = 0;//B类灰度均值
 float maxvariance = 0;
 float variance ;
 int threshold;

 for(int i=0;i<256;i++)
 {
        PA += histogram[i];
  PB = 1-PA;
  Agrayvalue += i*histogram[i];//A类灰度均值
  Bgrayvalue += maxavgvalue - Agrayvalue;//B类灰度均值
  //Agrayvalue = Agrayvalue/PA;
  //Bgrayvalue = Bgrayvalue/PB;
        variance = PA*(Agrayvalue-maxavgvalue)*(Agrayvalue-maxavgvalue)+PB*(Bgrayvalue-maxavgvalue)*(Bgrayvalue-maxavgvalue);//计算类间方差


   if(variance>maxvariance)
   {
    maxvariance = variance;
    threshold = i;//求得最大类间方差时的像素值,即为最佳阈值
   }
     }

 return threshold;//返回最佳阈值二值化图像

}


 

 

将这个算法放入代码中,实现的效果很理想,并且进行形态学运算后效果如下:

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值