办公室今天停电,幸好本本还有电,同事们好多都去打麻将去了,话说麻将这东西玩起来也还是有味的,不过我感觉我是输了不舒服,赢了替输的人不舒服,所以干脆拜别麻坛四五年了,在办公室一个人整理下好久前的一片论文的思想,和万千世界里有缘人共同分享下资源了。

  论文的名字是<Adaptive Logarithmic Mapping For Displaying High Contrast Scenes>,相关的PDF文档可以在百度上下载到,翻译成中文的意思是一种显示高对比度场景的自适应对数映射算法,也是一篇很古老的算法文章的,看了下好像是2003年的,在Opencv 3.0中已经提供了这个算法的实现了,但是其实现的细节我觉得写的真恶心(我觉得Opencv所有的算法写的都恶心,饶了一堆弯才到算法的中点,感觉大的工程都是这样的),其算法位于OpenCV3.0\opencv\sources\modules\photo\src\tonemap文件中,我在实现这个算法时时参考了另外一个非常有名的开源软件:luminance hdr, 这个软件最新的版本集成了11中用于HDR显示的算法。过完年我要再次好好的看看这个软件的代码了。

  话说回本文的重点,由于对论文的理解不是很深刻,部分内容仅以翻译为主。

  一、应用背景

  简单的说,就是我们认为显示给人眼看的亮度值Ld和场景亮度值Lw之间存在如下的关系:

  其中Lmax为场景的最大亮度,这个映射关系式能够保证无论真实亮度范围有多大,最亮的部分总能映射为1(白色),而其他的亮度也能平缓的变化。虽然这个算式对一些图能获得较为满意的结果,但是我们也发现有些图的亮度压缩太过了,一些高对比度的内容也丢失了。

  二、自适应对数映射

  那么论文提出的色调映射方案遵循了下面几条规则:(1)不管原始数据如何分散,他必须都能输出连续的结果。(2)它应该具有自适应性和可扩展性,他必须能显示出场景的物理本质同时不得引入对比度反转和光晕。总的亮度也必须忠实于实际的内容。(3)算法也需要对用户友好,也就是说在大部分情况下需要能自动实现,少数情况需要调节一些比较直观的参数。

  1、把场景亮度映射到图像亮度

  输出图像的整体亮度主要是由场景的亮度特性决定的,所以找到一个从场景亮度到输出图像亮度之间的初始缩放因子很重要,这就类似于在摄影中曝光设置决定了所拍摄的图片的最终效果一样。现在的镜头都提供的不同的自动曝光选项,比如center- weighted, center-spot以及 matrix-metering等。同样,本文提出两种不同的方法适合于不同的用途。对于静态图片或者当用户不直接和场景交互,我们基于所有像素的亮度信息计算出场景的对数平均值作为初始缩放因子,对于需要交互的场合,缩放因子不是固定值,而是使用亮度的对数信息的高斯模糊后的结果,通常高斯模糊核能覆盖场景的15%范围即可以,当然也可以调整这个范围。

  2、对比度调整

  本文提出的核心的最具特色的色调映射函数就是根据每个像素的信息来自适应的调整函数中的对数基(从2到10)。这从本质上提供了很好的对比度和细节信息,同时能对高亮度值进行很大程度上的压缩。原则上,一个更宽或者更窄的对数基也可以使用,但是实际上,我们没有任何理由去使用它。当对数基小于2时,其值迅速增加,导致曝光调整很困难。另一方面,当对数基大于10时,亮度压缩的量很小,导致这个图片丢失了太多的对比度。同时,我们也观察到了高对数基时的一些颜色偏移现象。

  如下左图所示,左图时基于2对数基的,有图是基于10对数基的(全图),很明显,两幅图的对比度和亮度区别很明显,但是他们都没有给出非常令人满意的结果。

         

  为了实现不同像素不同的对数基以及像素的连续性的要求,我们参考了 Perlin和Hoffert的偏置对数函数,该函数是纹理分析的的标准工具并且在计算机视觉上广为应用。偏置函数定义在单位区间[0,1]之间的power函数,有一个参数b,直接决定了输出值的大小,具体形式如下:

  其曲线如上右图所示。

  2.3 算法细节

  一般数据是基于RGB空间的,我们首先将数据转换到XYZ空间,其中的Y分量反应了每个像素的亮度值。我们首先基于Y分量计算出对数的最大亮度Lwmax和平均亮度Lwa。然后把公式(3)带入公式(1)并做适当的阔啊站,得到最终的计算显示亮度的公式如下所示:

    

  相比于论文,上述公式后半部分是我自己添加上去的,主要是为了解释方便。

  我们首先看下算式中的,很明显,他的取值范围是2到10之间,这和论文前面的描述是一致的。然后底部的Log10也保证了整个算式的区间范围。

  然后我们知道,对数计算式有如下特性:    

       

  因此把公式(4)的后半部分展开就到了论文的结果。

  式中有多了个参数Ldmax,这个值表示显示设备的最大显示能力,对于普通的CRT显示器,我们直接取值为100。

  论文后面还有关于Gamma校正的内容,那些都是辅助的了,实际上没啥意思,论文核心的就是上述公式。

  三:具体实现即细节注意:

  具体实现代码可以完美的参考luminance hdr,关键是要注意一些数据的范围要映射到0和1之间才能处理,特别是论文有些地方其实没有讲的特别清晰,比如在论文里有这样一句话:The XYZ luminance component Y of each pixel (Lw for world luminance) and the maximum luminance of the scene Lwmax are divided by the world adaptation luminance Lwa and eventually multiplied by an exposure factor set by the user。这里其实没有明确的说Lwa是什么(整篇论文都没有说)其实就是上面讲的对数平均值,还有最后直接用公式计算得到的Ld一般情况下是很小的,如何处理让其显示也是值得讲究的。我这里贴出对公式(4)计算的核心代码:

void ComputeScaleTable(float ScaleTable[], float Bias, float Saturation, float MaxLum, float AvLum)
{
float Divider, BiasP, NormalY, Interpol, NewLum;
MaxLum = MaxLum / AvLum; // normalize maximum luminance by average luminance(divided by the world adaptation luminance Lwa)
Divider = log10f(MaxLum + 1.0f); // 论文公式(4)左半部分的除数
BiasP = logf(Bias) / log(0.5); // 公式(3)中的上指标 for (int Index = ; Index < ; Index++) // Normal tone mapping of every pixel
{
// The XYZ luminance component Y of each pixel (Lw for world luminance) and the maximum luminance of the scene
// Lwmax are divided by the world adaptation luminance Lwa and eventually multiplied by an exposure factor set by the user.
NormalY = (Index / 255.0) / AvLum; // divided by the world adaptation luminance Lwa
Interpol = logf(2.0f + powf(NormalY / MaxLum, BiasP) * 8.0f); // 论文公式(4)右半部分的除数
NewLum = (logf(NormalY + 1.0f) / Interpol) / Divider; // 论文公式(4)
ScaleTable[Index] = powf(NewLum / (Index / 255.0 + 1e-), Saturation);
}
}  

  以上代码是针对8位图像的,上面的/255.0就是归一化到[0,1]范围的作用。但是最后一行的NewLum / (Index / 255.0 + 1e-4)你们能理解是什么意思吗?

  最后一行代码的Saturation的作用见<Gradient domain high dynamic range compression>一文,当大于1时,图像越饱和也越亮,小于1是图像变暗。

  虽然论文描述的算法本意是用到HDR这种高动态范围的图像的,但是实际上我目前也只实现了8位的LDR的代码,但是对于8位的图像,特别是偏暗的图像还是有很好的增强的效果的,对于正常的图像,一般也不会出现特别不好的效果。

   

   

  对于常态的图片,一般也能起到一定的视觉增强效果:

  

  关于速度优化方面,如果是针对8位图像,则中间的很多浮点计算可以用查表代替,而XYZ和RGB空间转化,我前面一篇博客已经提到可以用SSE快速实现。处理1080P的图大概需要20ms。

  也曾尝试不转到XYZ空间,直接提取出亮度信息,然后直接在RGB空间处理,似乎效果也还可以,但是有可能会出现较多的偏色。

  明年有时间把这个算法扩展到16位图像上取看看,有什么效果。

  8位测试工程:https://files.cnblogs.com/files/Imageshop/TonemapDrago.rar

  

Tone Mapping算法系列二:一种自适应对数映射的高对比度图像显示技术及其速度优化。的更多相关文章

  1. Tone Mapping算法系列一:基于Fast Bilateral Filtering 算法的 High-Dynamic Range(HDR) 图像显示技术。

    一.引言 本人初次接触HDR方面的知识,有描述不正确的地方烦请见谅. 为方便文章描述,引用部分百度中的文章对HDR图像进行简单的描述. 高动态范围图像(High-Dynamic Range,简称HDR ...

  2. [论文阅读] ALM-HCS(高对比场景自适应对数映射)

    [论文阅读] ALM-HCS(高对比场景自适应对数映射) 文章: Adaptive Logarithmic Mapping for Displaying High Contrast Scenes 1. ...

  3. 基于Fast Bilateral Filtering 算法的 High-Dynamic Range(HDR) 图像显示技术。

    一.引言 本人初次接触HDR方面的知识,有描述不正确的地方烦请见谅. 为方便文章描述,引用部分百度中的文章对HDR图像进行简单的描述. 高动态范围图像(High-Dynamic Range,简称HDR ...

  4. SSE图像算法优化系列二十:一种快速简单而又有效的低照度图像恢复算法。

    又有很久没有动笔了,主要是最近没研究什么东西,而且现在主流的趋势都是研究深度学习去了,但自己没这方面的需求,同时也就很少有动力再去看传统算法,今天一个人在家,还是抽空分享一个简单的算法吧. 前段日子在 ...

  5. Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解

    Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全   Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...

  6. SSE图像算法优化系列二十二:优化龚元浩博士的曲率滤波算法,达到约1000 MPixels/Sec的单次迭代速度

      2015年龚博士的曲率滤波算法刚出来的时候,在图像处理界也曾引起不小的轰动,特别是其所说的算法的简洁性,以及算法的效果.执行效率等方面较其他算法均有一定的优势,我在该算法刚出来时也曾经有关注,不过 ...

  7. java讲讲几种常见的排序算法(二)

    java讲讲几种常见的排序算法(二) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 堆排序 思路:构建一个小顶堆,小顶堆就是棵二叉树,他的左右孩子均大于他的根节点( ...

  8. 基于物理的渲染—HDR Tone Mapping

    在游戏引擎渲染管线中,我们对于R.G.B通道颜色信息的数值范围通常设置在[0,1]之间(或者是[0,255]).其中,0代表没有光亮度,1代表显示器能够显示的最大光亮度.这个表示方式虽然直接易懂,但它 ...

  9. 图机器学习(GML)&图神经网络(GNN)原理和代码实现(前置学习系列二)

    项目链接:https://aistudio.baidu.com/aistudio/projectdetail/4990947?contributionType=1 欢迎fork欢迎三连!文章篇幅有限, ...

随机推荐

  1. PHP算法排序之快速排序、冒泡排序、选择排序、插入排序性能对比

    <?php //冒泡排序 //原理:从倒数第一个数开始,相邻的两个数比较,后面比前面的小,则交换位置,一直到比较第一个数之后则最小的会排在第一位,以此类推 function bubble_sor ...

  2. Java基础总结02:环境变量的配置

    (一)Windows系统下配置环境变量 ※在"系统变量"中设置3项属性JAVA_HOME.PATH.CLASSPATH(JDK1.5之后此项属性不必再配),若已存在则点击" ...

  3. hive参数配置及任务优化

    一.hive常用参数 0.常用参数 --@Name: --@Description: --@Type:全量加载 --@Author:--- --@CreateDate: --@Target: --@S ...

  4. NN:神经网络算法进阶优化法,进一步提高手写数字识别的准确率—Jason niu

    上一篇文章,比较了三种算法实现对手写数字识别,其中,SVM和神经网络算法表现非常好准确率都在90%以上,本文章进一步探讨对神经网络算法优化,进一步提高准确率,通过测试发现,准确率提高了很多. 首先,改 ...

  5. Visual Studio 2015开发Qt项目实战经验分享(附项目示例源码)

    Visual Studio 2015开发Qt项目实战经验分享(附项目示例源码)    转 https://blog.csdn.net/lhl1124281072/article/details/800 ...

  6. Hibernate中报错org.hibernate.HibernateException: No CurrentSessionContext configured!

    报错信息如下: 解决方法: 问题原因是getCurrentSession()出现了问题 在hibernate.cfg.xml(hibernate的核心配置文件)文件中加入下列代码: <prope ...

  7. poj 3067 Japan 【树状数组】

    <题目链接> 题目大意: 有两个点集,这两个点集从上至下分别从1~n,1~m编号,现在给出n组数据,(x,y),表示左边点集编号为x的点与右边点集编号为y的点相连,现在要求计算这些线段的交 ...

  8. P2415 集合求和

    P2415 集合求和显然,一共有2^n个子集,对于其中的一个确定的元素,它不在的集合有2^(n-1),相当于有n-1元素,那么它存在的集合有,2^n-2^(n-1)==2^(n-1),那么集合的和为s ...

  9. 【java并发核心八】Fork-Join分治编程

    jdk1.7中提供了Fork/Join并行执行任务框架,主要作用就是把大任务分割成若干个小任务,再对每个小任务得到的结果进行汇总. 正常情况下,一些小任务我们可以使用单线程递归来实现,但是如果要想充分 ...

  10. win 2012 安装Net35

    使用 PowerShell, 指定源文件路径然后进行安装: Install-WindowsFeature NET-Framework-Core –Source D:\Sources\sxs 使用命令提 ...