基於灰度世界、完美反射、動態閾值等圖像自動白平衡算法的原理、實現及效果


     白平衡是電視攝像領域一個非常重要的概念,通過它可以解決色彩還原和色調處理的一系列問題。白平衡是隨着電子影像再現色彩真實而產生的,在專業攝像領域白平衡應用的較早,現在家用電子產品(家用攝像機、數碼照相機)中也廣泛地使用,然而技術的發展使得白平衡調整變得越來越簡單容易,但許多使用者還不甚了解白平衡的工作原理,理解上存在諸多誤區。它是實現攝像機圖像能精確反映被攝物的色彩狀況,有手動白平衡和自動白平衡等方式,本文簡要的介紹了幾種自動白平衡算法。

一、原始的灰度世界算法

  灰度世界算法(Gray World)是以灰度世界假設為基礎的,該假設認為對於一幅有着大量色彩變化的圖像, R、 G、 B 三個分量的平均值趨於同一個灰度K。一般有兩種方法來確定該灰度。

        (1)直接給定為固定值, 取其各通道最大值的一半,即取為127或128;

       (2)令 K = (Raver+Gaver+Baver)/3,其中Raver,Gaver,Baver分別表示紅、 綠、 藍三個通道的平均值。

         算法的第二步是分別計算各通道的增益:

             Kr=K/Raver;

       Kg=K/Gaver;

             Kb=K/Baver;

         算法第三步為根據Von Kries 對角模型,對於圖像中的每個像素R、G、B,計算其結果值:

             Rnew = R * Kr;

       Gnew = G * Kg;

       Bnew = B * Kb;

         對於上式,計算中可能會存在溢出(>255,不會出現小於0的)現象,處理方式有兩種。

         a、 直接將像素設置為255,這可能會造成圖像整體偏白。

         b、 計算所有Rnew、Gnew、Bnew的最大值,然后利用該最大值將將計算后數據重新線性映射到[0,255]內。實踐證明這種方式將會使圖像整體偏暗,建議采用第一種方案。

        一般來說,灰度世界算法的效果還是比較好的呢,並且該算法的執行速度非常之快,目前也存在了不少對該算法進行改進的效果,有時間我在整理一下。

         

         

         

                                     原圖                                                                            處理后的圖

二、完美反射算法

      當初寫這個代碼的時候的一些參考文獻一下子也找不到了,就從已經寫好的代碼中描述下該算法的過程吧。

      原理:完美全反射理論perfect Reflector假設圖像上最亮點就是白點,並以此白點為參考對圖像進行自動白平衡,最亮點定義為R+G+B的最大值,具體編碼步驟如下:

      (1)計算每個像素的R\G\B之和,並保存到一臨時內存塊中。

            for (Y = 0; Y < Height; Y++)
            {
                Pointer = bmp.Pointer + Y * Stride;
                for (X = 0; X < Width; X++)
                {
                    Sum = (short)(*(Pointer) + *(Pointer + 1) + *(Pointer + 2));     // R+G+B
                    HistRGB[Sum]++;
                    *SumP = (short)Sum;
                    Pointer += 3;
                    SumP++;
                }
            }

     (2)按R+G+B值的大小計算出其前10%或其他Ratio的白色參考點的的閾值T。

            for (Y = 767; Y >= 0; Y--)
            {
                Sum += HistRGB[Y];
                if (Sum > Width * Height * Ratio / 100)
                {
                    Threshold = Y;
                    break;
                }
            }

    (3)遍歷圖像中的每個點,計算其中R+G+B值大於T的所有點的R\G\B分量的累積和的平均值。

            for (Y = 0; Y < Height; Y++)
            {
                Pointer = bmp.Pointer + Y * Stride;
                for (X = 0; X < Width; X++)
                {
                    if (*SumP > Threshold)
                    {
                        AvgB += *Pointer;
                        AvgG += *(Pointer + 1);
                        AvgR += *(Pointer + 2);             // 為獲得增益做准備
                        Amount++;
                    }
                    Pointer += 3;
                    SumP++;
                }
            }
            AvgB /= Amount;
            AvgG /= Amount;
            AvgR /= Amount;

   (4)對每個點將像素量化到[0,255]之間。

            for (Y = 0; Y < Height; Y++)
            {
                Pointer = bmp.Pointer + Y * Stride;
                for (X = 0; X < Width; X++)
                {
                    Blue = *Pointer * MaxValue / AvgB;                                   // 另外一種算法需要先計算不抑制重新計算的RGB的范圍,然后求RGB的最大值,如果最大值大於255,則所有的結果都要除以最大值在乘以255,但實際表明該算法、   不合適;
                    Green = *(Pointer + 1) * MaxValue / AvgG;
                    Red = *(Pointer + 2) * MaxValue / AvgR;
                    if (Red > 255) Red = 255; else if (Red < 0) Red = 0;                // 這里需要判斷,因為RGB空間所有的顏色轉換到YCbCr后,並不是填充滿了0-255的范圍的,反轉過去就會存在一些溢出的點。
                    if (Green > 255) Green = 255; else if (Green < 0) Green = 0;        // 編譯后應該比三目運算符的效率高
                    if (Blue > 255) Blue = 255; else if (Blue < 0) Blue = 0;
                    *Pointer = (byte)Blue;
                    *(Pointer + 1) = (byte)Green;
                    *(Pointer + 2) = (byte)Red;
                    Pointer += 3;
                }
            }

        

            

            

                                原圖                                                  Ratio=10%                                            Ratio=2%

    從效果上看,該算法應該比灰度世界的效果要好些,但是也還是受到Ratio這個參數的影像。特別是第二個圖片,過高的Ration導致圖片過於泛白。這個問題可以還是最后量化的哪一步引起的,我會抽空再研究一下其他的量化方式,盡量降低Ration的影響。

    針對上述的第二步,看到很多matlab和VC的代碼,有很多人居然先用快速排序對累加后的數據進行排序,然后再取其10%的最大值,對圖像的數據進行排序,可能就是再快速的排序都快不起來吧,看到這,也許全國人民都笑了。

三、動態閾值算法

      參考論文:A Novel Automatic White Balance Method For Digital Still Cameras

      同經典的一些算法相同,算法分為兩個步驟:白點檢測和白點調整。

      白點檢測:

           (1)為了增強算法的魯棒性,原文將圖像分成12部分,其中寬高比為4:3,關於這一點,我認為不合理,對圖像不是通用的,后文再說。

            (2)計算每個區域的Cb\Cr分量的平均值Mb/Mr

            (3)按下式計算每個區域的Cb\Cr分量的絕對差的累積值Db/Dr

                                 

                                 

                  上式中N為每個區域的像素數。

         (4)如果Db/Dr的值偏小,則我們忽略這一塊,因為這表明這一塊的顏色分布比較均勻,而這樣的局部對於白平衡不好。這個偏小的准則我們稍微再談。

         (5)統計對於除了符合第四條的的其他區域的Mb/Mr/Db/Dr的平均值作為整幅圖像的Mb/Mr/Db/Dr值。

        關於這一條,原文的話是:The final Mb、Mr、Db、Dr are obtained by taking the average of those regions that pass this additional step。

       我在實際中做的時候就是分別對每塊進行的,似乎效果也還不錯。

         (6)按下述規則初步確定哪些點是屬於白色參考點:

                       

                        

         (7)對於初步判斷已經屬於白色參考點的像素,按大小取其亮度值為前10%的位最終確定的白色參考點。

      白點調整:

     (1)計算白色參考點亮度值的平均值Raver,Gaver,Baver,(各通道分開計算)。

          (2)按照以下各式計算每個通道的增益:

             

                       

                      

              式中,Ymax就是YCbCr顏色空間中Y分量的在整幅圖像中的最大值。

          (3)按照以下各式計算最終每個通道的顏色值:

                      

                      

                      

          其中R/G/B為在原始的顏色空間中的值,注意這里要進行溢出檢測的。

        簡單的談下白點檢測的分塊操作吧,原文把圖像分成4*3的12快,這樣做事針對於我們很多數碼照片是這個比例的,如果通用,我覺得應該用每個塊的大小來控制,比如每塊為 100*100個像素。

          這個算法的效果如下:

          

          

          

                           原圖                                              塊大小50*50                    塊大小100*100

      上三圖表明:1、該算法效果非常好;2、對塊大小不太敏感,因此非常適合於自動化操作。

       關於RGB到YCbCr的快速轉換,可以參考:顏色空間系列3: RGB和YCbCr顏色空間的轉換及優化算法 

      由於在上述鏈接的文章中,YCbCr顏色空間已經被轉換到[0,255],因此白色檢測部分的第(6)條中的sign函數就不需要了。

      同樣,提供個編譯好的文件給有興趣研究該算法的朋友看看效果:

      http://files.cnblogs.com/Imageshop/AutoWhiteBalance.zip

   后記:

     針對動態閾值法,很多朋友反映如果YCbCr的值量化在0到255之間的話會出現所有的像素都會被式(6)初步判斷為白色參考點。這樣前期的工作就失去了意義,算法就變成了類似於完美反射算法那了,稍微有點不同的地方就是兩者選擇兩點的准則有所不同。雖然這樣做的最終結果還算不錯,但確實和論文的本意像違背了,后面經過實踐,如果把YCbCr的值量化在-127到128之間,式6中的Sgn同樣適用,則初步判斷為白點的數會大量的減少,對於同一個圖片,同一個參數兩個算法的最終的效果比較如下:

   更新后的下載鏈接依舊如下,以增加了修正后的功能。

          

         

 

 

 ***************************作者: laviewpbt   時間: 2013.4.20    聯系QQ:  33184777  轉載請保留本行信息*************************

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM