使用 OpenCV 4.0 对 HDR 图像进行色调映射

Ash*_*nCZ 6 python opencv hdr

我想创建一个脚本,它接受一个.HDR文件并将其色调映射到.JPG. 我看过一些OpenCV 教程,似乎应该能够做到这一点。

我写了这个脚本:

import cv2
import numpy as np

filename = "image/gg.hdr"
im = cv2.imread(filename)

cv2.imshow('', im.astype(np.uint8))
cv2.waitKey(0)

tonemapDurand = cv2.createTonemapDurand(2.2)
ldrDurand = tonemapDurand.process(im.copy())

new_filename = filename + ".jpg"
im2_8bit = np.clip(ldrDurand * 255, 0, 255).astype('uint8')
cv2.imwrite(new_filename, ldrDurand)

cv2.imshow('', ldrDurand.astype(np.uint8))
Run Code Online (Sandbox Code Playgroud)

根据教程应该可以工作。不过,我最终得到了一个黑色图像。我已经验证它保存的结果是.JPG,以及输入图像(1.6 兆像素 HDR 环境图)是一个有效的.HDR.

OpenCV 应该能够.HDR根据文档加载s 。

我试过复制链接的教程并且工作正常,所以问题出在.HDR图像上,有人知道该怎么做吗?

谢谢

编辑:我使用了这个 HDR 图像。由于版权等原因,提供链接而不是直接下载。

Dan*_*šek 5

除了两个小错误之外,您几乎就在那里。

第一个错误是使用cv2.imread加载 HDR 图像而不指定任何标志。除非你用 调用它,否则IMREAD_ANYDEPTH数据将被缩小到 8 位,并且你失去了所有的高动态范围。

当您指定时IMREAD_ANYDEPTH,图像将被加载为 32 位浮点格式。这通常具有 [0.0, 1.0] 范围内的强度,但由于是 HDR,这些值超过 1.0(在这种特殊情况下,它们上升到大约 22)。这意味着您无法通过简单地将数据转换为np.uint8. 您也许可以先将其标准化为标称范围,或者使用缩放和剪辑方法……无论您觉得合适。由于早期的可视化与结果无关,我将跳过它。

第二个问题是微不足道的。您正确地缩放色调映射图像并将其剪裁回np.uint8,但是您永远不会使用它。


脚本

import cv2
import numpy as np

filename = "GoldenGate_2k.hdr"
im = cv2.imread(filename, cv2.IMREAD_ANYDEPTH)

tonemapDurand = cv2.createTonemapDurand(2.2)
ldrDurand = tonemapDurand.process(im)

im2_8bit = np.clip(ldrDurand * 255, 0, 255).astype('uint8')

new_filename = filename + ".jpg"
cv2.imwrite(new_filename, im2_8bit)
Run Code Online (Sandbox Code Playgroud)

输出

样本输出