高動態范圍成像


    自然景物的輻照范圍很廣,同樣人眼也可以感知到很大的輻照范圍下的圖像,然而攝像機成像很容易飽和或者曝光不足,所以需要根據拍攝場景來設置合理的快門時間(或者光圈,ISO等參數)。

    盡管通過設置快門時間(或者光圈,ISO等參數)可以得到一幅比較理想的圖像,但仍然可能存在曝光不足或曝光過度的現象。

    高動態范圍成像(High Dynamic Range)通過

    1)拍攝一組不同曝光下的圖像序列,根據已知曝光時間來估計相機的輻射響應函數,

    2)然后將所有像素點映射為輻照值,即得到高動態范圍圖像。

   但是由於顯示設備都是以256階強度顯示圖像,所以需要對高動態范圍圖像進行色調映射以適應顯示設備,色調映射后的圖像應該比不同曝光圖像序列中任意圖像所觀察的動態范圍大。

 

1 圖像對齊

    在拍攝的一組不同曝光圖像序列中,不同圖像間不可避免存在一些位移,如果位移僅有相機抖動引起,可以使用全局平移參數進行描述。由於拍攝內容高度一致,所以可以使用一種簡單方法估計平移,具體如下:

    1)求每幀圖像的中值閾值圖(Median Threshold Bitmap),由於曝光改變並不改變像素值大小關系,所以每幀圖像的中值閾值圖應該具有相同的模式,但可能存在一些位移;

    2)以圖像序列中間幀作為參考,使用圖像金字塔逐次求解每一幀求關於中間幀的全局平移參數;

    opencv 提供了類 AlignMTB 實現了這種情況下的圖像對其,其計算全局平移主要代碼如下:

// 創建圖像金字塔
std::vector<Mat> pyr0; std::vector<Mat> pyr1; buildPyr(img0, pyr0, maxlevel); buildPyr(img1, pyr1, maxlevel);
// 初始平移為0
Point shift(0, 0);
// 自頂而下計算平移量
for(int level = maxlevel; level >= 0; level--) {
shift
*= 2; Mat tb1, tb2, eb1, eb2; computeBitmaps(pyr0[level], tb1, eb1); computeBitmaps(pyr1[level], tb2, eb2); int min_err = (int)pyr0[level].total(); Point new_shift(shift); for(int i = -1; i <= 1; i++) { for(int j = -1; j <= 1; j++) { Point test_shift = shift + Point(i, j); Mat shifted_tb2, shifted_eb2, diff; shiftMat(tb2, shifted_tb2, test_shift); shiftMat(eb2, shifted_eb2, test_shift); bitwise_xor(tb1, shifted_tb2, diff); bitwise_and(diff, eb1, diff); bitwise_and(diff, shifted_eb2, diff); int err = countNonZero(diff); // 非零元越少表示重合程度越高 if(err < min_err) { new_shift = test_shift; min_err = err; } } } shift = new_shift; }

    如果圖像位移由於拍攝場景內部的某些運動引起,則需要描述局部平移,這可以使用稠密光流等方式實現。在光流計算中,一般要求兩幀間圖像亮度變化較小,一種解決方案是在直方圖均衡化后的圖像序列上計算光流。

    結合全局平移與局部光流,可以對圖像進行精確對齊。在HDR應用中,圖像序列均在極短時間內獲取,一般情況只需要計算全局平移即可。

 

2 求相機輻照響應函數

    當成像物體輻照強度不同時,經過相機后會產生不同的像素值,該系統可以用下圖描述

    

    已知像素值,同時知道不同圖像的快門時間,如何估計輻照響應函數呢?大致思路如下:

    對某一固定點 i,假設其輻照強度為 ,不同幀的快門時間為 ,不同幀上固定點 i 的像素值為 ,可建立關系 

    求反函數並取 2 的對數得 ,令  即為需要求解的輻照響應函數(反函數)。

     即建立起一個最優求解方案,其中, 為未知函數, 為未知輻照強度。

    以上為相機輻照強度函數的基本求解思路,在實際實現中,能量函數上添加了一個平滑項以確保曲線平滑性。

    對於像素點的選取,總是利用亮度變化平緩區域,這可以避免梯度變化附近的光暈影響。

    opencv 提供了類 CalibrateDebevec 實現了相機輻照強度函數求解,如果圖像為彩色圖像,則得到3個不同通道的相機輻照函數。

    createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false) 函數創建一個 CalibrateDebevec 對象,

    samples 使用足夠采樣點以獲得一個超定的線性方程,lambda 為平滑像控制系數,random 決定采樣點來自隨機選取還是一個固定的矩形區域。

 

3 合成輻照圖(radiance map)

    理想情況下,根據相機輻照響應函數,使用任意幀的非飽和點就可以求出任意點的輻照值。但真實圖像中存在噪聲干擾,可以使用加權方式求得該點的輻照值。

    

    觀察以上輻照響應函數,在較暗區域或者飽和區域時,其梯度值趨近無窮大(注意,這里自變量為 Z),

    所以可以使用權重  進行加權處理, 

    

    在每個通道上應用不同的相機輻照響應函數即可求得每個點上的輻照值,即構成了 HDR 圖像。

    可使用 opencv 提供的 MergeDebevec 類合成輻照圖,HDR 圖像可以使用不同的格式存儲,包括 .ppm,.hdr,.exr,每種格式對輻照值的表達上限不一致。

 

4 色調映射

    當獲得 HDR 圖像后,我們無法在顯示器上直接顯示結果,所以需要將 HDR 圖像映射為 8 位深度圖像。具體方法如下:

    1)將圖像拆分為亮度通道與色彩通道;

    2)對亮度通道取對數 

    3)在亮度對數函數上應用低通濾波 

    4)亮度對數圖像高頻成分可表示為 

    5)壓縮低頻成分 

    6)形成新亮度對數函數 

    7)指數還原 ,即得到色調映射后結果;

    以上過程中低通濾波器如使用線性濾波(如高斯模糊)可能在圖像邊緣處產生光暈,這是由於線性濾波器不保留邊界,可以使用雙邊濾波器改善光暈。

    雙邊濾波器不僅考慮像素間的位置信息,同時考慮像素間的亮度信息,這就較好的保留了邊緣信息,從而避免邊緣附近的光暈現象。

     

    opencv 在 photo 模塊中提供了 HDR 相關實現,Tonemap 僅使用 gamma 調節,TonemapDrago 與 TonemapReinhard 引入了亮度壓縮,同時可對色彩進行調整。

    以下給出示例圖像:

        

       

 

參考資料   Computer Vision: Algorithms and Applications   Richard Szeliski

                  Recovering High Dynamic Range Radiance Maps from Photographs   Paul E. Debevec &Jitendra Malik


免責聲明!

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



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