如何用tonemapping的作用 解决hdr 的问题

在游戏引擎渲染管线中,我们对于R、G、B通道颜色信息的数值范围通常设置在[0,1]之间(或者是[0,255])。其中,0代表没有光亮度,1代表显示器能够显示的最大光亮度。这个表示方式虽然直接易懂,但它并不能反映真实世界中光亮度的情况。在真实世界的光照环境中,光亮强度有时候会超过显示器能够显示的最大亮度。而且,人眼在观察真实世界的物体时,会根据光照强度进行自我调节。因此,更加真实的渲染方式是让颜色值超过1。这种光照计算方式或环境光照图就是我们常常在游戏引擎中看到的HDR(High Dynamic Range)光照或者HDR环境贴图。但是,采用HDR渲染出来的亮度值会超过显示器能够显示最大值。此时,我们需要将光照结果从HDR转换为显示器能够正常显示的LDR。这一过程我们通常称之为Tone Mapping。下图是Unity引擎对采用HDR渲染的图片使用了Tone Mapping和没有使用Tone Mapping的对比结果:


其中,上图是没有使用Tone Mapping的结果,下图是使用了Tone Mapping的结果。可以看到,在没有使用Tone Mapping的渲染结果中,有很大一部分像素的光亮度是超过了显示器能够显示的最大值。在视觉上,这些地方变得过曝了。而在使用了Tone Mapping的渲染结果中,像素光亮度变得正常,视觉上也更加真实。

今天我们要介绍的这一篇论文是于2002年发表在Siggraph会议上的论文“Photographic Tone Reproduction for Digital Images”。这篇论文提出了一种新的Tone Mapping的方法,使得经过该方法转换的结果从视觉上看起来更加接近真实世界的物体。首先,我们来看看这篇论文的结果图,如下图所示:


其中,左图是采用线性缩放的结果,右图是采用论文中的算法进行转换的结果。可以看到,在简单的线性缩放结果中,许多细节部分丢失了;而论文算法转换的结果则很好地保留了图像的细节部分。接下来,我们将对论文中的算法部分做详细介绍。


首先,文章作者对整个图像做了一个光亮度的映射,其作用类似于设置相机的曝光。这一操作实际就是对每一个像素做固定缩放。根据前人对Tone Mapping的研究结论,论文作者认为光亮度的log平均值能够反映图片中像素光亮度的特征。因此,作者用该值对每个像素作缩放。

若用Lω(x,y)表示像素(x,y)的光亮度,则log平均值可表示为:

其中,N 表示像素个数,δ 是一个用于避免奇异值的常数。缩放后的光亮度 L(x,y) 可用如下公式表示:

其中,α 是一个缩放参数,被称为Key Value,不同的 α 值对应了不同的缩放程度,如下图所示:

但是,仅仅做简单线性缩放是不够的。对于光亮度变化不是很大的图片,这种方法可以将像素的光亮度很好地压缩到一定范围,但是对于大多数图片,绝大部分像素光亮度是在某一个范围之内,而少数高亮的像素比平均值高太多,很容易产生过曝,如:光源、高光反射等。因此,通常在经过线性缩放之后,还需要利用非线性的算子对图像进行处理。文中作者列举了一种常用的算子:

其中,Ld(x,y)表示经过非线性算子处理后的像素,Lwhite表示图片中被映射到白色亮度的像素中的最小值。由于是非线性的,对于亮度高的像素缩放更大,因此该公式能够防止线性缩放中无法处理的过曝情况。但是,这种简单的算子通常容易导致细节丢失。作者观察到,在传统打印技术中,为了提高打印结果的质量,通常会采用一种dodying-and-burning的方法。该方法的原理是根据打印内容的不同,在不同区域减少光亮度(dodying)或者增加光亮度(burning)。论文作者通过实验,对比了简单非线性映射以及dodying-and-burning处理后的结果,如下图所示:

其中,上排图片中太阳被树枝遮挡住,因此不包含高亮的区域,下面的图片则包含高光反射。左边一列图片同样是采用简单非线性算子(Simple Operator)缩放,经过观察可以发现,下图中的书中文字完全被高光覆盖。由此可见,简单的非线性算子缩放会丢失很多细节。

论文作者在经过观察和测试之后,基于dodging-and-burning方法,提出了一种自适应的dodging-and-burning方法,下面我们将详细说明。


自适应dodging-and-burning的特点是,找出对比度大的边缘包围的区域,然后对该区域进行处理。因此,作者提出利用高斯核卷积的方法来找出这些区域。对于不同的缩放系数 s,在不同的像素点(x,y),计算高斯核函数 Ri(x,y,s)与图像 L(x,y)的卷积。则卷积结果 Vi(x,y,s)可表示为:

其中,Ri(x,y,s)可表示为:

然后,论文作者定义了一个误差函数,计算不同 αi 参数的卷积结果之差,来衡量图像局部像素的光亮度分布。则误差函数 V 可以表示为:

通过对不同的缩放参数 s 进行计算,找出符合如下公式的参数:

其中,? 是一个阈值,sm 是对每个像素计算出的缩放参数。当我们获得每一个像素的缩放参数后,对每一个像素进行不同的缩放计算:

从而获得最终的Tone Mapping结果。下图显示了计算过程:

其中,左图显示了计算缩放参数的过程,Center表示内圈高斯计算的范围,Surround表示外圈高斯计算的范围。右图显示了用不同缩放参数进行缩放后的结果。通过观察可以发下,当缩放太小时无法有效地提取出图像细节,而缩放太大时会出现黑色的Artifacts。


论文作者将dodging-and-burning计算结果与前人的结果进行了对比实验。如下图所示:
其中,New operator表示了论文的实现结果。


论文作者提出了一种新的Tone Mapping的算法,它通过对dodging-and-burning打印技术的观察和分析,对于不同的区域采用不同的缩放系数,提出了自适应dodging-and-burning的方法,能够将高动态图转换成低动态图时防止高亮部分过曝,并且能达到在亮部和暗部都能保持细节的目的。


Michael Stark,计算机图形学研究者,曾就读于美国犹他大学;
Peter Shirley,著名计算机图形学大牛,真实感渲染专家,犹他大学客座教授,NVidia首席科学家;
James Ferwerda,著名计算机图形学学者,罗彻斯特理工学院副教授。

这是侑虎科技第225篇原创文章,欢迎转发分享,未经作者授权请勿转载。如果您也有任何独到的见解或者全新的发现也欢迎联系我们,一起探讨。(QQ群)


【惟学无际】是UWA在2017年推出的全新研究型专栏,我们将为大家推荐极具实际价值的学术论文,并梳理其中的研究背景、实现原理和执行方法等。内容专注于游戏、VR和AR相关的计算机图形学领域。正所谓问渠哪得清如许,为有源头活水来 ,希望大家在研发的过程中不仅知其然,还能知其所以然。


}

tone Mapping原是摄影学中的一个术语,因为打印相片所能表现的亮度范围不足以表现现实世界中的亮度域,而如果简单的将真实世界的整个亮度域线性压缩到照片所能表现的亮度域内,则会在明暗两端同时丢失很多细节,这显然不是所希望的效果,Tone Mapping就是为了克服这一情况而存在的,既然相片所能呈现的亮度域有限则我们可以根据所拍摄场景内的整体亮度通过光圈与曝光时间的长短来控制一个合适的亮度域,这样既保证细节不丢失,也可以不使照片失真。人的眼睛也是相同的原理,这就是为什么当我们从一个明亮的环境突然到一个黑暗的环境时,可以从什么都看不见到慢慢可以适应周围的亮度,所不同的是人眼是通过瞳孔来调节亮度域的。


而这个问题同样存在在计算机图形上,为了让图像更真实的显示在显示器上,同样需要Tone Mapping来辅助。
整个Tone Mapping的过程就是首先要根据当前的场景推算出场景的平均亮度,再根据这个平均亮度选取一个合适的亮度域,再将整个场景映射到这个亮度域得到正确的结果。其中最重要的几个参数:
Middle grey:整个场景的平均灰度,关系到场景所应处在亮度域。
Key:场景的Key将决定整个场景的亮度倾向,倾向偏亮亦或是偏暗。
首先我们需要做的是计算出整个场景的平均亮度,有很多种计算平均亮度的方法,目前常用的的是使用log-average亮度来作为场景的平均亮度,通过下面的公式可以计算得到:

其中Lw(x,y)是像素点x,y的亮度,N是场景内的像素数,δ是一个很小的数用来应对像素点纯黑的情况。

上面的公式用来映射亮度域,α即是前面所讲的Key值,用来控制场景的亮度倾向,一般来说,会使用几个特定的值,0.18是一个适中的Key,0.36或者0.72相对偏亮,0.09甚至0.045则是偏暗。完成映射的场景为了满足计算机能显示的范围还要将亮度范围再映射到[0,1]区间,可以通过下面的公式简单的得到[0,1]区间的亮度。

不过这样得到的结果并不总是令人满意的,所以一般扩展为如下面的公式,公式中的参数Lwhite用来控制场景中的曝光,凡是亮度超过Lwhite的像素都会被置为纯白。如果Lwhite的值非常大,则这个参数在公式中将不起任何作用,如果非常小则场景将变为几乎全白。Ld即为我们所要的映射后的x,y像素点的亮度值。

Tone Mapping一般作为HDR算法中的一部分存在,在使用中会灵活很多,但基本的原理都是相同的。

}

我要回帖

更多关于 tonemapping 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信