背景

最近学习深度学习涉及到了一些HDR图片的读取,HDR全称是High-Dynamic Range,在显示HDR图片的时候,如果不进行色调映射,也就是Tone map的话,那显示出来的HDR图片就会很暗,所以我们需要映射之后再进行显示。

方法

方法1

在现有的论文中,一般会有一个tone map公式,这个公式的描述如下:

利用OpenCV进行Tonemapping_OpenCV

其中Ih是需要tone map的图片,μ是一个压缩的参数,在一般情况下取到5000,这个方法用代码写出来就是下面这样

def tonemapping(pic):
    return np.log(1. + 5000. * pic) / np.log(1. + 5000.)

没有进行tone map前的HDR图:

利用OpenCV进行Tonemapping_pytorch_02

原始HDR图片

可以看到HDR图片拥有很多细节,但是不进行映射的话,更本无法展示出来

利用这个方法进行tone map后的效果如图:

利用OpenCV进行Tonemapping_OpenCV_03

映射后的结果

可以看到图片的细节已经展示了出来,但是这时候也发现了一个问题,图片的颜色偏淡,感觉雾蒙蒙的,这和论文里面经过色调映射后的效果有很大的差别,这时候我就开始寻找怎样进行映射可以展示出图片的细节,同时图片的颜色也尽可能的丰富。

方法2

我在寻找的时候,发现了OpenCV在内部已经实现了几种ToneMap的操作,分别是以下的五种:

cv2.createTonemapDrago()

cv2.createTonemapDurand{}

cv2.createTonemapReinhard{}

cv2.createTonemapMantiuk{}

cv2.createTonemap{}

这几个函数的关系如下:
利用OpenCV进行Tonemapping_JAVA_04

这里参考了https://github.com/spmallick/learnopencv/blob/master/hdr/hdr.py里的tone map代码

# Tonemap using Drago's method to obtain 24-bit color image
print("Tonemaping using Drago's method ... ")
tonemapDrago = cv2.createTonemapDrago(1.0, 0.7)
ldrDrago = tonemapDrago.process(hdrDebevec)
ldrDrago = 3 * ldrDrago
cv2.imwrite("ldr-Drago.jpg", ldrDrago * 255)
print("saved ldr-Drago.jpg")

# Tonemap using Durand's method obtain 24-bit color image
print("Tonemaping using Durand's method ... ")
tonemapDurand = cv2.createTonemapDurand(1.5, 4, 1.0, 1, 1)
ldrDurand = tonemapDurand.process(hdrDebevec)
ldrDurand = 3 * ldrDurand
cv2.imwrite("ldr-Durand.jpg", ldrDurand * 255)
print("saved ldr-Durand.jpg")

# Tonemap using Reinhard's method to obtain 24-bit color image
print("Tonemaping using Reinhard's method ... ")
tonemapReinhard = cv2.createTonemapReinhard(1.5, 0, 0, 0)
ldrReinhard = tonemapReinhard.process(hdrDebevec)
cv2.imwrite("ldr-Reinhard.jpg", ldrReinhard * 255)
print("saved ldr-Reinhard.jpg")

# Tonemap using Mantiuk's method to obtain 24-bit color image
print("Tonemaping using Mantiuk's method ... ")
tonemapMantiuk = cv2.createTonemapMantiuk(2.2, 0.85, 1.2)
ldrMantiuk = tonemapMantiuk.process(hdrDebevec)
ldrMantiuk = 3 * ldrMantiuk
cv2.imwrite("ldr-Mantiuk.jpg", ldrMantiuk * 255)
print("saved ldr-Mantiuk.jpg")

结果如下:

利用OpenCV进行Tonemapping_github_05

createTonemapDrago

利用OpenCV进行Tonemapping_JAVA_06

createTonemapMantiuk

利用OpenCV进行Tonemapping_JAVA_07

createTonemapReinhard

可以看到经过不同的tone map算法,相同的HDR图片可以产生不同的图片,相较于上面的方法一,可以看到颜色会相较方法一会丰富很多

想法

为什么论文里面需要使用方法一这样的tone map方法呢?我的想法是这样,因为方法一是使用在计算Loss前的,GT和预测值都使用同样的的公式,所以这个Tonemap公式的作用其实是让网络的收敛更加的迅速,因为HDR图片的范围是比较窄的,不映射的话计算的Loss就会比较小,网络的收敛也会比较慢,这一点在论文里面也得到了体现。

利用OpenCV进行Tonemapping_OpenCV_08

所以方法一其实主要的作用是让计算更加的有效率,而不是最终展示的作用,那么如果需要将结果进行展示的话,可以使用其他的ToneMap方法或者直接使用OpenCV已经实现好的方法。

最后

如果大家有疑问或者发现我的文章有错误,都欢迎指出~