最近受朋友的委托,想自己实现Matlab里的一个HDR转LDR的函数,函数名是tonemapfarbman,乘着十一假期,稍微浏览下这个函数,并做了一点C++的实现和优化。
为了看到这个函数的效果,需要至少matlab R2018b及其以上的版本。
首先,我们下载了matlab帮助文档中提到的该算法对应的论文:Edge-Preserving Decompositions for Multi-Scale Tone and Detail Manipulation.
通读了下这个论文,感觉他并没有提出一个什么具体的算法,而是一个大的框架,其最有用的部分为 3.1 Multi-scale edge-preserving decompositions。

这个意思呢,就是用某一种保边滤波器进行K+1层次的分解,但是分解是依次的,这K+1次保边滤波器使用某一种逐渐增强的参数,使得细节信息呢越来越少,但是边缘信息还是尽量保存。这个时候,前一层的结果减去后一层结果即为细节层,最后依次的保边滤波结果即为基础层,此时,由基础层再反向加上每一层的细节层即可以得到原始一模一样的数据。
这个呢,和早期的16位RAW图像处理一】:基于Fast Bilateral Filtering 算法的 High-Dynamic Range(HDR) 图像显示技术 相比,其实最大的区别就在于用了多层保边滤波器,而这个文章只用了一层。
同一些基于金字塔的的HDR相比呢,其核心区别是没有进行任何的下采样,而都是全图进行的。
那么要进行HDR到LDR的操作,总的来说就是一个要点,想办法调节细节层的信息,一个最简单的方法就是每个细节层乘以一个系数,在文章后续还描述了一些过程,针对不同的需求有不同的实现方式,不过我们去翻看matlab针对这个函数的核心代码,发现m处理的是相对来说非常简单的,我们摘取下他的核心部分代码:
1 % Compute log luminance
2 logLum = log(lum);
3
4 % Apply diffusion filter for multi-scale decomposition
5 % Compute detail layers
6