局部自適應自動色階/對比度算法在圖像加強上的應用。

    在限制對比度自適應直方圖均衡化算法原理、實現及效果一文中針對全局直方圖均衡化的一些缺點,提出了分塊的自適應均衡化技術,很好的克服了全局直方圖均衡化的一些缺點,對於圖像加強也有着顯著的做用,咱們稍微回顧下CLAHE的算法流程,簡單的能夠用下面的過程描述:html

for each Tile in Image 
{
   Calcuate( HistGram);
   ClipHistGram(HistGram, ClipLimit);
   MakeMapping(HistGram);
}
for each Tile in Image 
    for each Pixel in Tile
        use bilinear interpolation between four adjacent HistGram info to generate new Pixel

   原始的直方圖均衡化算法的核心在上述 MakeMapping(HistGram)函數中得以體現,算法

void MakeMapping(int* Histgram)
{
    int I, Sum = 0, Amount = 0;
    for (I = 0; I < 256; I++) Amount += Histgram[I];
    for (I = 0; I < 256; I++)
    {
        Sum += Histgram[I];
        Histgram[I] = Sum * 255/ Amount;     // 計算分佈
    }
}

    上述Histgram[I] = Sum * 255/ Amount;   一句就是HE算法的核心,就直方圖數據從新分佈。app

    咱們回顧一下PS的調整菜單,除了直方圖均衡化是一鍵式菜單(即點擊無可調參數界面,實際上直翻圖均衡化仍是有的,在有選區的狀況下回彈出一個框),還有另外三個經常使用的一鍵操做,即:自動色階、自動對比度以及自動顏色。從本質上講,這三個算法同直方圖均衡化同樣,在內部也是一個直方圖從新分佈和像素從新映射的過程,所以,若是把這裏的MakeMapping函數總映射過程替換他們三者中的某一種會是什麼狀況和效果呢, 這實際上是瞭解了CLAHE算法的原理後,很天然的能拓寬和聯想到的。 函數

     關於自動色階和自動對比度的原理,我在調整圖像- 自動對比度、自動色階算法一文中已經有了較爲詳細的實現,而關於自動顏色的原理,目前爲止我彷佛沒有發現有任何人對其進行了詳細的解釋。我在Imageshop中也只是作了一種簡單的模擬,這裏就不提了。 post

     以自動色階爲例,上述MakeMapping函數的形式可能以下所示:url

void MakeMapping(int* Histgram,float CutLimit=0.01)
{
    int I, Sum = 0, Amount = 0;
    const int Level = 256;
    for (I = 0; I < Level; I++) Amount += Histgram[I];
    int MinB,MaxB;
    for (I = 0; I < Level; I++)
    {
        Sum = Sum + Histgram[I];
        if (Sum >= Amount * CutLimit )
        {
            MinB = I;                              
            break;
        }
    }  
    Sum = 0;
    for(I = Level-1; I >= 0; I--)
    {
        Sum = Sum +Histgram[I];
        if (Sum >= Amount * CutLimit )
        {
            MaxB = I ;                            
            break;
        }   
    }
        
    if (MaxB!=MinB)
    {
        for (I = 0; I < Level; I++)
        {
            if (I<MinB)
                Histgram[I] =0;
            else if(I>MaxB)
                Histgram[I]=255;
            else
                Histgram[I] = 255* (I - MinB) / (MaxB - MinB) ;     
        }
    }
    else
    {
        for (I = 0; I < Level; I++) Histgram[I]=MaxB;        //     必須有,否則會有一些圖像平坦的部位效果出錯
    }
}

  注意在這個函數裏我增長了CutLimit參數,這個參數名和CLAHE的同樣,其實是由於自動色階這種工做方式,就是對直方圖的一種裁剪,所以CLAHE算法的ClipHistGram過程就能夠捨去了,而把CutLimit做爲自動色階的一個調節參數也是順其天然的一個事情了。spa

      在上述代碼代碼中,if (MaxB!=MinB)的判斷主要是防止出現除以0的錯誤,同時在這種狀況發生時,必須把直方圖中的全部數據都設置爲MaxB(其實這種狀況發生時,原始直方圖數據中必然是大部分都等於MaxB,但可能仍是有部分是不一樣的,若是不賦值爲MaxB,處理的結果圖像中會出現莫名其妙的紋理圖)。code

      把上述代碼替換掉CLAHE算法中相應的部分,保持插值等代碼不動,可得到以下效果:htm

         

               原圖                          塊大小爲200,CutLimit =0.01 處理後結果blog

     由上面的圖能夠看出,處理先後的加強效果仍是很明顯的,整個圖像顯得更清晰。

     根據上述代碼分析,這樣處理的效果確定是原先圖像中的黑的部分更黑,白的部分更白,所以,對比度更加宣明。爲了能控制整個對比度調節的程度,咱們新增長一個參數,用來調節在最後隱射階段的最大值。我這裏作了以下的處理:

void MakeMapping(int* Histgram,float CutLimit=0.01,float Contrast = 1)
{
    int I, Sum = 0, Amount = 0;
    const int Level = 256;
    for (I = 0; I < Level; I++) Amount += Histgram[I];
    int MinB =0 ,MaxB=255;
    int Min = 0,Max=255;
    for (I = 0; I < Level; I++)
    {
        if  (Histgram[I]!=0) 
        {
            Min = I ;
            break;
        }
    }

    for(I = Level-1; I >= 0; I--)
    {
        if  (Histgram[I]!=0) 
        {
            Max = I ;
            break;
        }
    }
    for (I = 0; I < Level; I++)
    {
        Sum = Sum + Histgram[I];
        if (Sum >= Amount * CutLimit )
        {
            MinB = I;                              
            break;
        }
    }
  
    Sum = 0;
    for(I = Level-1; I >= 0; I--)
    {
        Sum = Sum +Histgram[I];
        if (Sum >= Amount * CutLimit )
        {
            MaxB = I ;                            
            break;
        }   
    }
    int Delta = (Max - Min) * Contrast * 0.5  ;
    Min = Min - Delta;
    Max = Max +    Delta ;
    if (Min    < 0) Min = 0;
    if (Max > 255) Max = 255;

    if (MaxB!=MinB)
    {
        for (I = 0; I < Level; I++)
        {
            if (I<MinB)
                Histgram[I] =Min;
            else if(I>MaxB)
                Histgram[I]=Max;
            else
                Histgram[I] = (Max-Min)* (I - MinB) / (MaxB - MinB) + Min ;     
        }
    }
    else
    {
        for (I = 0; I < Level; I++) Histgram[I]=MaxB;        //     必須有,否則會有一些圖像平坦的部位效果出錯
    }
}

   首先分析得到原始塊中的最大值和最小值,而後再這個的基礎上按照設定的參數向黑和白兩個方向同等程度擴展,這樣就避免了不管什麼狀況下的分佈都直接擴展到0-255內。有效的抑制了噪音的放大。

  修改後,咱們看看一些效果:

           原圖                      CutLimit =0.01,Contrast=1                    CutLimit =0.05,Contrast=1

    分析:上面這幅圖原始圖像總體就比較亮,所以,在Contrast=1的時候,不少塊調整後的Min=0,Max也等於255了,所以繼續增長Contrast參數,圖像的效果基本沒有什麼變化了。而增長CutLimit值使得圖像的映射表由兩個極端向中間靠攏,圖像會稍微顯得濃烈一些。

       原圖                      CutLimit =0.01,Contrast=1                    CutLimit =0.01,Contrast=2.5    

    而上面這幅圖像,則因爲總體比較暗,增長Contrast的效果就比較明顯了,當Contrast=2.5,圖像頂部的一些細節信息也能清晰的表達出來。

    另外,分析原始代碼的雙線性插值部分可知,在四周邊緣處,特備是離邊緣小於TileX/2或小於TileY/2的部分,因爲其臨近信息的缺失,其實是沒有進行雙線性插值的,這樣對於部分圖像,邊緣處顯得有點不天然,彌補的方式就是在處理前對圖像進行擴展,分別向四周擴展TileX/2和TileY/2大小,固然擴展部分的數據須要按照鏡像的方式填充數據。

    在貼一些這個算法的處理效果:

                                         

      特別是最後一幅圖,處理的效果都要比我博客中其餘的幾種方法來的好,感受真是帥呆了。

      實際中還發現,若是每一個塊的大小過小,處理的速度和效果都會有所降低,太大就至關於全局的處理了,所以,通常狀況下可取將一副圖平均分紅約4*4塊大小的塊大小。同時,調節塊大小時還會出現一些點忽然過亮或過暗的現象,這個問題可能會影響一部分圖的效果。

      用C寫個DLL,並提供了C#調用的實例:http://files.cnblogs.com/Imageshop/AdaptAutoContrastTest.rar

   

    上圖中通道分離選項能夠當作是局部自動色階和自動對比度算法的切換,在勾選通道分離選項時,對於部分圖像會發現有偏色的現象,這個現象在PS中使用自動色階和自動對比度時也會出現。

 

*********************************做者: laviewpbt   時間: 2013.10.29    聯繫QQ:  33184777  轉載請保留本行信息************************

相關文章
相關標籤/搜索