在本章中,我們將
高動態範圍成像(HDRI或HDR)是一種用於成像和攝影的技術,可以比標準數字成像或攝影技術重現更大的動態亮度範圍。雖然人眼可以適應各種光照條件,但是大多數成像設備每通道使用8位,因此我們僅限於256級。當我們拍攝現實世界的照片時,明亮的區域可能會曝光過度,而黑暗的區域可能會曝光不足,因此我們無法一次拍攝所有細節。HDR成像適用於每個通道使用8位以上(通常為32位浮點值)的圖像,從而允許更大的動態範圍。
獲取HDR圖像的方法有多種,但是最常見的一種方法是使用以不同曝光值拍攝的場景照片。要綜合這些曝光,了解相機的響應功能以及估算算法的功能非常有用。合併HDR圖像後,必須將其轉換回8位才能在常規顯示器上查看。此過程稱為音調映射。當場景或攝像機的對象在兩次拍攝之間移動時,還會增加其他複雜性,因為應記錄並調整具有不同曝光度的圖像。
在本教程中,我們展示了兩種算法(Debevec,Robertson)來根據曝光序列生成和顯示HDR圖像,並演示了另一種稱為曝光融合(Mertens)的方法,該方法可以生成低動態範圍圖像,並且不需要曝光時間數據。此外,我們估計相機響應函數(CRF)對於許多計算機視覺算法都具有重要價值。HDR流水線的每個步驟都可以使用不同的算法和參數來實現,因此請查看參考手冊以了解所有內容。
在本教程中,我們將查看以下場景,其中有4張曝光圖像,曝光時間分別為15、2.5、1 / 4和1/30秒。 (你可以從Wikipedia下載圖像)
1. 將曝光圖像加載到列表中
import cv2 as cv
import numpy as np
# 將曝光圖像加載到列表中
img_fn = ["img0.jpg", "img1.jpg", "img2.jpg", "img3.jpg"]
img_list = [cv.imread(fn) for fn in img_fn]
exposure_times = np.array([15.0, 2.5, 0.25, 0.0333], dtype=np.float32)
2. 將曝光合成HDR圖像 在此階段,我們將曝光序列合併為一張HDR圖像,顯示了OpenCV中的兩種可能性。 第一種方法是Debevec,第二種方法是Robertson。 請注意,HDR圖像的類型為float32,而不是uint8,因為它包含所有曝光圖像的完整動態範圍。
# 將曝光合成HDR圖像
merge_debevec = cv.createMergeDebevec()
hdr_debevec = merge_debevec.process(img_list, times=exposure_times.copy())
merge_robertson = cv.createMergeRobertson()
hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy())
3. 色調圖HDR圖像 我們將32位浮點HDR數據映射到[0..1]範圍內。實際上,在某些情況下,該值可以大於1或小於0,因此請注意,我們稍後將必須裁剪數據以避免溢出。
# 色調圖HDR圖像
tonemap1 = cv.createTonemap(gamma=2.2)
res_debevec = tonemap1.process(hdr_debevec.copy())
4. 使用Mertens融合曝光 在這裡,我們展示了一種替代算法,用於合併曝光圖像,而我們不需要曝光時間。我們也不需要使用任何色調映射算法,因為Mertens算法已經為我們提供了[0..1]範圍內的結果。
# 使用Mertens融合曝光
merge_mertens = cv.createMergeMertens()
res_mertens = merge_mertens.process(img_list)
5. 轉為8-bit並保存 為了保存或顯示結果,我們需要將數據轉換為[0..255]範圍內的8位整數。
# 轉化數據類型為8-bit並保存
res_debevec_8bit = np.clip(res_debevec*255, 0, 255).astype('uint8')
res_robertson_8bit = np.clip(res_robertson*255, 0, 255).astype('uint8')
res_mertens_8bit = np.clip(res_mertens*255, 0, 255).astype('uint8')
cv.imwrite("ldr_debevec.jpg", res_debevec_8bit)
cv.imwrite("ldr_robertson.jpg", res_robertson_8bit)
cv.imwrite("fusion_mertens.jpg", res_mertens_8bit)
你可以看到不同的結果,但是請考慮到每種算法都有其他額外的參數,你應該將它們附加以達到期望的結果。 最佳實踐是嘗試不同的方法,然後看看哪種方法最適合你的場景。
Debevec:
Robertson:
Mertenes融合
攝像機響應功能(CRF)使我們可以將場景輻射度與測量強度值聯繫起來。CRF在某些計算機視覺算法(包括HDR算法)中非常重要。在這裡,我們估計逆相機響應函數並將其用於HDR合併。
# 估計相機響應函數(CRF)
cal_debevec = cv.createCalibrateDebevec()
crf_debevec = cal_debevec.process(img_list, times=exposure_times)
hdr_debevec = merge_debevec.process(img_list, times=exposure_times.copy(), response=crf_debevec.copy())
cal_robertson = cv.createCalibrateRobertson()
crf_robertson = cal_robertson.process(img_list, times=exposure_times)
hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy(), response=crf_robertson.copy())
相機響應功能由每個顏色通道的256長度向量表示。 對於此序列,我們得到以下估計: