Tone Mapping算法系列二:一種自適應對數映射的高對比度圖像顯示技術及其速度優化。

  辦公室今天停電,幸虧本本還有電,同事們好多都去打麻將去了,話說麻將這東西玩起來也仍是有味的,不過我感受我是輸了不舒服,贏了替輸的人不舒服,因此乾脆拜別麻壇四五年了,在辦公室一我的整理下很久前的一片論文的思想,和萬千世界裏有緣人共同分享下資源了。算法

  論文的名字是<Adaptive Logarithmic Mapping For Displaying High Contrast Scenes>,相關的PDF文檔能夠在百度上下載到,翻譯成中文的意思是一種顯示高對比度場景的自適應對數映射算法,也是一篇很古老的算法文章的,看了下好像是2003年的,在Opencv 3.0中已經提供了這個算法的實現了,可是其實現的細節我以爲寫的真噁心(我以爲Opencv全部的算法寫的都噁心,饒了一堆彎纔到算法的中點,感受大的工程都是這樣的),其算法位於OpenCV3.0\opencv\sources\modules\photo\src\tonemap文件中,我在實現這個算法時時參考了另一個很是有名的開源軟件:luminance hdr, 這個軟件最新的版本集成了11中用於HDR顯示的算法。過完年我要再次好好的看看這個軟件的代碼了。app

  話說回本文的重點,因爲對論文的理解不是很深入,部份內容僅以翻譯爲主。dom

  1、應用背景ide

  簡單的說,就是咱們認爲顯示給人眼看的亮度值Ld和場景亮度值Lw之間存在以下的關係:函數

                                         

  其中Lmax爲場景的最大亮度,這個映射關係式可以保證不管真實亮度範圍有多大,最亮的部分總能映射爲1(白色),而其餘的亮度也能平緩的變化。雖然這個算式對一些圖能得到較爲滿意的結果,可是咱們也發現有些圖的亮度壓縮太過了,一些高對比度的內容也丟失了。工具

  2、自適應對數映射測試

  那麼論文提出的色調映射方案遵循了下面幾條規則:(1)無論原始數據如何分散,他必須都能輸出連續的結果。(2)它應該具備自適應性和可擴展性,他必須能顯示出場景的物理本質同時不得引入對比度反轉和光暈。總的亮度也必須忠實於實際的內容。(3)算法也須要對用戶友好,也就是說在大部分狀況下須要能自動實現,少數狀況須要調節一些比較直觀的參數。優化

  一、把場景亮度映射到圖像亮度ui

  輸出圖像的總體亮度主要是由場景的亮度特性決定的,因此找到一個從場景亮度到輸出圖像亮度之間的初始縮放因子很重要,這就相似於在攝影中曝光設置決定了所拍攝的圖片的最終效果同樣。如今的鏡頭都提供的不一樣的自動曝光選項,好比center- weighted, center-spot以及 matrix-metering等。一樣,本文提出兩種不一樣的方法適合於不一樣的用途。對於靜態圖片或者當用戶不直接和場景交互,咱們基於全部像素的亮度信息計算出場景的對數平均值做爲初始縮放因子,對於須要交互的場合,縮放因子不是固定值,而是使用亮度的對數信息的高斯模糊後的結果,一般高斯模糊核能覆蓋場景的15%範圍便可以,固然也能夠調整這個範圍。spa

  二、對比度調整

  本文提出的核心的最具特點的色調映射函數就是根據每一個像素的信息來自適應的調整函數中的對數基(從2到10)。這從本質上提供了很好的對比度和細節信息,同時能對高亮度值進行很大程度上的壓縮。原則上,一個更寬或者更窄的對數基也可使用,可是實際上,咱們沒有任何理由去使用它。當對數基小於2時,其值迅速增長,致使曝光調整很困難。另外一方面,當對數基大於10時,亮度壓縮的量很小,致使這個圖片丟失了太多的對比度。同時,咱們也觀察到了高對數基時的一些顏色偏移現象。

  以下左圖所示,左圖時基於2對數基的,有圖是基於10對數基的(全圖),很明顯,兩幅圖的對比度和亮度區別很明顯,可是他們都沒有給出很是使人滿意的結果。

                     

   爲了實現不一樣像素不一樣的對數基以及像素的連續性的要求,咱們參考了 Perlin和Hoffert的偏置對數函數,該函數是紋理分析的的標準工具而且在計算機視覺上廣爲應用。偏置函數定義在單位區間[0,1]之間的power函數,有一個參數b,直接決定了輸出值的大小,具體形式以下:

                                 

  其曲線如上右圖所示。

  2.3 算法細節

  通常數據是基於RGB空間的,咱們首先將數據轉換到XYZ空間,其中的Y份量反應了每一個像素的亮度值。咱們首先基於Y份量計算出對數的最大亮度Lwmax和平均亮度Lwa。而後把公式(3)帶入公式(1)並作適當的闊啊站,獲得最終的計算顯示亮度的公式以下所示:

    

  相比於論文,上述公式後半部分是我本身添加上去的,主要是爲了解釋方便。

  咱們首先看下算式中的,很明顯,他的取值範圍是2到10之間,這和論文前面的描述是一致的。而後底部的Log10也保證了整個算式的區間範圍。

  而後咱們知道,對數計算式有以下特性:    

       

   所以把公式(4)的後半部分展開就到了論文的結果。

  式中有多了個參數Ldmax,這個值表示顯示設備的最大顯示能力,對於普通的CRT顯示器,咱們直接取值爲100。

  論文後面還有關於Gamma校訂的內容,那些都是輔助的了,實際上沒啥意思,論文核心的就是上述公式。

  三:具體實現即細節注意:

  具體實現代碼能夠完美的參考luminance hdr,關鍵是要注意一些數據的範圍要映射到0和1之間才能處理,特別是論文有些地方其實沒有講的特別清晰,好比在論文裏有這樣一句話:The XYZ luminance component Y of each pixel (Lw for world luminance) and the maximum luminance of the scene Lwmax are divided by the world adaptation luminance Lwa and eventually multiplied by an exposure factor set by the user。這裏其實沒有明確的說Lwa是什麼(整篇論文都沒有說)其實就是上面講的對數平均值,還有最後直接用公式計算獲得的Ld通常狀況下是很小的,如何處理讓其顯示也是值得講究的。我這裏貼出對公式(4)計算的核心代碼:

void ComputeScaleTable(float ScaleTable[], float Bias, float Saturation, float MaxLum, float AvLum)
{
    float Divider, BiasP, NormalY, Interpol, NewLum;
    MaxLum = MaxLum / AvLum;                    //    normalize maximum luminance by average luminance(divided by the world adaptation luminance Lwa)
    Divider = log10f(MaxLum + 1.0f);            //    論文公式(4)左半部分的除數
    BiasP = logf(Bias) / log(0.5);                //    公式(3)中的上指標    

    for (int Index = 0; Index < 256; Index++)    // Normal tone mapping of every pixel
    {
        //        The XYZ luminance component Y of each pixel (Lw for world luminance) and the maximum luminance of the scene
        //        Lwmax are divided by the world adaptation luminance Lwa and eventually multiplied by an exposure factor set by the user.
        NormalY = (Index / 255.0) / AvLum;                                            //        divided by the world adaptation luminance Lwa
        Interpol = logf(2.0f + powf(NormalY / MaxLum, BiasP) * 8.0f);                //        論文公式(4)右半部分的除數
        NewLum = (logf(NormalY + 1.0f) / Interpol) / Divider;                        //        論文公式(4)
        ScaleTable[Index] = powf(NewLum / (Index / 255.0 + 1e-4), Saturation);
    }
}  

  以上代碼是針對8位圖像的,上面的/255.0就是歸一化到[0,1]範圍的做用。可是最後一行的NewLum / (Index / 255.0 + 1e-4)大家能理解是什麼意思嗎?

  最後一行代碼的Saturation的做用見<Gradient domain high dynamic range compression>一文,當大於1時,圖像越飽和也越亮,小於1是圖像變暗。

  雖然論文描述的算法本意是用到HDR這種高動態範圍的圖像的,可是實際上我目前也只實現了8位的LDR的代碼,可是對於8位的圖像,特別是偏暗的圖像仍是有很好的加強的效果的,對於正常的圖像,通常也不會出現特別很差的效果。

     

     

   對於常態的圖片,通常也能起到必定的視覺加強效果:

     

   關於速度優化方面,若是是針對8位圖像,則中間的不少浮點計算能夠用查表代替,而XYZ和RGB空間轉化,我前面一篇博客已經提到能夠用SSE快速實現。處理1080P的圖大概須要20ms。

  也曾嘗試不轉到XYZ空間,直接提取出亮度信息,而後直接在RGB空間處理,彷佛效果也還能夠,可是有可能會出現較多的偏色。

  明年有時間把這個算法擴展到16位圖像上取看看,有什麼效果。

  8位測試工程:https://files.cnblogs.com/files/Imageshop/TonemapDrago.rar

相關文章
相關標籤/搜索