文档章节

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

abcijkxyz
 abcijkxyz
发布于 2016/11/22 16:40
字数 1915
阅读 10
收藏 0
点赞 0
评论 0

一、引言

本人初次接触HDR方面的知识,有描述不正确的地方烦请见谅。

为方便文章描述,引用部分百度中的文章对HDR图像进行简单的描述。

高动态范围图像(High-Dynamic Range,简称HDR),相比普通的图像,可以提供更多的动态范围和图像细节,根据不同的曝光时间的LDR(Low-Dynamic Range)图像,利用每个曝光时间相对应最佳细节的LDR图像来合成最终HDR图像,能够更好的反映人真实环境中的视觉效果。

现实真正存在的亮度差,即最亮的物体亮度,和最小的物体亮度之比为108, 而人类的眼睛所能看到的范围是105左右,但是一般的显示器,照相机能表示的只有256种不同的亮度,计算一般的显示器,照相机能表示的只有256种不同的亮度机在表示图象的时候是用8bit(256)级或16bit(65536)级来区分图象的亮度的,但这区区几百或几万无法再现真实自然的光照情况。HDR文件是一种特殊图形文件格式,它的每一个像素除了普通的RGB信息,还有该点的实际亮度信息。普通的图形文件每个象素只有0 -255的灰度范围,这实际上是不够的。想象一下太阳的发光强度和一个纯黑的物体之间的灰度范围或者说亮度范围的差别,远远超过了256个级别。因此,一张普通的白天风景图片,看上去白云和太阳可能都呈现是同样的灰度/亮度,都是纯白色,但实际上白云和太阳之间实际的亮度不可能一样,他们之间的亮度差别是巨大的。因此,普通的图形文件格式是很不精确的,远远没有纪录到现实世界的实际状况。而HDR格式则记录了很广范围内的亮度信息。

但是最终,HDR图像要在显示器中显示,还是需要对其数据进行处理的,如何处理即能充分利用这些数据,又能使得图像的显示尽量不丢失细节,是多年来不少图像工作者研究的重点。

简单的说,就是现在有一堆离散的数据,数据的分布范围可能很广,如何把这些离散的数据隐射到0到255之间。

二、相关算法的实现

最简单的当然是线性隐射,先算出离散数据的最大值和最小值,然后将数据线性的拉升至0到255之间,这种直接的操作往往无法得到满意的效果,会导致大量细节丢失,表现在视觉上就是一大块黑色或者一大块白色的,如下图所示:

      

     上面两幅图要么是暗部太暗,要么是亮部太亮,整体对比度太强,导致细节信息大量丢失。

     针对这一问题,很多人提出了不少相当不错的解决方案,比如基于全局操作符的,其中本文作者实现其中的基于快速双边滤波技术的HDR显示过程。

     本文对应的参考论文地址: Fast Bilateral Filtering for the Display of High-Dynamic-Range Images

     论文的细路很简单,首先他将原始的HDR数据分解成两个层:base layer 和 detail layer,然后降低base layer的对比度,不改变detail layer的数据,在将这两层合并。

     其中:base layer的数据用 HDR原始数据进行双边滤波获取。

     算法的简单流程入下所示:

    1、input intensity= 1/61*(R*20+G*40+B)

    2、r=R/(input intensity), g=G/input intensity, B=B/input intensity

    3、log(base)=Bilateral(log(input intensity))

    4、log(detail)=log(input intensity)-log(base)

    5、log (output intensity)=log(base)*compressionfactor+log(detail) - log_absolute_scale

    6、R output = r*10^(log(output intensity)), etc.

     上述过程中的变量compressionfactor,log_absolute_scale原文作者的建议取值为:

      compressionfactor = targetContrast/(max(log(base)) - min(log(base))) 对于很多图像,targetContrast使用log(5)能获得较为理想的值。

      而log_absolute_scale= max(log(base))*compressionfactor;

    在进行双边的时候,SigmaS一般取值为0.02*Max(Width,Height)比较合适,而SigmaR取值0.4较为理想(这里是指数据量化到了0-1之间的)。

  所以都取优化的参数,则上述过程可以自动进行。

    作者提到上述log操作都是以10为底进行的,我觉得以e为底实际效果也没啥区别的。

  三、效果

    按照这个思路编制程序后,确实能取得很不错的效果,比如上述两幅图像,按照前面讲的参数取值,解码后得到的图像如下:

     

    可见,图像的细节较为完美的体现出来了。

    当然,自动的参数不一定能调处最好的效果,比如还是这两幅图,手工选择一些参数,可以调出如下效果:

     

  特别是第一幅图,很有种蒙太奇的感觉。

    在看看几张长出现在论文中的图像的结果:

             

     

    

    

              线性解码图                                              双边滤波解码图

  有些图线性解码啥都看不到,双边滤波解码后细节表现的就很清晰了。

    HDR格式的原始数据的解码可以借助FreeImage来实现,FreeImage似乎已经讲这些数据量化到了0和1之间(不一定正确)。一段简单的实现代码如下:

public Bitmap LoadHdrFormFreeImage(string FileName)
{
    Bitmap Bmp = null;
    FREE_IMAGE_FORMAT fif = FREE_IMAGE_FORMAT.FIF_UNKNOWN; ;
    if (FreeImage.IsAvailable() == true)
    {
        fif = FreeImage.GetFileType(FileName, 0);
        if (fif != FREE_IMAGE_FORMAT.FIF_HDR)
        {
            MessageBox.Show("不是Hdr格式的图像.");
            return null;
        }
        fif = FreeImage.GetFIFFromFilename(FileName);
        FIBITMAP Dib = FreeImage.Load(fif, FileName, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
        uint Bpp = FreeImage.GetBPP(Dib);

        if (Bpp != 96)
        {
            MessageBox.Show("无法支持的Hdr格式.");
            FreeImage.Unload(Dib);
            return null;
        }
        uint Width = FreeImage.GetWidth(Dib);                        //  图像宽度
        uint Height = FreeImage.GetHeight(Dib);                      //  图像高度
        uint Stride = FreeImage.GetPitch(Dib);                       //  图像扫描行的大小,必然是4的整数倍
        IntPtr Bits = FreeImage.GetBits(Dib);

        float* Data = (float*)Bits;
        int Speed, Index;
        byte* Pixel;
        float Value;

        if (RawData != null) Marshal.FreeHGlobal((IntPtr)RawData);
        RawData = (float*)Marshal.AllocHGlobal((int)Width * (int)Height * 3 * sizeof(float));
        CopyMemory(RawData, Data, (int)Width * (int)Height * 3 * sizeof(float));

        Bmp = new Bitmap((int)Width, (int)Height, PixelFormat.Format24bppRgb);
        BitmapData BmpData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        Pixel = (byte*)BmpData.Scan0;

        for (int Y = 0; Y < Height; Y++)
        {
            Speed = Y * BmpData.Stride;
            Index = Y * (int)Width * 3;
            for (int X = 0; X < Width; X++)
            {
                Value = (Data[Index + 2] * 255);
                if (Value > 255)
                    Value = 255;
                else if (Value < 0)
                    Value = 0;
                Pixel[Speed] = (byte)Value;
                Value = (Data[Index + 1] * 255);
                if (Value > 255)
                    Value = 255;
                else if (Value < 0)
                    Value = 0;
                Pixel[Speed + 1] = (byte)Value;
                Value = (Data[Index + 0] * 255);
                if (Value > 255)
                    Value = 255;
                else if (Value < 0)
                    Value = 0;
                Pixel[Speed + 2] = (byte)Value;
                Index += 3;
                Speed += 3;
            }
        }
        FreeImage.Unload(Dib);
        Bmp.UnlockBits(BmpData);
        Bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
        return Bmp;
    }
    else
        return null;
}

  以上采用的是线性解码。

  附一个解码的调用程序:http://files.cnblogs.com/Imageshop/ReadHdrTest.rar 

     更多的源码可参考:http://people.csail.mit.edu/sparis/code/src/tone_mapping

                            http://people.csail.mit.edu/fredo/PUBLI/Siggraph2002/

     一些常见的用于测试的HDR图像可以从这里下载:http://www.pauldebevec.com/Research/HDR/

     同样,这种 tone mapping算法也可以用在普通的RGB图像上,效果如下所示:

     

              原图                                    增加base layer的对比度

    

             原图                                    降低base layer的对比度

   对于普通的整体偏暗的图像,该方式也能取得相当理想的效果,一些测试结果如下:

     

     

     

    很多其他的算法也能起到类似上述的效果,不过他们一般很容易产生halo现象。  

    相信对于偏亮的普通照片,也可以有同样的处理能力(未找到合适的测试图片)。

  

 

*********************************作者: laviewpbt   时间: 2013.11.18   联系QQ:  33184777  转载请保留本行信息************************

   

本文转载自:http://www.cnblogs.com/Imageshop/p/3428809.html

共有 人打赏支持
abcijkxyz
粉丝 60
博文 6196
码字总数 1876
作品 0
深圳
项目经理
海思Hi3516A(4)HDR模式开发

1. HDR概述 HDR(High-Dynamic Range)算法根据不同曝光的图片,合成最终HDR图片,比一般图片具有更宽的动态范围和图像细节。 一般HDR算法有两种:一种是基于不同曝光时间的连续几幅图片合现,...

shugenyin
2016/11/30
0
0
使用 OpenCV 进行高动态范围(HDR)成像

在本教程中,我们将学习如何使用由不同曝光设置拍摄的多张图像创建高动态范围High Dynamic Range(HDR)图像。 我们将以 C++ 和 Python 两种形式分享代码。 什么是高动态范围成像? 大多数数...

01%
06/17
0
0
opencv的C++类怎么引入

刚配置了OpenCV的软件环境,包括OpenCV2.4.6+VS2010和Opencv2.4.6+CodeBlocks11.04,都能显示出图像的测试程序,但是今天使用了官网提供的一个关于《High Dynamic Range Imaging¶》中的代码...

郑元春
2013/10/22
631
4
【GPU精粹与Shader编程】(三) 《GPU Gems 1》全书核心内容提炼总结 · 下篇

本文由@浅墨_毛星云 出品,首发于知乎专栏,转载请注明出处 文章链接: https://zhuanlan.zhihu.com/p/36499291 题图背景来自《神秘海域4》。 系列文章前言 《GPU Gems》1~3 、《GPU Pro》1...

zhmxy555
05/06
0
0
OpenGL——理解HDR与Bloom

学习资料链接 https://learnopengl-cn.github.io/05%20Advanced%20Lighting/06%20HDR/ https://learnopengl-cn.github.io/05%20Advanced%20Lighting/07%20Bloom/ HDR 一句话定义HDR:HDR是一......

wanghaodiablo
2017/12/13
0
0
Panorama Tools

Panorama Tools是德国数学家Helmut Dersch 发起的基于Java开发的一组全景播放软件,支持的有球形全景漫游、柱形全景漫游及HDR(high Dynamic Range)。其中大部分软件的协议是 GNU General Pu...

匿名
2008/11/04
3.2K
0
Fotoxx 10.7 发布,照片处理软件

Fotoxx 是一款 Linux 平台下用于处理照片的一个开源的自由软件,虽然不及大家熟知的“光影魔术手”的功能那么强大,但对于照片的日常上的简单处理还是足够了。可以进行简单的去 红眼,补光,...

红薯
2010/07/09
1K
0
【Unity3D技术文档翻译】第2.3篇 标准着色器 (Standard Shader)

上一章:【Unity3D技术文档翻译】第2.2篇 创建和使用材质 本章原文所在章节:【Unity Manual】→【Graphics】→【Graphics Overview】→【Materials, Shaders & Textures】→【Standard Shad...

何三思
05/28
0
0
假期不能错过的音视频领域技术进展

本文将带您回顾春节假期不可错过的音视频领域新闻和技术进展。 新的开源编码器XVC,AV1和HEVC之外的另外选项? 原文链接:https://mp.weixin.qq.com/s/rYtiGBCQx6RR85E8VptqCw 视频数据是目前...

LiveVideoStack
02/23
0
0
景不美,P 图软件补,自动修图系统背后的技术原理是什么?

研究人员们将推出一个能够按照专业摄影师的风格进行自动修图的新系统,分分钟拍大片。 如果你是个不会拍照的男孩子,恰好你的女友又是个喜欢拍照的姑娘,那么你之后的拍照水平可能会被疯狂吐...

图普科技
2017/08/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

组件及路由理论知识

一、 组件component 1. 什么是组件? 组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码组件是自定义元素(对象) 2. 定义组件的方式 方式1:先创建...

一个yuanbeth
刚刚
0
0
Saltstack配置之 nodegroups

#cd /etc/salt #mkdir master.d #vim node.conf //按组写入文件 nodegroups: client_all: 'L@192.168._._,192.168._._' clienta: 'L@192.168.192._' clientb: 'L@192.168.192._' #/etc/init......

硅谷课堂
7分钟前
0
0
expect(spawn) 自动化git提交和scp拷贝---centos(linux)

**在进行SCP文件拷贝中,往往需要进行用户密码的输入,即用户交互。若采用自动化脚本的方式进行,则可用以下方式: ** #!/usr/bin/expect #设置参数 set src [lindex $argv 0] set dest [lin...

helplove
11分钟前
1
0
用Build来构建对象的写法

如果一个类的属性过多,用构造器来构建对象很难写,因此我们时用Build方式来构建对象。写法大致如下。 import java.io.Serializable;import java.util.Date;public class Log impleme...

算法之名
13分钟前
11
0
利用 acme.sh 获取网站证书并配置https访问

acme.sh 实现了 acme 协议, 可以从 letsencrypt 生成免费的证书.(https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) 主要步骤: 安装 acme.sh 生成证书 copy 证书到 nginx/ap...

haoyuehong
26分钟前
2
0
微擎框架内如何根据media_id获取到微信图片的路径

微擎的框架内,图片选择后,获取的是那个字符串是media_id,相当于你这张图片在微信的图片服务器里面的id 要求是:获取https://mmbiz.qpic.cn/mmbiz_jpg/…… 微信图片的路径 而微信并没有根据m...

老bia同学
30分钟前
2
0
Spring boot中日期的json格式化

Model 在model层中,类的日期属性上面添加如下注解: @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss") 参考 Jackson Date格式化教程...

亚林瓜子
32分钟前
2
0
Eclipse:Failed to load the JNI shared library

1.问题背景: 由于我之前使用jdk1.9学习,当使用Luke的时候发现jdk版本过高,需要向下配置jdk,就向朋友拷了一个安装包。重新配置路径后,便开始报错。 2.问题描述: Failed to load the JNI...

tinder_boy
34分钟前
1
0
少儿学习编程课程是否真的适合七八岁的低龄儿童[图]

少儿学习编程课程是否真的适合七八岁的低龄儿童[图]: 天下熙熙皆为利来,天下攘攘皆为利往。 这几年来,乐高教育机构在国内如同雨后春笋般出现,当然关闭/转手的也很多。从教师角度来看,部...

原创小博客
40分钟前
1
0
ES12-词项查询

1.词项查询介绍 全文查询将在执行之前分析查询字符串,但词项级别查询将按照存储在倒排索引中的词项进行精确操作。这些查询通常用于数字,日期和枚举等结构化数据,而不是全文本字段。 或者,...

贾峰uk
47分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部