问题定义
HDR字面意思是高动态范围High Dynamic Range,而动态范围是高图像质量的五个要素之一(其余是1. 分辨率,2.位深度,3.帧速率,4.色域),而画质直接关系到人眼的主观感受。
如果将动态范围理解为量化的阶数,阶数越高,动态范围也越大。人眼看到的自然界内容都是人眼中虹膜 iris的调整,大脑的不断解析,所以可以同时看到各种亮度。而数字图像受限于CCD和ADC,动态范围是有限的,以8bit量化为例,只有256个levels,当同一幅图中同时有高亮和暗部时,如此跨度无法同时表达,就会导致亮度过曝,暗部欠曝。至于胶卷,胶卷相机也不能保证高动态范围,因为暗部细节需要高曝光,亮度细节需要低曝光,而镜头无法保证这样。
解决思路
一般处理的思路是使用多张不同曝光( bexposure bracketing)的照片(提前 registered and aligned.),融合得到HDR图。曝光值 exposure value (EV),也称作stops,高一档表示光线light扩大为2倍。得到不同曝光的方法有改变曝光时间和改变光圈。但是光圈还会影响景深 ,不利于图像对齐等,所以一般都是通过改变曝光时间得到不同ev的图像。
HDR图一般以浮点型float32表示,对应的文件后缀是.hdr。但无耐屏幕的量化水平还是低,为了在8bit机器上也能正常显示,还需要将HDR图使用8bit表示,这一过程称为tonemapping。胶卷时代也有tonemapping,做法是在print阶段,在暗室中使用 dodging and burning。
tonemapping
数字时代的tonemapping会把浮点型的数据转换为[0,1]区间(要求输入输出都在这个区间),这个过程会有截断。匹配场景与显示器之间只是tobemapping的一个应用,tonemapping更广泛的作用是使得图像更加美观,在降低整体对比度的同时保留局部对比度。根据每个像素使用的映射函数是否相同,可以分为全局tonemapping和局部tonemapping。
全局的映射,一旦估计得到最优的函数,每个像素分别单独地被映射,比如颜色反转和对比度降低。常见的全局映射有,将[0,+)映射到[0,1)。低亮的地方对比度被加强,高亮的地方对比度被减弱。常见的还有gamma compression。人眼感受光线和彩色都是非线性的,在更暗的色调下对相对亮度差异的敏感度更高。所以在亮的区域就没有必要浪费太多的比特去描述亮度的变化,这也就是非线性gamma的原理。尽管伽马编码最初是为了补偿阴极射线管 (CRT) 显示器的输入输出特性而开发的,但这并不是其在现代系统中的主要目的或优势。
局部映射,映射算子在每个像素位置都是不同的,会产生光晕halo或者振铃效应,产生的图像比较sharp,但是也可能会得到更好的效果。
OpenCV中的HDR算法1
Debvec和Robertson的算法都需要多张不同曝光图的同时还需要他们各自的曝光时间,通过估计得到camera response function (CRF) ,重建得到.hdr图:
# Merge exposures to HDR image2 merge_debvec = cv2.createMergeDebevec()3 hdr_debvec = merge_debvec.process(img_list, times=exposure_times.copy())4 merge_robertson = cv2.createMergeRobertson()5 hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy())
Robertson这篇1999年的文章,需要 initial calibration, where the camera response function is determined。
很多相机尤其是消费级相机的CRF不是线性的。胶卷对光照的响应就是非线性的,这个曲线辐射带来的,同时需要注意即便没有光照,胶卷也会有较小的响应,而光照太强会造成饱和。此外,冲印,扫描,数字化都会带入非线性。对于数码相机,虽然charge coupled device (CCD)本身是线性的,但是从CCD的输出到写入之前,又有很多的非线性,比如12bit转为8bit,为了显示的考虑使用非线性模拟胶卷等。无论是胶卷还是数码相机,造成非线性最大问题是饱和点的存在。
总而言之就是相机处处都是非线性,是多个非线性的结合composition of several nonlinear mappings,所以需要先将这些非线性以一个函数描述出来。
Z表示位置i,曝光时间索引j处的响应值,可以理解为灰度值,它是已知量。f就是要估计的非线性曲线,假设它是单调递增的,它的自变量是.
上面这个式子经过反函数,取自然对数。可以得到优化函数的data term。第二项是平滑项,是g函数的二阶导,具体可以通过差分的方式实现。这就和拉普拉斯算子一样,我们知道,图像的拉普拉斯算子表示二阶导的过零点,表示边缘信息。最终的优化求解就是线性最小二乘,可以使用SVD求解。
OpenCV中的HDR算法2
当不需要得到.hdr图,只需要有HDR效果的LDR图时,可以使用exposure fusion (Mertens)算法,该算法直接将多曝光的图进行融合,不需要曝光值。融合的过程是使用不同曝光图中可用的部分,这就需要一些指标来衡量图像质量,这里选用的是对比度,饱和度,曝光质量。
对比度的计算使用拉普拉斯滤波器,饱和度的计算使用三个通道的标准差,曝光质量借助高斯曲线。使用乘积的方式将三者联系起来,而不是使用线性的方法。得到权重之后,再归一化就可以融合了。
融合的结果会出现不自然的线条,这是因为权重变化太快,而权重变化太快又是因为图像之间的曝光之间差异较大,绝对强度值差异较大。融合使用的权重图可以使用高斯模糊,也可以使用导向双边滤波,但是效果都不太好。其实这是一个blending问题,可以使用拉普拉斯金字塔进行融合。
reference:
OpenCV: High Dynamic Range (HDR)
OpenCV3.0 HDR(高动态范围)示例代码以及用法 - 一度逍遥 - 博客园
High Dynamic Range Imaging — OpenCV 3.0.0-dev documentation
http://www.pauldebevec.com/Research/HDR/debevec-siggraph97.pdf
Recovering High Dynamic Range Radiance Maps from Photographs