OTSU一維算法概述

 OTSU一維算法,我自己的理解是自適應閾值分割法,通過對灰度圖的處理自行得到一個最佳的閾值,並最後用這個閾值二值化灰度圖,參考了商丘師範學院的胡穎老師的<<OTSU算法的改進與糾正>>一文,但是我用的時候效果不是很理想,於是自己進行了稍微的變動,

OTSU算法:就是計算出灰度圖最佳閾值的算法

1.先對灰度圖進行直方圖計算並歸一化處理,得到0-255之間每個像素在灰度圖中出現的概率,即表示爲某個像素在灰度圖中出現了n個,灰度圖總的像素點爲N個,則這個像素的出現概率爲Pi=n/N

2.每個灰度圖可以由閾值k將灰度圖分爲A,B兩大類,很容易得到A,B類在灰度圖中的出現概率以及灰度均值

3.計算灰度圖A,B類得類間方差,在最佳閾值K處,求得的類間方差最大,也就是類間方差最大的那個時刻的閾值就爲灰度圖的最佳閾值

下面結合代碼講解

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;//返回最佳閾值二值化圖像

}


 

 

將這個算法放入代碼中,實現的效果很理想,並且進行形態學運算後效果如下:

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章