OpenCV-Python 高動態範圍

2020-04-19   人工智慧遇見磐創

目標

在本章中,我們將

  • 了解如何根據曝光順序生成和顯示HDR圖像。
  • 使用曝光融合來合併曝光序列。

理論

高動態範圍成像(HDRI或HDR)是一種用於成像和攝影的技術,可以比標準數字成像或攝影技術重現更大的動態亮度範圍。雖然人眼可以適應各種光照條件,但是大多數成像設備每通道使用8位,因此我們僅限於256級。當我們拍攝現實世界的照片時,明亮的區域可能會曝光過度,而黑暗的區域可能會曝光不足,因此我們無法一次拍攝所有細節。HDR成像適用於每個通道使用8位以上(通常為32位浮點值)的圖像,從而允許更大的動態範圍。

獲取HDR圖像的方法有多種,但是最常見的一種方法是使用以不同曝光值拍攝的場景照片。要綜合這些曝光,了解相機的響應功能以及估算算法的功能非常有用。合併HDR圖像後,必須將其轉換回8位才能在常規顯示器上查看。此過程稱為音調映射。當場景或攝像機的對象在兩次拍攝之間移動時,還會增加其他複雜性,因為應記錄並調整具有不同曝光度的圖像。

在本教程中,我們展示了兩種算法(Debevec,Robertson)來根據曝光序列生成和顯示HDR圖像,並演示了另一種稱為曝光融合(Mertens)的方法,該方法可以生成低動態範圍圖像,並且不需要曝光時間數據。此外,我們估計相機響應函數(CRF)對於許多計算機視覺算法都具有重要價值。HDR流水線的每個步驟都可以使用不同的算法和參數來實現,因此請查看參考手冊以了解所有內容。

曝光序列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長度向量表示。 對於此序列,我們得到以下估計:

附加資源

  1. Paul E Debevec and Jitendra Malik. Recovering high dynamic range radiance maps from photographs. In ACM SIGGRAPH 2008 classes, page 31. ACM, 2008. [48]
  2. Mark A Robertson, Sean Borman, and Robert L Stevenson. Dynamic range improvement through multiple exposures. In Image Processing, 1999. ICIP 99. Proceedings. 1999 International Conference on, volume 3, pages 159–163. IEEE, 1999. [182]
  3. Tom Mertens, Jan Kautz, and Frank Van Reeth. Exposure fusion. In Computer Graphics and Applications, 2007. PG'07. 15th Pacific Conference on, pages 382–390. IEEE, 2007. [148]
  4. Images from Wikipedia-HDR

練習

  1. 嘗試所有色調圖算法:cv::TonemapDrago,cv::TonemapMantiuk和cv::TonemapReinhard
  2. 嘗試更改HDR校準和色調圖方法中的參數。